Skip to content

Add classify, thumb_hash, perceptual_hash, crop_objects and preserve_hdr support - #93

Open
11bit wants to merge 5 commits into
mainfrom
add-classification-hashes-crop-objects-preserve-hdr
Open

Add classify, thumb_hash, perceptual_hash, crop_objects and preserve_hdr support#93
11bit wants to merge 5 commits into
mainfrom
add-classification-hashes-crop-objects-preserve-hdr

Conversation

@11bit

@11bit 11bit commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Closes #82
Closes #94

Upstream:

Adds the five options that the Usage docs gained in those ranges.

Image info options (generateImageInfoUrl)

classify / cl

  • top_k — required, integer >= 0. When greater than zero, imgproxy classifies the image and returns the top K classes with the highest confidence scores.
  • class_names — optional; if given, imgproxy classifies only those classes.
generateImageInfoUrl(url, { classify: { top_k: 2, class_names: ["Bus", "Person"] } });
// -> /cl:2:Bus:Person/plain/...

thumb_hash / th — boolean; returns the image's ThumbHash.

perceptual_hash / phash / ph — boolean; returns the perceptual hash of the image.

generateImageInfoUrl(url, { thumb_hash: 1, perceptual_hash: true });
// -> /ph:t/th:t/plain/...

Processing options (generateUrl)

crop_objects / c_obj (PRO)

  • scale_factor — required, number >= 0. 1.0 crops exactly to the detected objects, 1.2 adds 20% padding.
  • class_names — optional; if omitted, imgproxy crops to all the detected objects.

preserve_hdr / ph — boolean; overrides IMGPROXY_PRESERVE_HDR.

generateUrl(url, { crop_objects: { scale_factor: 1.2, class_names: ["face"] }, preserve_hdr: 1 });
// -> /c_obj:1.2:face/ph:t/plain/...

On the coc_obj rename

The crop_objects docs first landed with co as the short keyword, which collided with contrast — supporting both would have broken contrast (its build runs earlier and would throw on a CropObjects object) and made co unusable in the Options type. Upstream has since renamed the keyword to c_obj (#94), so this PR accepts crop_objects and c_obj and emits c_obj:. contrast keeps co and the two now coexist:

generateUrl(url, { contrast: 1.5, c_obj: { scale_factor: 2 } });
// -> /co:1.5/c_obj:2/plain/...

ph means perceptual_hash in image info URLs and preserve_hdr in processing URLs. That follows an established imgproxy convention — a is adjust or alpha, s is size or file size, f is output format or detected format — and this package already models s and f that way, so both keys are simply supported in their own namespace.

Out of scope in those compare ranges

docs/configuration/options.mdx, docs/features/*, docs/image_formats_support.mdx, docs/image_sources/*, docs/installation.mdx, docs/memory_usage_tweaks.mdx, docs/monitoring/* — server configuration and feature manuals, not URL options. docs/cache/**, versioned_docs/**, sidebars.ts, docusaurus.config.ts and versions.json — docs-site restructuring and version snapshots.

npm run lint, npm run check-types, npm run test -- --run (1237 tests) and npm run build all pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WQMVmChgR1GbXkCdrkFS4S

11bit and others added 5 commits August 24, 2026 18:50
…hdr support

Covers the imgproxy Usage docs update from issue #82.

Image info options: classify (cl), thumb_hash (th) and
perceptual_hash (phash, ph).

Processing options: crop_objects (PRO) and preserve_hdr (ph).

The docs list `co` as the short keyword of crop_objects, but `co` is
already the short keyword of the contrast option, so only the full
`crop_objects` keyword is supported. The emitted segment is still `co:`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WQMVmChgR1GbXkCdrkFS4S
The imgproxy docs listed `co` as the short keyword of `crop_objects`, which
collided with the `contrast` option. Upstream resolved it by renaming the
keyword to `c_obj`, so accept both `crop_objects` and `c_obj`, and emit
`c_obj:` instead of `co:`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WQMVmChgR1GbXkCdrkFS4S
Reusing a keyword across the processing and image info namespaces is an
established imgproxy convention: `a` means adjust or alpha, `s` means size
or file size, and `f` means output format or detected format, depending on
the URL kind. `ph` is no different, and neither `size` nor `format` warns
about its counterpart, so the notes were inconsistent noise.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WQMVmChgR1GbXkCdrkFS4S
Both options called .join(":") on whatever was passed, so a vanilla-JS
consumer passing `class_names: "face"` got a raw `TypeError: class_names.join
is not a function` instead of the library's guard-style error.

guardIsNotArray can't be used as-is here: it rejects empty arrays, and an
empty class_names is meaningful — it behaves like an omitted one, meaning
all detected classes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WQMVmChgR1GbXkCdrkFS4S
Replaces the hand-rolled Array.isArray checks in crop_objects and classify
with the shared guard, so the message goes through getParamName like every
other array option.

guardIsNotArray gains an optional allowEmpty flag, matching the shape of
guardIsNotStr's isHex flag. It defaults to off, so the eight existing call
sites keep rejecting empty arrays; only the two optional class_names lists
opt in, since an empty one means "all detected classes".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WQMVmChgR1GbXkCdrkFS4S
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Usage docs of imgproxy have been updated Usage docs of imgproxy have been updated

1 participant