mirror of
https://github.com/GuerillaStudio/souvenir.git
synced 2025-01-20 22:30:20 +00:00
refactor(gif encoder): expose an Event Emitter API
This commit is contained in:
parent
73d37d2c23
commit
481e30a01c
5 changed files with 47 additions and 51 deletions
19
package-lock.json
generated
19
package-lock.json
generated
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
11
src/store.js
11
src/store.js
|
@ -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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue