2019-08-17 17:54:45 +00:00
|
|
|
import BlurhashWorker from 'worker-loader!../_workers/blurhash' // eslint-disable-line
|
2019-08-17 21:36:13 +00:00
|
|
|
import PromiseWorker from 'promise-worker'
|
|
|
|
import { BLURHASH_RESOLUTION as RESOLUTION } from '../_static/blurhash'
|
2019-08-18 22:15:13 +00:00
|
|
|
import { QuickLRU } from '../_thirdparty/quick-lru/quick-lru'
|
2019-08-17 21:36:13 +00:00
|
|
|
|
2019-08-18 22:15:13 +00:00
|
|
|
// A timeline will typically show 20-30 articles at once in the virtual list. The maximum number
|
|
|
|
// of sensitive images per article is 4. 30*4=120, so this is a very conservative number.
|
|
|
|
// Blurhash blobs seem to range from ~1.2-2kB, so this cache could grow to about 2kB*150=300kB max.
|
|
|
|
const cache = new QuickLRU({ maxSize: 150 })
|
2019-08-17 17:54:45 +00:00
|
|
|
|
|
|
|
let worker
|
|
|
|
let canvas
|
|
|
|
let canvasContext2D
|
|
|
|
|
2019-08-18 22:15:13 +00:00
|
|
|
cache.on('evict', (evictedUrl, blurhash) => {
|
|
|
|
console.log('evicted URL', evictedUrl, 'with blurhash', blurhash)
|
|
|
|
URL.revokeObjectURL(evictedUrl)
|
|
|
|
})
|
|
|
|
|
2019-08-17 17:54:45 +00:00
|
|
|
export function init () {
|
2019-08-17 21:36:13 +00:00
|
|
|
worker = worker || new PromiseWorker(new BlurhashWorker())
|
2019-08-17 17:54:45 +00:00
|
|
|
}
|
|
|
|
|
2019-08-17 21:36:13 +00:00
|
|
|
function initCanvas () {
|
|
|
|
if (!canvas) {
|
|
|
|
canvas = document.createElement('canvas')
|
|
|
|
canvas.height = RESOLUTION
|
|
|
|
canvas.width = RESOLUTION
|
|
|
|
canvasContext2D = canvas.getContext('2d')
|
|
|
|
}
|
|
|
|
}
|
2019-08-17 17:54:45 +00:00
|
|
|
|
2019-08-17 21:36:13 +00:00
|
|
|
// canvas is the backup if we can't use OffscreenCanvas
|
|
|
|
async function decodeUsingCanvas (imageData) {
|
|
|
|
initCanvas()
|
|
|
|
canvasContext2D.putImageData(imageData, 0, 0)
|
|
|
|
const blob = await new Promise(resolve => canvas.toBlob(resolve))
|
2019-08-18 22:15:13 +00:00
|
|
|
console.log('blob.size', blob.size)
|
2019-08-17 21:36:13 +00:00
|
|
|
return URL.createObjectURL(blob)
|
|
|
|
}
|
2019-08-17 17:54:45 +00:00
|
|
|
|
2019-08-17 21:36:13 +00:00
|
|
|
async function decodeWithoutCache (blurhash) {
|
|
|
|
init()
|
|
|
|
const { decoded, imageData } = await worker.postMessage(blurhash)
|
|
|
|
if (decoded) {
|
|
|
|
return decoded
|
|
|
|
}
|
|
|
|
return decodeUsingCanvas(imageData)
|
|
|
|
}
|
2019-08-17 17:54:45 +00:00
|
|
|
|
2019-08-17 21:36:13 +00:00
|
|
|
export async function decode (blurhash) {
|
2019-08-18 22:15:13 +00:00
|
|
|
let result = cache.get(blurhash)
|
2019-08-17 21:36:13 +00:00
|
|
|
if (!result) {
|
|
|
|
result = await decodeWithoutCache(blurhash)
|
2019-08-18 22:15:13 +00:00
|
|
|
cache.set(blurhash, result)
|
2019-08-17 21:36:13 +00:00
|
|
|
}
|
|
|
|
return result
|
2019-08-17 17:54:45 +00:00
|
|
|
}
|