Commit 9f75a14
Implement image resize search with bisect (commontoolsinc#2056)
* Add maxSizeBytes auto-compression to ct-image-input
Add optional client-side image compression for LLM API size limits:
**New Property**:
- `maxSizeBytes?: number` - Optional max size before compression
- Only compresses if set and file exceeds limit
- Falls back to original if compression fails
**Compression Strategy**:
- Uses Canvas API (OffscreenCanvas for performance)
- Tries 9 progressive size/quality combinations:
- 2048px @ 85% quality → 800px @ 50% quality
- Stops when under size limit
- Logs compression results for debugging
**Implementation**:
- `_compressImage()`: Robust compression with fallback
- Preserves original filename
- Updates size metadata to reflect compressed size
- JPEG output for broad compatibility
**Use Case**:
Anthropic vision API has 5MB limit per image. Setting maxSizeBytes={4_500_000} ensures images compress automatically before upload.
**Example**:
```typescript
<ct-image-input
maxSizeBytes={4500000}
multiple
maxImages={5}
buttonText="📷 Scan Signs"
/>
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
* Add maxSizeBytes to CTImageInputAttributes types
Update JSX type definitions for new compression property
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
* Optimize image compression with binary search algorithm
Replace linear scan through 9 predefined quality/dimension combinations
with an intelligent binary search approach:
- Binary search on quality values (0.5-0.95) for each dimension level
- Tries dimensions in descending order: 2048, 1600, 1200, 800
- Returns as soon as optimal compression is found
- More efficient: typically 3-4 compressions per dimension vs 9 total
- Better quality: finds optimal quality dynamically instead of using
predefined values
This reduces compression time while maintaining or improving output quality.
* Refactor: Extract image compression logic into utility module
Move the binary search image compression algorithm from ct-image-input
component into a reusable utility module:
- Created packages/ui/src/v2/utils/image-compression.ts with:
- compressImage() function with configurable options
- formatFileSize() helper function
- CompressionResult interface with detailed metadata
- CompressionOptions interface for customization
Benefits:
- Reusability: Other components can now use image compression
- Testability: Logic can be tested independently
- Separation of concerns: UI component focuses on presentation
- Maintainability: Algorithm improvements benefit all consumers
- Type safety: Proper TypeScript interfaces and return types
The ct-image-input component now delegates to the utility while
maintaining the same compression behavior and logging.
* Fix lint
* Fix logic so it works at runtime
* Trim console.log output
* Clarify intended logic
* Fix logic
* Respond to feedback
---------
Co-authored-by: Alex Komoroske <[email protected]>
Co-authored-by: Claude <[email protected]>1 parent 91f4d30 commit 9f75a14
File tree
4 files changed
+314
-36
lines changed- packages
- html/src
- ui/src/v2
- components/ct-image-input
- utils
4 files changed
+314
-36
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3162 | 3162 | | |
3163 | 3163 | | |
3164 | 3164 | | |
| 3165 | + | |
3165 | 3166 | | |
3166 | 3167 | | |
3167 | 3168 | | |
| |||
Lines changed: 80 additions & 36 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
15 | 19 | | |
16 | 20 | | |
17 | 21 | | |
| |||
68 | 72 | | |
69 | 73 | | |
70 | 74 | | |
| 75 | + | |
71 | 76 | | |
72 | 77 | | |
73 | 78 | | |
| |||
83 | 88 | | |
84 | 89 | | |
85 | 90 | | |
| 91 | + | |
| 92 | + | |
86 | 93 | | |
87 | 94 | | |
88 | 95 | | |
| |||
219 | 226 | | |
220 | 227 | | |
221 | 228 | | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
222 | 232 | | |
223 | 233 | | |
224 | 234 | | |
| |||
307 | 317 | | |
308 | 318 | | |
309 | 319 | | |
310 | | - | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
311 | 366 | | |
312 | 367 | | |
313 | | - | |
314 | 368 | | |
315 | 369 | | |
316 | | - | |
317 | | - | |
318 | | - | |
319 | | - | |
320 | | - | |
321 | | - | |
322 | | - | |
323 | | - | |
324 | | - | |
325 | | - | |
326 | | - | |
327 | | - | |
328 | | - | |
329 | | - | |
330 | | - | |
331 | | - | |
332 | | - | |
333 | | - | |
334 | | - | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
335 | 385 | | |
336 | 386 | | |
337 | | - | |
338 | | - | |
339 | | - | |
| 387 | + | |
| 388 | + | |
340 | 389 | | |
341 | | - | |
342 | | - | |
343 | | - | |
344 | | - | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
345 | 395 | | |
346 | 396 | | |
347 | 397 | | |
348 | 398 | | |
349 | 399 | | |
350 | 400 | | |
351 | | - | |
| 401 | + | |
352 | 402 | | |
353 | 403 | | |
354 | 404 | | |
| |||
360 | 410 | | |
361 | 411 | | |
362 | 412 | | |
363 | | - | |
364 | | - | |
365 | | - | |
366 | | - | |
367 | | - | |
368 | | - | |
369 | 413 | | |
370 | 414 | | |
371 | 415 | | |
| |||
452 | 496 | | |
453 | 497 | | |
454 | 498 | | |
455 | | - | |
| 499 | + | |
456 | 500 | | |
457 | 501 | | |
458 | 502 | | |
| |||
0 commit comments