u
This commit is contained in:
@@ -146,7 +146,7 @@ Backend mapping:
|
||||
| `updateBySku` | `(googleAuthId, sku, { name })` | same shape as `getBySku` |
|
||||
| `addImage` | `(googleAuthId, sku, imageBuffer)` | image result (see below) |
|
||||
|
||||
`addImage` accepts a full-size AVIF `Buffer`, scales to max 1000×1000 (`pic.binary`) and 200×200 (`pic.thumbbinary`) via `sharp`, computes `hash` / `thumbhash`, links `articlepic`. Auth like `getBySku`. Errors: `Article not found`, `Not authorized`.
|
||||
`addImage` accepts a full-size AVIF `Buffer`. Full image: if already AVIF and ≤1000×1000, stored as-is; otherwise scaled to max 1000×1000 (`pic.binary`). Thumb always scaled to max 200×200 (`pic.thumbbinary`) via `sharp`. Computes `hash` / `thumbhash`, links `articlepic`. Auth like `getBySku`. Errors: `Article not found`, `Not authorized`.
|
||||
|
||||
`addImage` returns:
|
||||
|
||||
@@ -154,7 +154,7 @@ Backend mapping:
|
||||
{
|
||||
picId,
|
||||
sort,
|
||||
full: { w, h, size }, // scaled AVIF, max 1000×1000 (fit inside)
|
||||
full: { w, h, size }, // AVIF, max 1000×1000 (stored as-is when already AVIF and within bounds)
|
||||
thumb: { w, h }, // scaled AVIF, max 200×200 (fit inside)
|
||||
hash, // SHA-256 hex of full image bytes
|
||||
thumbHash, // base64 thumbhash of thumb preview
|
||||
|
||||
@@ -10,16 +10,37 @@ export default async function processAvifImage(inputBuffer) {
|
||||
? inputBuffer
|
||||
: Buffer.from(inputBuffer);
|
||||
|
||||
const meta = await sharp(input).metadata();
|
||||
const w = meta.width ?? 0;
|
||||
const h = meta.height ?? 0;
|
||||
const isAvif =
|
||||
meta.format === 'avif' ||
|
||||
(meta.format === 'heif' && meta.compression === 'av1');
|
||||
const useOriginalFull =
|
||||
isAvif && w > 0 && h > 0 && w <= FULL_MAX && h <= FULL_MAX;
|
||||
|
||||
if (!useOriginalFull) {
|
||||
console.log(
|
||||
`processAvifImage: converting full image (format=${meta.format ?? 'unknown'}, ${w}×${h}, avif=${isAvif})`,
|
||||
);
|
||||
}
|
||||
|
||||
const thumbPipeline = sharp(input)
|
||||
.resize(THUMB_MAX, THUMB_MAX, { fit: 'inside', withoutEnlargement: true });
|
||||
|
||||
const [full, thumb, thumbRgba] = await Promise.all([
|
||||
sharp(input)
|
||||
.resize(FULL_MAX, FULL_MAX, { fit: 'inside', withoutEnlargement: true })
|
||||
.avif({ effort: 4 })
|
||||
.toBuffer({ resolveWithObject: true }),
|
||||
sharp(input)
|
||||
.resize(THUMB_MAX, THUMB_MAX, { fit: 'inside', withoutEnlargement: true })
|
||||
.avif({ effort: 4 })
|
||||
.toBuffer({ resolveWithObject: true }),
|
||||
sharp(input)
|
||||
useOriginalFull
|
||||
? Promise.resolve({
|
||||
info: { width: w, height: h },
|
||||
data: input,
|
||||
})
|
||||
: sharp(input)
|
||||
.resize(FULL_MAX, FULL_MAX, { fit: 'inside', withoutEnlargement: true })
|
||||
.avif({ effort: 4 })
|
||||
.toBuffer({ resolveWithObject: true }),
|
||||
thumbPipeline.clone().avif({ effort: 4 }).toBuffer({ resolveWithObject: true }),
|
||||
thumbPipeline
|
||||
.clone()
|
||||
.resize(100, 100, { fit: 'inside', withoutEnlargement: true })
|
||||
.ensureAlpha()
|
||||
.raw()
|
||||
|
||||
Reference in New Issue
Block a user