Fix: let Squoosh default image quality internally (#4906)

* removes our quality defaults, allowing Squoosh format-specific defaults to be used

* chore: add changeset
This commit is contained in:
Tony Sullivan 2022-09-28 20:55:09 +00:00 committed by GitHub
parent 9103ac57fb
commit ec55745ae5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 20 additions and 11 deletions

View file

@ -0,0 +1,5 @@
---
'@astrojs/image': patch
---
Updates the default image service to use format-specific quality defaults

View file

@ -115,7 +115,7 @@ class SquooshService extends BaseSSRService {
inputBuffer, inputBuffer,
operations, operations,
transform.format, transform.format,
transform.quality || 100 transform.quality
); );
return { return {

View file

@ -78,7 +78,7 @@ export async function processBuffer(
buffer: Buffer, buffer: Buffer,
operations: Operation[], operations: Operation[],
encoding: OutputFormat, encoding: OutputFormat,
quality: number quality?: number
): Promise<Uint8Array> { ): Promise<Uint8Array> {
// @ts-ignore // @ts-ignore
const worker = await getWorker() const worker = await getWorker()
@ -109,14 +109,14 @@ export async function processBuffer(
return await worker.dispatchJob({ return await worker.dispatchJob({
operation: 'encodeavif', operation: 'encodeavif',
imageData, imageData,
quality: quality || 100 quality,
}) as Uint8Array; }) as Uint8Array;
case 'jpeg': case 'jpeg':
case 'jpg': case 'jpg':
return await worker.dispatchJob({ return await worker.dispatchJob({
operation: 'encodejpeg', operation: 'encodejpeg',
imageData, imageData,
quality: quality || 100, quality,
}) as Uint8Array; }) as Uint8Array;
case 'png': case 'png':
return await worker.dispatchJob({ return await worker.dispatchJob({
@ -127,7 +127,7 @@ export async function processBuffer(
return await worker.dispatchJob({ return await worker.dispatchJob({
operation: 'encodewebp', operation: 'encodewebp',
imageData, imageData,
quality: quality || 100, quality,
}) as Uint8Array; }) as Uint8Array;
default: default:
throw Error(`Unsupported encoding format`) throw Error(`Unsupported encoding format`)

View file

@ -16,7 +16,7 @@ export async function processBuffer(
buffer: Buffer, buffer: Buffer,
operations: Operation[], operations: Operation[],
encoding: OutputFormat, encoding: OutputFormat,
quality: number quality?: number
): Promise<Uint8Array> { ): Promise<Uint8Array> {
let imageData = await impl.decodeBuffer(buffer) let imageData = await impl.decodeBuffer(buffer)
for (const operation of operations) { for (const operation of operations) {
@ -29,7 +29,7 @@ export async function processBuffer(
switch (encoding) { switch (encoding) {
case 'avif': case 'avif':
return await impl.encodeAvif(imageData, { quality: quality }) as Uint8Array; return await impl.encodeAvif(imageData, { quality }) as Uint8Array;
case 'jpeg': case 'jpeg':
case 'jpg': case 'jpg':
return await impl.encodeJpeg(imageData, { quality }) as Uint8Array; return await impl.encodeJpeg(imageData, { quality }) as Uint8Array;

View file

@ -71,13 +71,14 @@ export async function resize({ image, width, height }: ResizeOpts) {
export async function encodeJpeg( export async function encodeJpeg(
image: ImageData, image: ImageData,
{ quality }: { quality: number } opts: { quality?: number }
): Promise<Uint8Array> { ): Promise<Uint8Array> {
image = ImageData.from(image) image = ImageData.from(image)
const e = supportedFormats['mozjpeg'] const e = supportedFormats['mozjpeg']
const m = await e.enc() const m = await e.enc()
await maybeDelay() await maybeDelay()
const quality = opts.quality || e.defaultEncoderOptions.quality
const r = await m.encode(image.data, image.width, image.height, { const r = await m.encode(image.data, image.width, image.height, {
...e.defaultEncoderOptions, ...e.defaultEncoderOptions,
quality, quality,
@ -87,13 +88,14 @@ export async function encodeJpeg(
export async function encodeWebp( export async function encodeWebp(
image: ImageData, image: ImageData,
{ quality }: { quality: number } opts: { quality?: number }
): Promise<Uint8Array> { ): Promise<Uint8Array> {
image = ImageData.from(image) image = ImageData.from(image)
const e = supportedFormats['webp'] const e = supportedFormats['webp']
const m = await e.enc() const m = await e.enc()
await maybeDelay() await maybeDelay()
const quality = opts.quality || e.defaultEncoderOptions.quality
const r = await m.encode(image.data, image.width, image.height, { const r = await m.encode(image.data, image.width, image.height, {
...e.defaultEncoderOptions, ...e.defaultEncoderOptions,
quality, quality,
@ -103,7 +105,7 @@ export async function encodeWebp(
export async function encodeAvif( export async function encodeAvif(
image: ImageData, image: ImageData,
{ quality }: { quality: number } opts: { quality?: number }
): Promise<Uint8Array> { ): Promise<Uint8Array> {
image = ImageData.from(image) image = ImageData.from(image)
@ -111,6 +113,8 @@ export async function encodeAvif(
const m = await e.enc() const m = await e.enc()
await maybeDelay() await maybeDelay()
const val = e.autoOptimize.min const val = e.autoOptimize.min
// AVIF doesn't use a 0-100 quality, default to 75 and convert to cqLevel below
const quality = opts.quality || 75
const r = await m.encode(image.data, image.width, image.height, { const r = await m.encode(image.data, image.width, image.height, {
...e.defaultEncoderOptions, ...e.defaultEncoderOptions,
// Think of cqLevel as the "amount" of quantization (0 to 62), // Think of cqLevel as the "amount" of quantization (0 to 62),