Resources Numerical accuracy Calculation policy

Pictures: size, placement and clip

Works out where a picture's corners lie, its pixel size when attached or pasted, and its clip boundary in pixel coordinates for saving.

How the precision is kept

A picture is held as a corner, two pixel vectors and its pixel counts, all 64-bit numbers. Corners, pixel size and the two-point rescale are single products, sums and divisions. Clip points are solved back to pixel coordinates by a 2 × 2 determinant.

Calculations under this policy

6 calculations in 2 source files. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.

pictures.js CadCraft 0.8.2 64-bit 3 calculations Reviewed

Tests bin/test-cadcraft.mjs

Picture corners

64-bit

The four corners of a picture in its block's coordinates.

W = u × w; H = v × h; corners = p, p + W, p + W + H, p + H

Products of a pixel vector and a whole pixel count, then sums; nothing is rounded.

  • pictures.js
  • lines 38 to 42
  • CadCraft 0.8.2
/** A picture's four corners in its block's coordinates (lower-left, lower-right, upper-right, upper-left). */
export function picCorners(pic) {
  const W = { x: pic.ux * pic.w, y: pic.uy * pic.w }, H = { x: pic.vx * pic.h, y: pic.vy * pic.h };
  return [{ x: pic.x, y: pic.y }, { x: pic.x + W.x, y: pic.y + W.y }, { x: pic.x + W.x + H.x, y: pic.y + W.y + H.y }, { x: pic.x + H.x, y: pic.y + H.y }];
}

Picture placement and clip for saving

64-bit

The insertion point, pixel vectors and clip boundary a DWG image record holds.

det = u × v; a = (d × v) ÷ det; b = (u × d) ÷ det; pixel = (a − 0.5, h − 0.5 − b)

The pixel vectors go through the reference's 2 × 2 matrix. Clip points are solved by Cramer's rule; the clip is left out only when |det| ≤ 1e-300, so a picture squeezed nearly flat divides by a very small determinant.

  • pictures.js
  • lines 77 to 101
  • CadCraft 0.8.2
/**
 * A reference to a picture block → what a DWG's IMAGE holds: { file, insert, u, v, size, clip? (pixel coordinates, y down
 * from the top-left pixel's centre, as the file keeps them), fade, transparent? } in the reference's space, or null when the block is
 * not a picture (anything besides its frame and name in it).
 */
export function picturePlacement(ref, block) {
  const fr = pictureFrame(block);
  if (!fr || fr.ole || block.entities.some((e) => e !== fr && !e.picName)) return null;   // an OLE object's preview is drawn like a picture but is no IMAGE (ole.js, 0.7 D7.23)
  const p = fr.pic, m = insertMatrix(ref, block);
  const at = mApply(m, { x: p.x, y: p.y });
  const vec = (x, y) => ({ x: m[0] * x + m[2] * y, y: m[1] * x + m[3] * y });
  const u = vec(p.ux, p.uy), v = vec(p.vx, p.vy);
  const out = { file: p.file, insert: at, u, v, size: { x: p.w, y: p.h }, fade: Number.isFinite(p.fade) ? p.fade : 0, ...(p.transparent ? { transparent: true } : {}) };
  if (p.clipped) {
    const det = u.x * v.y - u.y * v.x;
    if (Math.abs(det) > 1e-300) {
      out.clip = fr.pts.map((q) => {
        const w = mApply(m, q), dx = w.x - at.x, dy = w.y - at.y;
        const a = (dx * v.y - dy * v.x) / det, b = (u.x * dy - u.y * dx) / det;   // along the width, up, in pixels
        return { x: a - 0.5, y: p.h - 0.5 - b };
      });
    }
  }
  return out;
}

Pixel size of a picture in a PDF

64-bit

How many pixels a PNG keeps when a plot caps its resolution.

w₂ = round(maxDpi × mm ÷ 25.4), at least 1

25.4 mm per inch is the exact definition. The picture is shrunk only when both target sizes are smaller than its own; a JPEG is never resampled.

  • pictures.js
  • lines 258 to 260
  • CadCraft 0.8.2
if (maxDpi > 0 && mmW > 0 && mmH > 0) {
  const w2 = Math.max(1, Math.round(maxDpi * mmW / 25.4)), h2 = Math.max(1, Math.round(maxDpi * mmH / 25.4));
  if (w2 < img.w && h2 < img.h) { img = shrink(img, w2, h2); shrunk = true; }
pictures-cmd.js CadCraft 0.8.2 64-bit 3 calculations Reviewed

Tests bin/test-cadcraft.mjs

Pixel size when attaching

64-bit

The size of one pixel in drawing units from the width typed for the picture.

px = W ÷ pixel width

One division. Both pixel vectors use the same value, so pixels are square; with no width typed one pixel is one drawing unit.

  • pictures-cmd.js
  • lines 49 to 50
  • CadCraft 0.8.2
const px = W / rec.w;
const pic = { file: rec.name, x: 0, y: 0, ux: px, uy: 0, vx: 0, vy: px, w: rec.w, h: rec.h };

Inverse of a placement

64-bit

Takes clip points picked in the drawing back into the picture block's coordinates.

det = a·d − b·c; inverse = [d −b −c a (c·f − d·e) (b·e − a·f)] ÷ det

Six divisions by the determinant, which is not checked for zero.

  • pictures-cmd.js
  • lines 28 to 31
  • CadCraft 0.8.2
const invert = (m) => {
  const d = m[0] * m[3] - m[1] * m[2];
  return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[3] * m[4]) / d, (m[1] * m[4] - m[0] * m[5]) / d];
};

Rescaling a pasted area by two points

64-bit

Resizes a pasted picture so two picked points are a stated distance apart.

f = wanted ÷ |b − a|; sx′ = sx·f; sy′ = sy·f

Points closer than 1e-9 drawing units, an absolute limit, are refused. Otherwise one division and two multiplications; the corner stays where it was put.

  • pictures-cmd.js
  • lines 158 to 165
  • CadCraft 0.8.2
const cur = b && !b.option ? Math.hypot(b.x - a.x, b.y - a.y) : 0;
if (b && !b.option && !(cur > 1e-9)) c.print(t('scan.scale.same'));
const want = cur > 1e-9 ? await c.distance(t('scan.prompt.scale3', { d: fmt(cur) }), { base: a }) : null;
const ref = c.doc.get(r.id);
if (ref && typeof want === 'number' && want > 0) {
  const f = want / cur;
  c.doc.change('PASTEAREA', () => c.doc.update(ref.id, { ...ref, sx: ref.sx * f, sy: ref.sy * f }));
  width *= f;

In detail

Method
Affine placement by two pixel vectors; Cramer's rule for the clip; 2 × 3 matrix inverse by the determinant.
Number types
64-bit numbers; pixel counts are whole numbers read from the file header.
Tolerances
Clip solved only when |det| > 1e-300 (absolute). Two picked points closer than 1e-9 drawing units (absolute) are refused in the paste rescale.
Limits
The inverse used for clip points divides by a determinant that is not checked for zero.

Approach: 64-bit, direct

Every value is a 64-bit number from input to result. Formulas are closed form or a direct solve, and every comparison uses a stated tolerance.

Every policy that takes this approach