Files
SlabUploader/docs/capabilities/CAPTURE.md
T
grokbot_ty 1b5ad112cc fix(capture): warn 300–799px PNG floor; hard-block only below 300
Split FLOOR_WARN_PX=800 / FLOOR_BLOCK_PX=300. Warn-band still encodes and
includes the photo (Photos-ready + batchApply ok+warn). Block excludes
siblings and clean cal. CAPTURE-105 / CAPTURE.md / PHOTOS.md updated.
2026-09-26 09:11:34 -07:00

8.2 KiB
Raw Blame History

Milestone 1 — Capture

Runs in the browser on phone and PC as ordinary client code. No inference URL. No model. No backend. Mask, rectangle, measurements, crop, and PNG encode are deterministic functions of the photo and user inputs.

Milestone 1 uses one reference photo; Milestone 2 adds the batch. Milestone 1 ends when the user sees the inventory PNG and measurements. Milestone 2 is Photos (docs/capabilities/PHOTOS.md); Milestone 3 is Create (docs/capabilities/CREATE.md). This file does not create a WooCommerce product.

Requirements impact

Requirement Impact
CAPTURE-5, CAPTURE-135, CAPTURE-140 deterministic client core; server stores, never recomputes
CAPTURE-10 supported clients and hard stop
CAPTURE-20, CAPTURE-35 sheet setup and detection
CAPTURE-40, CAPTURE-41, CAPTURE-45, CAPTURE-50, CAPTURE-55 mask controls, sensitivity, live re-run, overlay, retake
CAPTURE-60, CAPTURE-65 length axis
CAPTURE-70, CAPTURE-75, CAPTURE-80, CAPTURE-85, CAPTURE-90 inputs and measure math
CAPTURE-95, CAPTURE-100, CAPTURE-105 inventory PNG
CAPTURE-141, CAPTURE-145, CAPTURE-150, CAPTURE-155, CAPTURE-160 preview, knobs, failure, rounding
CAPTURE-25, CAPTURE-115 calibration photo is the measurement reference
APP-10 device draft and resume
QUALITY-40, QUALITY-45, QUALITY-55, QUALITY-60, QUALITY-65, QUALITY-70, QUALITY-75, QUALITY-80, QUALITY-85, QUALITY-100 deterministic tests and vectors

Setup

Photograph the slab on a green or black sheet.

  • Sheet fills the frame around the slab.
  • Slab is fully on the sheet.
  • First photo is top-down, lens parallel to the face.

The app expects that sheet. Background removal keys green or black. Other backgrounds are out of Milestone 1.

Use case

If a device draft exists:

  • App opens Resume.
  • User chooses Continue or Start fresh.
  • Continue: app restores the last approved state.
  • Start fresh: app discards the draft and opens Add photo.

Otherwise the app opens Add photo.

  1. User adds one photo taken under Setup.
  2. App decodes the photo and opens Mask. App keys green or black and shows an overlay: slab stays the photograph; removed pixels are a light gray checkerboard.
  3. User sets sheet Auto / Green / Black and sensitivity 0–100 (slider or minus / plus). App updates the control immediately. App recomputes the overlay 2.0 seconds after the last sensitivity change. User adjusts until only the slab remains, then approves. App blocks approve if the mask has no slab pixels; user retakes. The approved mask is the footprint for every later step.
  4. App draws the minimum-area bounding rectangle of the mask and the length axis on the long side of that rectangle. User rotates the axis if it does not follow the slab length, then approves the axis.
  5. User enters length L in inches (1/8 in steps) and thickness (1/8 in steps), then presses Calculate.
  6. App sets scale = longest_axis_px / L (mask/wood span along the approved direction ÷ user L; rectangle is direction only).
  7. App computes widths, sqft, and bdft from the mask. App crops the masked slab into a 3:4 portrait frame: slab centered, 90% fill at the widest and tallest points, background transparent. App writes that frame as an inventory PNG (image/png, 8-bit RGBA).
  8. User sees the transparent PNG and the numbers. Milestone 1 stops here.

Calculate does not create a WooCommerce product.

Browsers

Phone: iOS Safari, Android Chrome. PC: Chrome, Edge, Firefox. Other clients get a hard stop.

States

One photo component is reused. Each state advances on approve. Back returns to the previous state. A device draft restores the last approved state.

  1. Resume — only when a device draft exists. Continue or Start fresh.
  2. Add photo — camera or picker. One photo. Setup rules visible.
  3. Mask — background removal on that photo.
  4. Length axis — bounding rectangle and long-side axis on the same photo.
  5. Measure — length, thickness, Calculate, crop, inventory PNG, widths, sqft, bdft. Milestone 1 stops here.

Display

Preview fits the device width. Height is capped so Mask and Measure controls stay on screen. Phone and PC use the same states.

The preview is display only. Mask, rectangle, crop, scale, sqft, and PNG encode use the source photo pixels, not the CSS size of the preview.

Runtime

Browser APIs: createImageBitmap, canvas / OffscreenCanvas, Web Worker, convertToBlob({ type: "image/png" }), IndexedDB. idb-keyval may wrap IndexedDB. No OpenCV, ONNX, U2Net, or image-editor kit. Sensitivity 0–100 maps to green chroma tightness and black brightness cutoff in the worker.

Mask

Overlay: slab remains the photograph. Removed pixels are a light gray checkerboard.

Controls on this state, with the photo visible:

  • Sheet: Auto, Green, or Black
  • Sensitivity: 0–100, step 1. Slider with minus and plus on each side. Button hit targets sized for a thumb.

The control value updates immediately. The overlay recomputes 2.0 seconds after the last sensitivity change. A sheet change may recompute on the change.

Mask work runs in the worker. The last good overlay stays visible while a pass runs. Show a busy mark only if a pass lasts more than a fraction of a second. If a pass fails, keep the last overlay; the user may retake.

Approve is blocked when the mask has no slab pixels. User retakes.

User approves the mask when only the slab remains. That mask is the footprint for Length axis, crop, measurements, and the inventory PNG.

Length axis

On the same photo, keep the approved mask in view and draw the minimum-area bounding rectangle of the mask with the length axis on the long side of that rectangle. User rotates the rectangle (slider with minus and plus) until that direction follows the slab length, then approves the axis.

Measure

User enters length L in inches (1/8 in steps) and thickness (1/8 in steps), then presses Calculate.

  • scale = longest_axis_px / L where longest_axis_px is the mask/wood span along the approved length direction (slab pixels end-to-end on that axis), not the rectangle edge length. The rectangle sets direction only; user-entered L is wood end→end along that direction.
  • Widths: min, max, avg from samples taken every 6 in along the approved length axis, perpendicular to it, after dropping the first and last 6 in of the span (bulk widths, not tips). If L ≤ 12 in there are no interior stations and all three are 0.
  • sqft = (mask_pixels / scale²) / 144 (2 decimals)
  • bdft = sqft × thickness_in (2 decimals)
  • Crop: 3:4 portrait, slab centered, 90% fill at the widest and tallest points, transparent background
  • File: inventory PNG, image/png, 8-bit RGBA, alpha kept

User sees the transparent PNG and those numbers. Stop. Calculate does not create a WooCommerce product.

Crop

On Calculate, the app builds the inventory image from the approved mask:

  1. Keep slab pixels from the source photo. Removed pixels are transparent.
  2. Place the slab in a 3:4 portrait frame, centered.
  3. Scale so the widest and tallest points of the slab fill 90% of the frame. Extra margin where the slab is narrower.
  4. After that crop, shorter side targets ≥ 800px when the source can supply it. If the slab bbox shorter side is 300–799 px, warn but still encode and include the photo. Below 300 px is a hard block (exclude / retake). No upscale from an undersized source.
  5. Encode as PNG with alpha.

Device draft

One in-progress slab is stored on the device. This is not a WooCommerce draft.

On open or refresh, if that draft exists, the app opens in Resume.

  • Continue restores the last approved state, including Measure.
  • Start fresh discards the device draft and opens Add photo.

Milestone 3 clears the device draft after Woo create.

Inventory PNG

The calibration photo is the measurement reference (CAPTURE-25, CAPTURE-115). Filename is an implementation detail.

Property Value
Format PNG, 8-bit RGBA (image/png)
Alpha Kept through encode and upload
Aspect 3:4 portrait
Layout Slab centered, 90% fill at the widest and tallest points
Size After crop, shorter side targets ≥ 800px when the source can supply it

Shorter side 300–799 px: warn but still encode/include. Below 300 px: hard block (exclude / retake). No upscale from an undersized source.