mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-14 17:49:52 +00:00
Simpler canDecode check
This commit is contained in:
@@ -1,23 +1,16 @@
|
|||||||
import { builtinDecode, sniffMimeType, canDecodeImage } from '../lib/util';
|
import { builtinDecode, sniffMimeType, canDecodeImageType } from '../lib/util';
|
||||||
import Processor from './processor';
|
import Processor from './processor';
|
||||||
import webpDataUrl from 'url-loader!./tiny.webp';
|
|
||||||
import avifDataUrl from 'url-loader!./tiny.avif';
|
|
||||||
|
|
||||||
const webPSupported = canDecodeImage(webpDataUrl);
|
|
||||||
const avifSupported = canDecodeImage(avifDataUrl);
|
|
||||||
|
|
||||||
export async function decodeImage(blob: Blob, processor: Processor): Promise<ImageData> {
|
export async function decodeImage(blob: Blob, processor: Processor): Promise<ImageData> {
|
||||||
const mimeType = await sniffMimeType(blob);
|
const mimeType = await sniffMimeType(blob);
|
||||||
|
const canDecode = await canDecodeImageType(mimeType);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (mimeType === 'image/avif' && !(await avifSupported)) {
|
if (!canDecode) {
|
||||||
return await processor.avifDecode(blob);
|
if (mimeType === 'image/avif') return await processor.avifDecode(blob);
|
||||||
|
if (mimeType === 'image/webp') return await processor.webpDecode(blob);
|
||||||
|
// If it's not one of those types, fall through and try built-in decoding for a laugh.
|
||||||
}
|
}
|
||||||
if (mimeType === 'image/webp' && !(await webPSupported)) {
|
|
||||||
return await processor.webpDecode(blob);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, just throw it at the browser's decoder.
|
|
||||||
return await builtinDecode(blob);
|
return await builtinDecode(blob);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw Error("Couldn't decode image");
|
throw Error("Couldn't decode image");
|
||||||
|
|||||||
@@ -78,11 +78,36 @@ async function decodeImage(url: string): Promise<HTMLImageElement> {
|
|||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Caches results from canDecodeImageType */
|
||||||
|
const canDecodeCache = new Map<string, Promise<boolean>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to load the given URL as an image.
|
* Tests whether the browser supports a particular image mime type.
|
||||||
|
*
|
||||||
|
* @param type Mimetype
|
||||||
|
* @example await canDecodeImageType('image/avif')
|
||||||
*/
|
*/
|
||||||
export function canDecodeImage(url: string): Promise<boolean> {
|
export function canDecodeImageType(type: string): Promise<boolean> {
|
||||||
return decodeImage(url).then(() => true, () => false);
|
if (!canDecodeCache.has(type)) {
|
||||||
|
const resultPromise = (async () => {
|
||||||
|
const picture = document.createElement('picture');
|
||||||
|
const img = document.createElement('img');
|
||||||
|
const source = document.createElement('source');
|
||||||
|
source.srcset = 'data:,x';
|
||||||
|
source.type = type;
|
||||||
|
picture.append(source, img);
|
||||||
|
|
||||||
|
// Wait a single microtick just for the `img.currentSrc` to get populated.
|
||||||
|
await 0;
|
||||||
|
// At this point `img.currentSrc` will contain "data:,x" if format is supported and ""
|
||||||
|
// otherwise.
|
||||||
|
return !!img.currentSrc;
|
||||||
|
})();
|
||||||
|
|
||||||
|
canDecodeCache.set(type, resultPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
return canDecodeCache.get(type)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function blobToArrayBuffer(blob: Blob): Promise<ArrayBuffer> {
|
export function blobToArrayBuffer(blob: Blob): Promise<ArrayBuffer> {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 303 B After Width: | Height: | Size: 303 B |
|
Before Width: | Height: | Size: 38 B After Width: | Height: | Size: 38 B |
@@ -1,5 +1,5 @@
|
|||||||
import webpDataUrl from 'url-loader!../codecs/tiny.webp';
|
import webpDataUrl from 'url-loader!./tiny.webp';
|
||||||
import avifDataUrl from 'url-loader!../codecs/tiny.avif';
|
import avifDataUrl from 'url-loader!./tiny.avif';
|
||||||
|
|
||||||
// Give TypeScript the correct global.
|
// Give TypeScript the correct global.
|
||||||
declare var self: ServiceWorkerGlobalScope;
|
declare var self: ServiceWorkerGlobalScope;
|
||||||
|
|||||||
Reference in New Issue
Block a user