mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-11 16:26:20 +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 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> {
|
||||
const mimeType = await sniffMimeType(blob);
|
||||
const canDecode = await canDecodeImageType(mimeType);
|
||||
|
||||
try {
|
||||
if (mimeType === 'image/avif' && !(await avifSupported)) {
|
||||
return await processor.avifDecode(blob);
|
||||
if (!canDecode) {
|
||||
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);
|
||||
} catch (err) {
|
||||
throw Error("Couldn't decode image");
|
||||
|
||||
@@ -78,11 +78,36 @@ async function decodeImage(url: string): Promise<HTMLImageElement> {
|
||||
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> {
|
||||
return decodeImage(url).then(() => true, () => false);
|
||||
export function canDecodeImageType(type: string): Promise<boolean> {
|
||||
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> {
|
||||
|
||||
|
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 avifDataUrl from 'url-loader!../codecs/tiny.avif';
|
||||
import webpDataUrl from 'url-loader!./tiny.webp';
|
||||
import avifDataUrl from 'url-loader!./tiny.avif';
|
||||
|
||||
// Give TypeScript the correct global.
|
||||
declare var self: ServiceWorkerGlobalScope;
|
||||
|
||||
Reference in New Issue
Block a user