-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create initial version of @wasm-codecs/gifsicle
- Loading branch information
1 parent
df218df
commit b3f4c66
Showing
11 changed files
with
278 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,20 @@ | ||
FROM trzeci/emscripten:1.39.18-upstream | ||
|
||
RUN apt-get update && \ | ||
apt-get install -y \ | ||
autoconf \ | ||
libtool \ | ||
libpng-dev \ | ||
pkg-config && \ | ||
rm -rf /var/lib/apt/lists/* | ||
|
||
RUN curl https://codeload.github.com/kohler/gifsicle/zip/v1.92 -o /tmp/gifsicle.zip && \ | ||
unzip /tmp/gifsicle.zip -d /lib && \ | ||
mv /lib/gifsicle-1.92 /lib/gifsicle && \ | ||
rm /tmp/gifsicle.zip | ||
|
||
RUN cd /lib/gifsicle && \ | ||
sed -i 's/CC="$CC -W -Wall"/CC="$CC -W -Wall -s ERROR_ON_UNDEFINED_SYMBOLS=0"/g' configure.ac && \ | ||
./bootstrap.sh && \ | ||
emconfigure ./configure --disable-gifview && \ | ||
emmake make |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
export type GifsicleModule = EmscriptenModule & { | ||
input: Uint8Array; | ||
output: (res: Uint8Array) => void, | ||
} | ||
|
||
export default function(mozjpeg: { | ||
stdout?: (char: number) => void, | ||
stderr?: (char: number) => void, | ||
arguments?: string[], | ||
input: Uint8Array, | ||
output: (res: Uint8Array) => void, | ||
}): Promise<Omit<GifsicleModule, 'then'>>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import Gifsicle from './gifsicle'; | ||
import { EncodeOptions } from './types'; | ||
import { defaultEncodeOptions } from './options'; | ||
import { stdout, stderr, flush } from './io'; | ||
|
||
const queue: Array<() => void> = []; | ||
|
||
/** | ||
* Initialize the gifsicle module | ||
*/ | ||
const initModule = (): Promise<void> => { | ||
return new Promise((resolve) => { | ||
// add a new job to the queue | ||
queue.push(resolve); | ||
|
||
// start it if there is no queue | ||
if (queue.length === 1) { | ||
queue[0](); | ||
} | ||
}); | ||
}; | ||
|
||
/** | ||
* Reset the gifsicle module | ||
*/ | ||
const resetModule = (): void => { | ||
if (queue.length > 0) { | ||
// remove finished job | ||
queue.shift(); | ||
|
||
// trigger next job | ||
if (queue.length > 0) { | ||
queue[0](); | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Encode an input image using Gifsicle | ||
* | ||
* @async | ||
* @param {Buffer} image Image input buffer | ||
* @param {EncodeOptions} encodeOptions Encoding options passed to Gifsicle | ||
* @returns {Buffer} Processed image buffer | ||
*/ | ||
const encode = async (image: Buffer, encodeOptions: EncodeOptions = {}): Promise<Buffer> => { | ||
await initModule(); | ||
|
||
return new Promise((resolve, reject) => { | ||
// merge default options | ||
const filledEncodeOptions = { ...defaultEncodeOptions, ...encodeOptions }; | ||
|
||
// build arguments | ||
const gifsicleArguments = [ | ||
// ignore gifsicle warnings | ||
'--no-warnings', | ||
|
||
// remove application extensions from the input image | ||
'--no-app-extensions', | ||
|
||
// set optimization level | ||
`--optimize=${filledEncodeOptions.optimizationLevel}`, | ||
|
||
// turn on interlacing | ||
filledEncodeOptions.interlaced === true ? '--interlace' : false, | ||
|
||
// set number of colors | ||
typeof filledEncodeOptions.colors === 'number' ? `--colors=${filledEncodeOptions.colors}` : false, | ||
|
||
// resize image | ||
filledEncodeOptions.width || filledEncodeOptions.height | ||
? `--resize ${filledEncodeOptions.width || '_'}x${filledEncodeOptions.height || '_'}` | ||
: false, | ||
|
||
// set input & output file names | ||
'-i', | ||
'/input.gif', | ||
'-o', | ||
'/output.gif', | ||
].filter(Boolean); | ||
|
||
let resolved = false; | ||
|
||
Gifsicle({ | ||
stdout, | ||
stderr, | ||
arguments: gifsicleArguments as string[], | ||
input: new Uint8Array(image.buffer), | ||
output: (res: Uint8Array) => { | ||
resolve(Buffer.from(res)); | ||
resolved = true; | ||
}, | ||
}).then(() => { | ||
flush(); | ||
if (!resolved) { | ||
reject(); | ||
} | ||
resetModule(); | ||
}); | ||
}); | ||
}; | ||
|
||
export default encode; | ||
export type { EncodeOptions } from './types'; | ||
module.exports = encode; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* eslint-disable no-console */ | ||
|
||
let out = ''; | ||
|
||
/** | ||
* Process stdout stream | ||
* | ||
* @param {number} char Next char in stream | ||
*/ | ||
export const stdout = (char: number): void => { | ||
out += String.fromCharCode(char); | ||
|
||
if (char === 10) { | ||
console.log(out); | ||
out = ''; | ||
} | ||
}; | ||
|
||
let err = ''; | ||
|
||
/** | ||
* Process stderr stream | ||
* | ||
* @param {number} char Next char in stream | ||
*/ | ||
export const stderr = (char: number): void => { | ||
err += String.fromCharCode(char); | ||
|
||
if (char === 10) { | ||
console.error(err); | ||
err = ''; | ||
} | ||
}; | ||
|
||
/** | ||
* Flush remaining buffer | ||
*/ | ||
export const flush = (): void => { | ||
if (out.length > 0) { | ||
console.log(out); | ||
out = ''; | ||
} | ||
|
||
if (err.length > 0) { | ||
console.error(err); | ||
err = ''; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { EncodeOptions } from './types'; | ||
|
||
export const defaultEncodeOptions: EncodeOptions = { | ||
optimizationLevel: 3, | ||
interlaced: false, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { GifsicleModule } from './gifsicle'; | ||
|
||
// write input file to FS of WASM before executing gifsicle | ||
Module.preRun = Module.preRun || []; | ||
Module.preRun.push(function writeInputFile() { | ||
const data = (Module as GifsicleModule).input; | ||
FS.writeFile('/input.gif', data); | ||
}); | ||
|
||
// send output file from FS of WASM back to the JS | ||
Module.postRun = Module.postRun || []; | ||
Module.postRun.push(function getOutputFile() { | ||
const data = FS.readFile('/output.gif'); | ||
(Module as GifsicleModule).output(data); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export type EncodeOptions = { | ||
optimizationLevel?: number; | ||
interlaced?: boolean; | ||
colors?: number; | ||
width?: number; | ||
height?: number; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters