chenbhao Claude Opus 4.6 commited on
Commit
862182b
·
1 Parent(s): ab32188

feat: pass pixelWidth/pixelHeight from Image props to Kitty renderer

Browse files

Previously the test computed accurate pixel dimensions from the original
image's aspect ratio, but the prop chain never forwarded them through
ImageComponentProps -> ImageRenderer -> KittyImage -> useImage, so
KittyImage always computed pixels from resolved chars × cell size (losing
aspect ratio information). Now the full chain forwards pixelWidth/
pixelHeight as overrides, letting the test control exact pixel scaling
while width/height still drive Ink layout and Kitty placement bounds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

src/ink-picture/__tests__/LocalPicture.test.tsx CHANGED
@@ -40,7 +40,7 @@ function App() {
40
  const cols = process.stdout.columns ?? 80;
41
 
42
  // 1. 目标字符尺寸
43
- const targetW_chars = Math.floor(cols * 0.6);
44
 
45
  // 2. 转为像素尺寸(用于图片缩放)
46
  const targetW_pixels = targetW_chars * CELL_WIDTH;
 
40
  const cols = process.stdout.columns ?? 80;
41
 
42
  // 1. 目标字符尺寸
43
+ const targetW_chars = Math.floor(cols * 0.4);
44
 
45
  // 2. 转为像素尺寸(用于图片缩放)
46
  const targetW_pixels = targetW_chars * CELL_WIDTH;
src/ink-picture/components/image/Kitty.tsx CHANGED
@@ -18,7 +18,7 @@ import type { ImageProps } from "./protocol.js";
18
  function KittyImage(props: ImageProps) {
19
  const terminalInfo = useTerminalInfo();
20
  const { stdout } = useStdout();
21
- const { src, width, height, alt } = props;
22
 
23
  const { containerRef, resolvedWidth, resolvedHeight } = useMeasuredSize(
24
  width,
@@ -27,13 +27,14 @@ function KittyImage(props: ImageProps) {
27
 
28
  const componentPosition = usePosition(containerRef);
29
 
30
- const pixelWidth = resolvedWidth * (terminalInfo?.cellWidth ?? 0);
31
- const pixelHeight = resolvedHeight * (terminalInfo?.cellHeight ?? 0);
 
32
 
33
  const { imageData, error } = useImage({
34
  src,
35
- pixelWidth,
36
- pixelHeight,
37
  mode: "png",
38
  });
39
 
@@ -118,6 +119,7 @@ function KittyImage(props: ImageProps) {
118
  ref={containerRef}
119
  width={width}
120
  height={height}
 
121
  alt={alt}
122
  error={error}
123
  loaded={!!imageId}
 
18
  function KittyImage(props: ImageProps) {
19
  const terminalInfo = useTerminalInfo();
20
  const { stdout } = useStdout();
21
+ const { src, width, height, pixelWidth, pixelHeight, alt } = props;
22
 
23
  const { containerRef, resolvedWidth, resolvedHeight } = useMeasuredSize(
24
  width,
 
27
 
28
  const componentPosition = usePosition(containerRef);
29
 
30
+ // Use external pixel dimensions if provided, otherwise compute from chars
31
+ const actualPixelWidth = pixelWidth ?? resolvedWidth * (terminalInfo?.cellWidth ?? 0);
32
+ const actualPixelHeight = pixelHeight ?? resolvedHeight * (terminalInfo?.cellHeight ?? 0);
33
 
34
  const { imageData, error } = useImage({
35
  src,
36
+ pixelWidth: actualPixelWidth,
37
+ pixelHeight: actualPixelHeight,
38
  mode: "png",
39
  });
40
 
 
119
  ref={containerRef}
120
  width={width}
121
  height={height}
122
+ imageHeight={actualPixelHeight}
123
  alt={alt}
124
  error={error}
125
  loaded={!!imageId}
src/ink-picture/components/image/index.tsx CHANGED
@@ -44,6 +44,8 @@ function Image({
44
  getVisibility,
45
  width = "100%",
46
  height = "100%",
 
 
47
  ...props
48
  }: ImageComponentProps) {
49
  const isScreenReaderEnabled = useIsScreenReaderEnabled();
@@ -121,6 +123,8 @@ function Image({
121
  key={effectiveProtocol}
122
  width={resolvedWidth}
123
  height={resolvedHeight}
 
 
124
  {...props}
125
  />
126
  </Box>
 
44
  getVisibility,
45
  width = "100%",
46
  height = "100%",
47
+ pixelWidth,
48
+ pixelHeight,
49
  ...props
50
  }: ImageComponentProps) {
51
  const isScreenReaderEnabled = useIsScreenReaderEnabled();
 
123
  key={effectiveProtocol}
124
  width={resolvedWidth}
125
  height={resolvedHeight}
126
+ pixelWidth={pixelWidth}
127
+ pixelHeight={pixelHeight}
128
  {...props}
129
  />
130
  </Box>
src/ink-picture/components/image/protocol.ts CHANGED
@@ -13,6 +13,10 @@ export interface ImageProps {
13
  height: number | string;
14
  /** Alternative text displayed while loading or on error */
15
  alt?: string;
 
 
 
 
16
  }
17
 
18
  /**
 
13
  height: number | string;
14
  /** Alternative text displayed while loading or on error */
15
  alt?: string;
16
+ /** Override pixel width for image scaling (default: resolved from width) */
17
+ pixelWidth?: number;
18
+ /** Override pixel height for image scaling (default: resolved from height) */
19
+ pixelHeight?: number;
20
  }
21
 
22
  /**