sharp by wasm
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import sharp from 'sharp';
|
||||
import { optimizeImage } from 'wasm-image-optimization';
|
||||
import * as db from '../../db/posterminal.js';
|
||||
|
||||
const PIMAGE_DEFAULT_W = 200;
|
||||
@@ -250,42 +250,63 @@ async function servePosImage(req, res, { isCimage = false } = {}) {
|
||||
return res.status(304).end();
|
||||
}
|
||||
|
||||
const imageSharp = sharp(image.buffer);
|
||||
const meta = await optimizeImage({ image: image.buffer, format: 'none' });
|
||||
const srcW = meta.originalWidth || targetW;
|
||||
const srcH = meta.originalHeight || targetH;
|
||||
const scale = Math.min(1, targetW / srcW, targetH / srcH);
|
||||
const scaledW = Math.max(1, Math.round(srcW * scale));
|
||||
const scaledH = Math.max(1, Math.round(srcH * scale));
|
||||
|
||||
const resizeOptions = isCimage
|
||||
? {
|
||||
fit: 'contain',
|
||||
background: '#ffffff',
|
||||
withoutEnlargement: true,
|
||||
}
|
||||
: {
|
||||
fit: 'inside',
|
||||
withoutEnlargement: true,
|
||||
};
|
||||
const scaledPng = await optimizeImage({
|
||||
image: image.buffer,
|
||||
width: scale < 1 ? scaledW : undefined,
|
||||
height: scale < 1 ? scaledH : undefined,
|
||||
fit: 'fill',
|
||||
format: 'png',
|
||||
});
|
||||
|
||||
let pipeline = imageSharp
|
||||
.resize(targetW, targetH, resizeOptions)
|
||||
.flatten({ background: '#ffffff' });
|
||||
const canvasW = isCimage ? targetW : scaledPng.width;
|
||||
const canvasH = isCimage ? targetH : scaledPng.height;
|
||||
const offsetX = Math.round((canvasW - scaledPng.width) / 2);
|
||||
const offsetY = Math.round((canvasH - scaledPng.height) / 2);
|
||||
const b64 = Buffer.from(scaledPng.data).toString('base64');
|
||||
const flatSvg =
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" width="${canvasW}" height="${canvasH}">` +
|
||||
`<rect width="${canvasW}" height="${canvasH}" fill="#ffffff"/>` +
|
||||
`<image href="data:image/png;base64,${b64}" x="${offsetX}" y="${offsetY}" width="${scaledPng.width}" height="${scaledPng.height}"/>` +
|
||||
`</svg>`;
|
||||
|
||||
const accept = String(req.headers.accept || '');
|
||||
const formatParam = typeof req.query.format === 'string' ? req.query.format.toLowerCase() : '';
|
||||
|
||||
let contentType = 'image/jpeg';
|
||||
let targetFormat = 'jpeg';
|
||||
let quality = 85;
|
||||
let speed = 6;
|
||||
if (formatParam === 'avif' || (!formatParam && accept.includes('image/avif'))) {
|
||||
pipeline = pipeline.avif({ effort: 2 });
|
||||
targetFormat = 'avif';
|
||||
speed = 8;
|
||||
contentType = 'image/avif';
|
||||
} else if (formatParam === 'webp' || (!formatParam && accept.includes('image/webp'))) {
|
||||
pipeline = pipeline.webp({ quality: 85 });
|
||||
targetFormat = 'webp';
|
||||
quality = 85;
|
||||
contentType = 'image/webp';
|
||||
} else if (formatParam === 'png') {
|
||||
pipeline = pipeline.png();
|
||||
targetFormat = 'png';
|
||||
contentType = 'image/png';
|
||||
} else {
|
||||
pipeline = pipeline.jpeg({ quality: 85 });
|
||||
targetFormat = 'jpeg';
|
||||
quality = 85;
|
||||
contentType = 'image/jpeg';
|
||||
}
|
||||
|
||||
const buffer = await pipeline.toBuffer();
|
||||
const encoded = await optimizeImage({
|
||||
image: flatSvg,
|
||||
format: targetFormat,
|
||||
quality,
|
||||
speed,
|
||||
});
|
||||
const buffer = Buffer.from(encoded.data);
|
||||
|
||||
res.setHeader('Content-Type', contentType);
|
||||
res.setHeader('Content-Length', String(buffer.length));
|
||||
|
||||
Reference in New Issue
Block a user