
* chore(npm): Install blurhash * feat(media): Show blurhash * fix(media/blurhash): Better sensitive video handling * feat(media): Preference for using blurhash * chore(utils/blurhash): Add performance marks * fix(utils/blurhash): Performance marks * fix(utils/blurhash): Use correct dimension * refactor(utils/blurhash): Use constant for number of pixels * refactor(media): Simplify logic for displaying blurhash * chore(tests/spec): Attempt to adjust sensitivity tests for blurhash * chore(tests/spec): Update sensitivity tests for blurhash * chore(tests/spec): Check for sensitive * fix(media/blurhash): Handle videos * fix: Video handling * fix: Videos * minor refactoring, fix Svelte warning * fix: Large inline images and videos * feat(settings): Rename blurhash setting * refactor: Use toBlob, block media rendering until blurhash ready * refactor: Move computations to Web Worker * fix(workers/blurhash): More error handling * feat(workers/blurhash): Use quick-lru for caching * fix: Don't create Context2D needlessly * fix(workers/blurhash): Increase cache size to 100 * fix(workers/blurhash): Don't resolve promise twice * fix(utils/decode-image): Ignore data URLs Throws exception which prevents the image from loading.
45 lines
1.7 KiB
JavaScript
45 lines
1.7 KiB
JavaScript
import { decode as decodeBlurHash } from 'blurhash'
|
|
import QuickLRU from 'quick-lru'
|
|
|
|
const RESOLUTION = 32
|
|
const OFFSCREEN_CANVAS = typeof OffscreenCanvas === 'function'
|
|
? new OffscreenCanvas(RESOLUTION, RESOLUTION) : null
|
|
const OFFSCREEN_CANVAS_CONTEXT_2D = OFFSCREEN_CANVAS
|
|
? OFFSCREEN_CANVAS.getContext('2d') : null
|
|
const CACHE = new QuickLRU({ maxSize: 100 })
|
|
|
|
self.addEventListener('message', ({ data: { encoded } }) => {
|
|
try {
|
|
if (CACHE.has(encoded)) {
|
|
if (OFFSCREEN_CANVAS) {
|
|
postMessage({ encoded, decoded: CACHE.get(encoded), imageData: null, error: null })
|
|
} else {
|
|
postMessage({ encoded, imageData: CACHE.get(encoded), decoded: null, error: null })
|
|
}
|
|
} else {
|
|
const pixels = decodeBlurHash(encoded, RESOLUTION, RESOLUTION)
|
|
|
|
if (pixels) {
|
|
const imageData = new ImageData(pixels, RESOLUTION, RESOLUTION)
|
|
|
|
if (OFFSCREEN_CANVAS) {
|
|
OFFSCREEN_CANVAS_CONTEXT_2D.putImageData(imageData, 0, 0)
|
|
OFFSCREEN_CANVAS.convertToBlob().then(blob => {
|
|
const decoded = URL.createObjectURL(blob)
|
|
CACHE.set(encoded, decoded)
|
|
postMessage({ encoded, decoded, imageData: null, error: null })
|
|
}).catch(error => {
|
|
postMessage({ encoded, decoded: null, imageData: null, error })
|
|
})
|
|
} else {
|
|
CACHE.set(encoded, imageData)
|
|
postMessage({ encoded, imageData, decoded: null, error: null })
|
|
}
|
|
} else {
|
|
postMessage({ encoded, decoded: null, imageData: null, error: new Error('decode did not return any pixels') })
|
|
}
|
|
}
|
|
} catch (error) {
|
|
postMessage({ encoded, decoded: null, imageData: null, error })
|
|
}
|
|
})
|