diff --git a/agent.md b/agent.md index 062be68..cec46a7 100644 --- a/agent.md +++ b/agent.md @@ -188,7 +188,7 @@ There are three selectable data sources: - Source discovery: use manufacturer mapping from Local scrape DB and show exactly which source produced each candidate. - Browser scraping: use the configured browser engine per source and keep the UI responsive while scraping runs. - Image extraction: collect original image URLs, dimensions, mime type, file size and source page URL. -- Image quality: show a clear warning for any picture candidate smaller than `800 x 800`; small thumbnails must remain visible for review but must be marked as not production-ready. +- Image quality: product pictures will later be normalized to a `1:1` square, so a portrait/landscape image may be production-ready even when one side is below `800px` (for example `739 x 1435`). Mark images as too small only when the longest side is below `800px`; otherwise show the real size and note when it is OK for `1:1` crop. - Duplicate detection: calculate `sha256` for exact duplicates and perceptual hash for visually similar images. - Target assignment: propose whether pictures belong to `color`, `size`, `combination` or `manual` target, then learn from user corrections. - Persistence: save picture blobs, candidates, hashes, source metadata and learned rules only into Local scrape DB. diff --git a/public/app.js b/public/app.js index 3cdc872..9170fe5 100644 --- a/public/app.js +++ b/public/app.js @@ -912,11 +912,15 @@ function renderPictureCandidates(items) { row.classList.remove("is-too-small"); return; } - const isTooSmall = image.naturalWidth < MIN_PRODUCT_PICTURE_SIZE || image.naturalHeight < MIN_PRODUCT_PICTURE_SIZE; + const shortestSide = Math.min(image.naturalWidth, image.naturalHeight); + const longestSide = Math.max(image.naturalWidth, image.naturalHeight); + const isTooSmall = longestSide < MIN_PRODUCT_PICTURE_SIZE; row.classList.toggle("is-too-small", isTooSmall); dimensions.textContent = isTooSmall - ? `Size: ${image.naturalWidth} x ${image.naturalHeight}px - too small, min ${MIN_PRODUCT_PICTURE_SIZE} x ${MIN_PRODUCT_PICTURE_SIZE}` - : `Size: ${image.naturalWidth} x ${image.naturalHeight}px`; + ? `Size: ${image.naturalWidth} x ${image.naturalHeight}px - too small, min long side ${MIN_PRODUCT_PICTURE_SIZE}px` + : shortestSide < MIN_PRODUCT_PICTURE_SIZE + ? `Size: ${image.naturalWidth} x ${image.naturalHeight}px - OK for 1:1 crop` + : `Size: ${image.naturalWidth} x ${image.naturalHeight}px`; }); image.addEventListener("error", () => { dimensions.textContent = "Size: image preview failed"; diff --git a/public/app.ts b/public/app.ts index 9d3589e..2aec9d7 100644 --- a/public/app.ts +++ b/public/app.ts @@ -992,11 +992,15 @@ function renderPictureCandidates(items) { return; } - const isTooSmall = image.naturalWidth < MIN_PRODUCT_PICTURE_SIZE || image.naturalHeight < MIN_PRODUCT_PICTURE_SIZE; + const shortestSide = Math.min(image.naturalWidth, image.naturalHeight); + const longestSide = Math.max(image.naturalWidth, image.naturalHeight); + const isTooSmall = longestSide < MIN_PRODUCT_PICTURE_SIZE; row.classList.toggle("is-too-small", isTooSmall); dimensions.textContent = isTooSmall - ? `Size: ${image.naturalWidth} x ${image.naturalHeight}px - too small, min ${MIN_PRODUCT_PICTURE_SIZE} x ${MIN_PRODUCT_PICTURE_SIZE}` - : `Size: ${image.naturalWidth} x ${image.naturalHeight}px`; + ? `Size: ${image.naturalWidth} x ${image.naturalHeight}px - too small, min long side ${MIN_PRODUCT_PICTURE_SIZE}px` + : shortestSide < MIN_PRODUCT_PICTURE_SIZE + ? `Size: ${image.naturalWidth} x ${image.naturalHeight}px - OK for 1:1 crop` + : `Size: ${image.naturalWidth} x ${image.naturalHeight}px`; }); image.addEventListener("error", () => { dimensions.textContent = "Size: image preview failed";