MCPcopy Create free account
hub / github.com/heygen-com/hyperframes / mapPointToImagePixel

Function mapPointToImagePixel

packages/sdk/src/adapters/iframe.ts:117–182  ·  view source on GitHub ↗
(
  rect: { left: number; top: number; width: number; height: number },
  natural: { width: number; height: number },
  objectFit: string,
  objectPosition: string,
  point: { x: number; y: number },
)

Source from the content-addressed store, hash-verified

115 */
116// fallow-ignore-next-line complexity
117export function mapPointToImagePixel(
118 rect: { left: number; top: number; width: number; height: number },
119 natural: { width: number; height: number },
120 objectFit: string,
121 objectPosition: string,
122 point: { x: number; y: number },
123): { px: number; py: number } | null {
124 // Local coords within the CSS box
125 const lx = point.x - rect.left;
126 const ly = point.y - rect.top;
127
128 if (lx < 0 || ly < 0 || lx > rect.width || ly > rect.height) return null;
129
130 const fit = objectFit || "fill";
131
132 // For fill (or unrecognized values): the natural image is stretched to the
133 // box; direct linear mapping.
134 if (fit !== "cover" && fit !== "contain" && fit !== "none") {
135 if (rect.width === 0 || rect.height === 0) return null;
136 const px = Math.floor((lx / rect.width) * natural.width);
137 const py = Math.floor((ly / rect.height) * natural.height);
138 return { px: clamp(px, 0, natural.width - 1), py: clamp(py, 0, natural.height - 1) };
139 }
140
141 // For none: image is drawn at its natural size; no scaling.
142 if (fit === "none") {
143 const pos = parseObjectPosition(objectPosition, rect, natural);
144 const ox = pos.x;
145 const oy = pos.y;
146 const px = Math.floor(lx - ox);
147 const py = Math.floor(ly - oy);
148 if (px < 0 || py < 0 || px >= natural.width || py >= natural.height) return null;
149 return { px, py };
150 }
151
152 // cover: scale uniformly so the image covers the box; may clip edges.
153 // contain: scale uniformly so the image fits within the box; may letterbox.
154 if (natural.width === 0 || natural.height === 0) return null;
155 const scaleX = rect.width / natural.width;
156 const scaleY = rect.height / natural.height;
157 const scale = fit === "cover" ? Math.max(scaleX, scaleY) : Math.min(scaleX, scaleY);
158
159 const renderedW = natural.width * scale;
160 const renderedH = natural.height * scale;
161
162 const pos = parseObjectPosition(objectPosition, rect, {
163 width: renderedW,
164 height: renderedH,
165 });
166
167 // Offset of the rendered image's top-left within the CSS box
168 const imgLeft = pos.x;
169 const imgTop = pos.y;
170
171 // Local coords relative to the rendered image's top-left
172 const rx = lx - imgLeft;
173 const ry = ly - imgTop;
174

Callers 2

imageAlphaOpaqueAtFunction · 0.85
iframe.test.tsFile · 0.85

Calls 2

clampFunction · 0.70
parseObjectPositionFunction · 0.70

Tested by

no test coverage detected