From a2017f3f47b238290cb2d156003b5927ee4da434 Mon Sep 17 00:00:00 2001 From: wryk Date: Tue, 21 May 2019 14:37:05 +0200 Subject: [PATCH] refact(workers): split encode-core --- src/services/encode-core.js | 84 --------------------------- src/services/quantize-color.js | 27 +++++++++ src/services/quantize-color.worker.js | 10 +--- src/services/write-gif.js | 46 +++++++++++++++ src/services/write-gif.worker.js | 30 +++++----- 5 files changed, 89 insertions(+), 108 deletions(-) delete mode 100644 src/services/encode-core.js create mode 100644 src/services/quantize-color.js create mode 100644 src/services/write-gif.js diff --git a/src/services/encode-core.js b/src/services/encode-core.js deleted file mode 100644 index 5845d48..0000000 --- a/src/services/encode-core.js +++ /dev/null @@ -1,84 +0,0 @@ -import EventEmitter from 'eventemitter3' - -import { - GifWriter, - MedianCutColorReducer, - IndexedColorImage -} from 'gif-writer' - -import { boomerang } from '/services/effects.js' -import { pipe, calcProgress } from '/services/util.js' - -class OutputStream { - constructor () { - this.buffer = [] - } - - writeByte (b) { - this.buffer.push(b) - } - - writeBytes (bb) { - Array.prototype.push.apply(this.buffer, bb) - } -} - -export function write (imageWidth, imageHeight, delay, indexedColorImages, boomerangEffect = false) { - const emitter = new EventEmitter() - - // yup, this is the browser nextTick implementation we are waiting for :facepalm: - Promise.resolve().then(() => { - emitter.emit('progress', 0) - - const outputStream = new OutputStream() - const writer = new GifWriter(outputStream) - - writer.writeHeader() - - writer.writeLogicalScreenInfo({ - width: imageWidth, - height: imageHeight - }) - - writer.writeLoopControlInfo(0) - - const frames = pipe(indexedColorImages, [ - (images) => boomerangEffect ? boomerang(images) : images - ]) - - frames.forEach((indexedColorImage, index, { length }) => { - writer.writeTableBasedImageWithGraphicControl(indexedColorImage, { delayTimeInMS: delay }) - emitter.emit('progress', calcProgress(0, 0.99, (index + 1) / length)) - }) - - writer.writeTrailer() - emitter.emit('progress', 1) - - emitter.emit('done', outputStream.buffer) - }) - - return emitter -} - -export function convertImageDataToIndexedColorImage (imageData, paletteSize) { - const reducer = new MedianCutColorReducer(imageData, paletteSize) - - const paletteData = reducer.process() - - const data = Array.from(imageData.data) - const indexedColorImageData = [] - - for (let index = 0, length = data.length; index < length; index += 4) { - const [r, g, b] = data.slice(index, index + 4) // r,g,b,a - indexedColorImageData.push(reducer.map(r, g, b)) - } - - return new IndexedColorImage( - { - width: imageData.width, - height: imageData.height - }, - indexedColorImageData, - paletteData - ) -} diff --git a/src/services/quantize-color.js b/src/services/quantize-color.js new file mode 100644 index 0000000..d63f359 --- /dev/null +++ b/src/services/quantize-color.js @@ -0,0 +1,27 @@ +import { + MedianCutColorReducer, + IndexedColorImage +} from 'gif-writer' + +export function convertImageDataToIndexedColorImage (imageData, paletteSize) { + const reducer = new MedianCutColorReducer(imageData, paletteSize) + + const paletteData = reducer.process() + + const data = Array.from(imageData.data) + const indexedColorImageData = [] + + for (let index = 0, length = data.length; index < length; index += 4) { + const [r, g, b] = data.slice(index, index + 4) // r,g,b,a + indexedColorImageData.push(reducer.map(r, g, b)) + } + + return new IndexedColorImage( + { + width: imageData.width, + height: imageData.height + }, + indexedColorImageData, + paletteData + ) +} diff --git a/src/services/quantize-color.worker.js b/src/services/quantize-color.worker.js index ef499de..ae8349b 100644 --- a/src/services/quantize-color.worker.js +++ b/src/services/quantize-color.worker.js @@ -1,11 +1,7 @@ -import { convertImageDataToIndexedColorImage } from '/services/encode-core.js' +import { convertImageDataToIndexedColorImage } from '/services/quantize-color.js' -onmessage = handleMessage - -function handleMessage (event) { +onmessage = event => { const { imageData, paletteSize } = event.data - const indexedColorImage = convertImageDataToIndexedColorImage(imageData, paletteSize) - - postMessage(indexedColorImage) + postMessage(convertImageDataToIndexedColorImage(imageData, paletteSize)) } diff --git a/src/services/write-gif.js b/src/services/write-gif.js new file mode 100644 index 0000000..9b2d5c2 --- /dev/null +++ b/src/services/write-gif.js @@ -0,0 +1,46 @@ +import { GifWriter } from 'gif-writer' +import { boomerang } from '/services/effects.js' +import { pipe, calcProgress } from '/services/util.js' + +class OutputStream { + constructor () { + this.buffer = [] + } + + writeByte (b) { + this.buffer.push(b) + } + + writeBytes (bb) { + Array.prototype.push.apply(this.buffer, bb) + } +} + +export function write (imageWidth, imageHeight, delay, indexedColorImages, boomerangEffect, progressCallback) { + const outputStream = new OutputStream() + const writer = new GifWriter(outputStream) + + progressCallback(0) + writer.writeHeader() + + writer.writeLogicalScreenInfo({ + width: imageWidth, + height: imageHeight + }) + + writer.writeLoopControlInfo(0) + + const frames = pipe(indexedColorImages, [ + (images) => boomerangEffect ? boomerang(images) : images + ]) + + frames.forEach((indexedColorImage, index, { length }) => { + writer.writeTableBasedImageWithGraphicControl(indexedColorImage, { delayTimeInMS: delay }) + progressCallback(calcProgress(0, 0.99, (index + 1) / length)) + }) + + writer.writeTrailer() + progressCallback(1) + + return outputStream.buffer +} diff --git a/src/services/write-gif.worker.js b/src/services/write-gif.worker.js index 260f852..90141de 100644 --- a/src/services/write-gif.worker.js +++ b/src/services/write-gif.worker.js @@ -1,23 +1,19 @@ -import { write } from '/services/encode-core.js' +import { write } from '/services/write-gif.js' -onmessage = handleMessage +const postProgressMessage = value => postMessage({ type: 'progress', payload: { value } }) +const postDoneMessage = buffer => postMessage({ type: 'done', payload: { buffer } }) -async function handleMessage (event) { +onmessage = event => { const { imageWidth, imageHeight, delayTime, indexedColorImages, boomerangEffect } = event.data - const writing = write(imageWidth, imageHeight, delayTime, indexedColorImages, boomerangEffect) + const buffer = write( + imageWidth, + imageHeight, + delayTime, + indexedColorImages, + boomerangEffect, + postProgressMessage + ) - writing.on('progress', value => postMessage({ - type: 'progress', - payload: { - value - } - })) - - writing.once('done', buffer => postMessage({ - type: 'done', - payload: { - buffer - } - })) + postDoneMessage(buffer) }