chore: better local image procession for crop image with both width and height.
This commit is contained in:
parent
6addf4e95d
commit
988a24e5b8
@ -15,6 +15,7 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
image: {
|
image: {
|
||||||
domains: ['localhost', '127.0.0.1'],
|
domains: ['localhost', '127.0.0.1'],
|
||||||
|
service: !options.isProd() ? { entrypoint: './plugins/resize', config: {} } : undefined,
|
||||||
},
|
},
|
||||||
experimental: {
|
experimental: {
|
||||||
env: {
|
env: {
|
||||||
|
91
plugins/resize.ts
Normal file
91
plugins/resize.ts
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import type { ImageOutputFormat, ImageQualityPreset, LocalImageService } from 'astro';
|
||||||
|
import { baseService } from 'astro/assets';
|
||||||
|
|
||||||
|
const qualityTable: Record<ImageQualityPreset, number> = {
|
||||||
|
low: 25,
|
||||||
|
mid: 50,
|
||||||
|
high: 80,
|
||||||
|
max: 100,
|
||||||
|
};
|
||||||
|
|
||||||
|
const parseQuality = (quality: string): string | number => {
|
||||||
|
const result = Number.parseInt(quality);
|
||||||
|
if (Number.isNaN(result)) {
|
||||||
|
return quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseServiceTransform = {
|
||||||
|
src: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
format: string;
|
||||||
|
quality?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface SharpImageServiceConfig {
|
||||||
|
/**
|
||||||
|
* The `limitInputPixels` option passed to Sharp. See https://sharp.pixelplumbing.com/api-constructor for more information
|
||||||
|
*/
|
||||||
|
limitInputPixels?: import('sharp').SharpOptions['limitInputPixels'];
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageService: LocalImageService<SharpImageServiceConfig> = {
|
||||||
|
getURL: baseService.getURL,
|
||||||
|
getSrcSet: baseService.getSrcSet,
|
||||||
|
getHTMLAttributes: baseService.getHTMLAttributes,
|
||||||
|
validateOptions: baseService.validateOptions,
|
||||||
|
parseURL: baseService.parseURL,
|
||||||
|
async transform(inputBuffer, transformOptions, config) {
|
||||||
|
const { default: sharp } = await import('sharp');
|
||||||
|
const transform: BaseServiceTransform = transformOptions as BaseServiceTransform;
|
||||||
|
|
||||||
|
// Sharp has some support for SVGs, we could probably support this once Sharp is the default and only service.
|
||||||
|
if (transform.format === 'svg') return { data: inputBuffer, format: 'svg' };
|
||||||
|
|
||||||
|
const result = sharp(inputBuffer, {
|
||||||
|
failOnError: false,
|
||||||
|
pages: -1,
|
||||||
|
limitInputPixels: config.service.config.limitInputPixels,
|
||||||
|
});
|
||||||
|
|
||||||
|
result.rotate();
|
||||||
|
|
||||||
|
// Never resize using both width and height at the same time, prioritizing width.
|
||||||
|
if (transform.height) {
|
||||||
|
if (!transform.width) {
|
||||||
|
result.resize({ height: Math.round(transform.height) });
|
||||||
|
} else {
|
||||||
|
// Allow the width and height to be set.
|
||||||
|
result.resize({ width: Math.round(transform.width), height: Math.round(transform.height) });
|
||||||
|
}
|
||||||
|
} else if (transform.width) {
|
||||||
|
result.resize({ width: Math.round(transform.width) });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transform.format) {
|
||||||
|
let quality: number | string | undefined = undefined;
|
||||||
|
if (transform.quality) {
|
||||||
|
const parsedQuality = parseQuality(transform.quality);
|
||||||
|
if (typeof parsedQuality === 'number') {
|
||||||
|
quality = parsedQuality;
|
||||||
|
} else {
|
||||||
|
quality = transform.quality in qualityTable ? qualityTable[transform.quality] : undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.toFormat(transform.format as keyof import('sharp').FormatEnum, { quality: quality });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data, info } = await result.toBuffer({ resolveWithObject: true });
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: data,
|
||||||
|
format: info.format as ImageOutputFormat,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default imageService;
|
Loading…
Reference in New Issue
Block a user