Add a call-out to Web Codecs API

This commit is contained in:
Surma
2021-05-18 19:53:39 +01:00
parent 10c5082499
commit eb8204d69b
3 changed files with 60 additions and 1 deletions

View File

@@ -34,6 +34,7 @@ import { resize } from 'features/processors/resize/client';
import type SnackBarElement from 'shared/custom-els/snack-bar';
import { Arrow, ExpandIcon } from '../icons';
import { generateCliInvocation } from '../util/cli';
import * as WebCodecs from '../util/web-codecs';
export type OutputType = EncoderType | 'identity';
@@ -109,8 +110,12 @@ async function decodeImage(
if (mimeType === 'image/webp2') {
return await workerBridge.wp2Decode(signal, blob);
}
// If it's not one of those types, fall through and try built-in decoding for a laugh.
}
// If none of those work, lets see if Web Codecs API is available
if (await WebCodecs.isTypeSupported(mimeType)) {
return await abortable(signal, WebCodecs.decode(blob, mimeType));
}
// Otherwise fall through and try built-in decoding for a laugh.
return await abortable(signal, builtinDecode(blob));
} catch (err) {
if (err.name === 'AbortError') throw err;

View File

@@ -0,0 +1,26 @@
import { drawableToImageData } from 'client/lazy-app/util';
const hasImageDecoder = typeof ImageDecoder !== 'undefined';
export async function isTypeSupported(mimeType: string): Promise<boolean> {
if (!hasImageDecoder) {
return false;
}
return ImageDecoder.isTypeSupported(mimeType);
}
export async function decode(
blob: Blob | File,
mimeType: string,
): Promise<ImageData> {
if (!hasImageDecoder) {
throw Error(
`This browser does not support ImageDecoder. This function should not have been called.`,
);
}
const decoder = new ImageDecoder({
type: mimeType,
// Non-obvious way to turn an Blob into a ReadableStream
data: new Response(blob).body!,
});
const result = await decoder.decode();
return drawableToImageData(result.image);
}

View File

@@ -0,0 +1,28 @@
interface ImageDecoderInit {
type: string;
data: BufferSource | ReadableStream;
premultiplyAlpha?: PremultiplyAlpha;
colorSpaceConversion?: ColorSpaceConversion;
desiredWidth?: number;
desiredHeight?: number;
preferAnimation?: boolean;
}
interface ImageDecodeOptions {
frameIndex: number;
completeFramesOnly: boolean;
}
interface ImageDecodeResult {
image: VideoFrame;
complete: boolean;
}
// Absolutely not correct, but its all we need and Im lazy.
type VideoFrame = ImageBitmap;
declare class ImageDecoder {
static isTypeSupported(type: string): Promise<boolean>;
constructor(desc: ImageDecoderInit);
decode(opts?: Partial<ImageDecodeOptions>): Promise<ImageDecodeResult>;
}