refact(workers): split encode-core

This commit is contained in:
wryk 2019-05-21 14:37:05 +02:00
parent 30a21b5709
commit a2017f3f47
5 changed files with 89 additions and 108 deletions

View file

@ -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
)
}

View file

@ -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
)
}

View file

@ -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))
}

46
src/services/write-gif.js Normal file
View file

@ -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
}

View file

@ -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)
}