refactor(gif encoder): expose an Event Emitter API

This commit is contained in:
wryk 2019-03-12 20:14:54 +01:00
parent 73d37d2c23
commit 481e30a01c
5 changed files with 47 additions and 51 deletions

19
package-lock.json generated
View file

@ -3095,6 +3095,11 @@
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
"dev": true "dev": true
}, },
"eventemitter3": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
"integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA=="
},
"events": { "events": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
@ -3510,14 +3515,12 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -3537,8 +3540,7 @@
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
@ -3686,7 +3688,6 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -3694,8 +3695,7 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.3.5", "version": "2.3.5",
@ -3799,8 +3799,7 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",

View file

@ -9,6 +9,7 @@
"lint-fix": "eslint --ext .js,vue . --fix" "lint-fix": "eslint --ext .js,vue . --fix"
}, },
"dependencies": { "dependencies": {
"eventemitter3": "^3.1.0",
"gif-writer": "^0.9.3", "gif-writer": "^0.9.3",
"postcss-modules": "^1.4.1", "postcss-modules": "^1.4.1",
"vue": "^2.6.6", "vue": "^2.6.6",

View file

@ -1,30 +1,31 @@
// import EncodeWorker from './encode.worker.js' import EventEmitter from 'eventemitter3'
const PALETTE_SIZE = 255 const PALETTE_SIZE = 255
export function encode ({ imageDataList, imageWidth, imageHeight, delayTime }) { export function encode ({ imageDataList, imageWidth, imageHeight, delayTime }) {
return new Promise((resolve, reject) => { const emitter = new EventEmitter()
const worker = new Worker('/services/encode.worker.js') const worker = new Worker('/services/encode.worker.js')
worker.onerror = error => reject(error) worker.onerror = error => emitter.emit('error', error)
worker.onmessageerror = error => emitter.emit('error', error)
worker.onmessage = event => { worker.onmessage = event => {
const { type, payload } = event.data const { type, payload } = event.data
switch (type) { switch (type) {
default: default:
reject(new Error(`Unexpected worker message with type ${type}`)) emitter.emit('error', new Error(`Unexpected worker message with type ${type}`))
break break
case 'progress': case 'progress':
console.log(`Encoding progress : ${payload.value}`) emitter.emit('progress', payload.value)
break break
case 'done': case 'done':
const byteArray = new Uint8Array(payload.buffer) const byteArray = new Uint8Array(payload.buffer)
const blob = new Blob([byteArray], { type: 'image/gif' }) const blob = new Blob([byteArray], { type: 'image/gif' })
const objectUrl = URL.createObjectURL(blob) const objectUrl = URL.createObjectURL(blob)
resolve(objectUrl) emitter.emit('done', objectUrl)
break break
} }
} }
@ -36,5 +37,6 @@ export function encode ({ imageDataList, imageWidth, imageHeight, delayTime }) {
paletteSize: PALETTE_SIZE, paletteSize: PALETTE_SIZE,
delayTime delayTime
}) })
})
return emitter
} }

View file

@ -7,17 +7,13 @@ import {
onmessage = (event) => { onmessage = (event) => {
const { imageDataList, imageWidth, imageHeight, paletteSize, delayTime } = event.data const { imageDataList, imageWidth, imageHeight, paletteSize, delayTime } = event.data
console.log('Write GIF')
const outputStream = new OutputStream() const outputStream = new OutputStream()
const writer = new GifWriter(outputStream) const writer = new GifWriter(outputStream)
postProgressMessage(0) postProgressMessage(0)
console.log(`Write header`)
writer.writeHeader() writer.writeHeader()
console.log(`Write logical screen informations`)
writer.writeLogicalScreenInfo({ writer.writeLogicalScreenInfo({
width: imageWidth, width: imageWidth,
height: imageHeight height: imageHeight
@ -26,19 +22,16 @@ onmessage = (event) => {
writer.writeLoopControlInfo(0) writer.writeLoopControlInfo(0)
const indexedColorImages = imageDataList.map((imageData, index, { length }) => { const indexedColorImages = imageDataList.map((imageData, index, { length }) => {
console.log(`Convert frame ${index} ImageData to IndexedColorImage`)
const indexedColorImage = imageDataToIndexedColorImage(imageData, paletteSize) const indexedColorImage = imageDataToIndexedColorImage(imageData, paletteSize)
postProgressMessage(calcProgress(0, 0.9, length, index + 1)) postProgressMessage(calcProgress(0, 0.9, length, index + 1))
return indexedColorImage return indexedColorImage
}) })
indexedColorImages.forEach((indexedColorImage, index, { length }) => { indexedColorImages.forEach((indexedColorImage, index, { length }) => {
console.log(`Write frame IndexedColorImage ${index}`)
writer.writeTableBasedImageWithGraphicControl(indexedColorImage, { delayTimeInMS: delayTime }) writer.writeTableBasedImageWithGraphicControl(indexedColorImage, { delayTimeInMS: delayTime })
postProgressMessage(calcProgress(0.9, 1, length, index + 1)) postProgressMessage(calcProgress(0.9, 1, length, index + 1))
}) })
console.log(`Write trailer`)
writer.writeTrailer() writer.writeTrailer()
postDoneMessage(outputStream.buffer) postDoneMessage(outputStream.buffer)

View file

@ -119,15 +119,16 @@ export default new Vuex.Store({
}, },
encode ({ commit }, captureData) { encode ({ commit }, captureData) {
commit('startEncoding') commit('startEncoding')
const encoding = encode(captureData)
console.log(captureData) encoding.once('error', error => console.error(error))
encode(captureData) encoding.on('progress', value => console.log(`Encoding progress ${Math.round(value * 100)}% (${value})`))
.then(dataUrl => {
encoding.once('done', objectUrl => {
commit('stopEncoding') commit('stopEncoding')
commit('startDownloading', dataUrl) commit('startDownloading', objectUrl)
}) })
.catch(error => console.error(error))
} }
} }
}) })