mirror of
https://github.com/GuerillaStudio/souvenir.git
synced 2024-11-08 12:11:53 +00:00
fix(encoder): remove nested worker
Nested worker is not supported on safari
This commit is contained in:
parent
57d4a8dd52
commit
388a1f4bb5
4 changed files with 96 additions and 117 deletions
|
@ -22,7 +22,7 @@ class OutputStream {
|
|||
}
|
||||
}
|
||||
|
||||
export function write (indexedColorImages, imageWidth, imageHeight, delay) {
|
||||
export function write (imageWidth, imageHeight, delay, indexedColorImages) {
|
||||
const emitter = new EventEmitter()
|
||||
|
||||
// yup, this is the browser nextTick implementation we are waiting for :facepalm:
|
||||
|
|
|
@ -1,42 +1,83 @@
|
|||
import EventEmitter from 'eventemitter3'
|
||||
import genericPool from 'generic-pool'
|
||||
import pEvent from 'p-event'
|
||||
import { write } from '/services/encode-core.js'
|
||||
import { promisesProgress, calcProgress } from '/services/util.js'
|
||||
|
||||
const PALETTE_SIZE = 255
|
||||
|
||||
export function encode ({ imageDataList, imageWidth, imageHeight, delayTime }) {
|
||||
const emitter = new EventEmitter()
|
||||
const worker = new Worker('/services/encode.worker.js')
|
||||
|
||||
worker.onerror = error => emitter.emit('error', error)
|
||||
worker.onmessageerror = error => emitter.emit('error', error)
|
||||
|
||||
worker.onmessage = event => {
|
||||
const { type, payload } = event.data
|
||||
|
||||
switch (type) {
|
||||
default:
|
||||
emitter.emit('error', new Error(`Unexpected worker message with type ${type}`))
|
||||
break
|
||||
|
||||
case 'progress':
|
||||
emitter.emit('progress', payload.value)
|
||||
break
|
||||
|
||||
case 'done':
|
||||
const byteArray = new Uint8Array(payload.buffer)
|
||||
const blob = new Blob([byteArray], { type: 'image/gif' })
|
||||
const objectUrl = URL.createObjectURL(blob)
|
||||
emitter.emit('done', objectUrl)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
worker.postMessage({
|
||||
imageDataList,
|
||||
imageWidth,
|
||||
imageHeight,
|
||||
paletteSize: PALETTE_SIZE,
|
||||
delayTime
|
||||
const quantizeColorWorkerPool = genericPool.createPool({
|
||||
create: () => new Worker('/services/quantize-color.worker.js'),
|
||||
destroy: worker => worker.terminate()
|
||||
}, {
|
||||
min: 0,
|
||||
max: 2
|
||||
})
|
||||
|
||||
|
||||
const indexedColorImagesP = imageDataList
|
||||
.map(async imageData => {
|
||||
const worker = await quantizeColorWorkerPool.acquire()
|
||||
|
||||
const indexedColorImage = await new Promise((resolve, reject) => {
|
||||
worker.onerror = reject
|
||||
worker.onmessageerror = reject
|
||||
worker.onmessage = event => {
|
||||
resolve(event.data)
|
||||
}
|
||||
|
||||
worker.postMessage({
|
||||
imageData,
|
||||
paletteSize: PALETTE_SIZE
|
||||
})
|
||||
})
|
||||
|
||||
await quantizeColorWorkerPool.release(worker)
|
||||
return indexedColorImage
|
||||
})
|
||||
|
||||
const progressPromises = promisesProgress(indexedColorImagesP, function (value) {
|
||||
emitter.emit('progress', calcProgress(0, 0.9, value))
|
||||
})
|
||||
|
||||
Promise.all(progressPromises).then(indexedColorImages => {
|
||||
const writeWorker = new Worker('/services/write-gif.worker.js')
|
||||
|
||||
writeWorker.onerror = error => emitter.emit('error', error)
|
||||
writeWorker.onmessageerror = error => emitter.emit('error', error)
|
||||
|
||||
writeWorker.onmessage = event => {
|
||||
const { type, payload } = event.data
|
||||
|
||||
switch (type) {
|
||||
default:
|
||||
emitter.emit('error', new Error(`Unexpected worker message with type ${type}`))
|
||||
break
|
||||
|
||||
case 'progress':
|
||||
emitter.emit('progress', calcProgress(0.9, 1, payload.value))
|
||||
break
|
||||
|
||||
case 'done':
|
||||
const byteArray = new Uint8Array(payload.buffer)
|
||||
const blob = new Blob([byteArray], { type: 'image/gif' })
|
||||
const objectUrl = URL.createObjectURL(blob)
|
||||
emitter.emit('done', objectUrl)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
writeWorker.postMessage({
|
||||
imageWidth,
|
||||
imageHeight,
|
||||
indexedColorImages,
|
||||
delayTime
|
||||
})
|
||||
})
|
||||
.catch(error => emitter.emit('error', error))
|
||||
|
||||
return emitter
|
||||
}
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
import genericPool from 'generic-pool'
|
||||
import pEvent from 'p-event'
|
||||
import { write } from '/services/encode-core.js'
|
||||
import { promisesProgress, calcProgress } from '/services/util.js'
|
||||
|
||||
onmessage = handleMessage
|
||||
|
||||
const workerPool = genericPool.createPool({
|
||||
create () {
|
||||
return new Worker('/services/quantize-color.worker.js')
|
||||
},
|
||||
destroy (worker) {
|
||||
worker.terminate()
|
||||
}
|
||||
}, {
|
||||
min: 0,
|
||||
max: 4
|
||||
})
|
||||
|
||||
async function handleMessage (event) {
|
||||
const { imageDataList, imageWidth, imageHeight, paletteSize, delayTime } = event.data
|
||||
|
||||
postProgressMessage(0)
|
||||
|
||||
console.time('quantization')
|
||||
|
||||
const promises = imageDataList
|
||||
.map(async imageData => {
|
||||
const worker = await workerPool.acquire()
|
||||
|
||||
const indexedColorImage = await new Promise((resolve, reject) => {
|
||||
worker.onerror = reject
|
||||
worker.onmessageerror = reject
|
||||
worker.onmessage = event => {
|
||||
resolve(event.data)
|
||||
}
|
||||
|
||||
worker.postMessage({
|
||||
imageData,
|
||||
paletteSize
|
||||
})
|
||||
})
|
||||
|
||||
await workerPool.release(worker)
|
||||
return indexedColorImage
|
||||
})
|
||||
|
||||
const progressPromises = promisesProgress(promises, function (value) {
|
||||
postProgressMessage(calcProgress(0, 0.9, value))
|
||||
})
|
||||
|
||||
const indexedColorImages = await Promise.all(progressPromises)
|
||||
|
||||
console.timeEnd('quantization')
|
||||
|
||||
console.time('write')
|
||||
|
||||
const writing = write(indexedColorImages, imageWidth, imageHeight, delayTime)
|
||||
|
||||
writing.on('progress', value => postProgressMessage(calcProgress(0.9, 1, value)))
|
||||
|
||||
const buffer = await pEvent(writing, 'done')
|
||||
|
||||
console.timeEnd('write')
|
||||
|
||||
postDoneMessage(buffer)
|
||||
}
|
||||
|
||||
function postProgressMessage (value) {
|
||||
postMessage({
|
||||
type: 'progress',
|
||||
payload: {
|
||||
value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function postDoneMessage (buffer) {
|
||||
postMessage({
|
||||
type: 'done',
|
||||
payload: {
|
||||
buffer
|
||||
}
|
||||
})
|
||||
}
|
23
src/services/write-gif.worker.js
Normal file
23
src/services/write-gif.worker.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { write } from '/services/encode-core.js'
|
||||
|
||||
onmessage = handleMessage
|
||||
|
||||
async function handleMessage (event) {
|
||||
const { imageWidth, imageHeight, delayTime, indexedColorImages } = event.data
|
||||
|
||||
const writing = write(imageWidth, imageHeight, delayTime, indexedColorImages)
|
||||
|
||||
writing.on('progress', value => postMessage({
|
||||
type: 'progress',
|
||||
payload: {
|
||||
value
|
||||
}
|
||||
}))
|
||||
|
||||
writing.once('done', buffer => postMessage({
|
||||
type: 'done',
|
||||
payload: {
|
||||
buffer
|
||||
}
|
||||
}))
|
||||
}
|
Loading…
Reference in a new issue