node-webpmux
A mostly-complete pure Javascript re-implementation of webpmux.
Can load "simple" lossy/lossless images as well as animations.
Install
npm install node-webpmux
Basic usage
const WebP = require('node-webpmux');
let img = new WebP.Image();
await img.load('img.webp');
await img.demux('.', { frame: 3 });
await img.replaceFrame(3, 'different.webp');
await img.save({ path: 'newimg.webp' });
Exports
TYPE_LOSSY
TYPE_LOSSLESS
TYPE_EXTENDED
Constants for what type of image is loaded.
encodeResults
: enum of values that set[Image/Frame]Data returns.
Image
: The main class.
Class definition:
Class properties
.width
(read-only)
The width of the loaded image.
.height
(read-only)
The height of the loaded image.
.type
(read-only)
The type of image from the TYPE_* constants table.
.hasAnim
(read-only)
A boolean flag for easily checking if the image is an animation.
.hasAlpha
(read-only)
A boolean flag for easily checking if the image has transparency in any way.
.frames
(read-only)
Returns the array of frames, if any, or undefined.
Note that while the frames themselves are read/write, you shouldn't modify them.
.frameCount
(read-only)
The number of frames in the image's animation, or 0 if it's not an animation.
.anim
(read-only)
Direct access to the raw animation data (see below in the Layout for internal Image data section).
.iccp
(read/write)
A Buffer containing the raw ICCP data stored in the image, or undefined if there isn't any.
.exif
(read/write)
A Buffer containing the raw EXIF data stored in the image, or undefined if there isn't any.
.xmp
(read/write)
A Buffer containing the raw XMP data stored in the image, or undefined if there isn't any.
Image member functions
async .initLib()
Calls Image.initLib(). This member function is no longer particularly useful and is kept for convenience.
async .load(source)
If source
is a string, it tries to load that as a path to a WebP image.
If source
is a buffer, it tries to load the contents of the buffer as a WebP image.
.convertToAnim()
Sets the image up for being an animation.
async .demux({ path = undefined, buffers = false, frame = -1, prefix = '#FNAME#', start = 0, end = 0 })
Dump the individual, unprocessed WebP frames to a directory.
path
: The directory to dump the frames to, if desired.buffers
: Return the frames as an array of Buffers instead of dumping to a path.prefix
: What to prefix the frame names with. Default is the file name of the original image (without .webp).
Format is <prefix>_<frame number>.webp.frame
: What frame to dump. Defaults to -1, which has it dump all available frames. Overrides start
/end
.start
: The first frame to dump. Defaults to the first frame.end
: The last frame to dump. Defaults to the last frame.
async .replaceFrame(frameIndex, source)
Replaces a frame in the animation with another image from source
. All other frame settings are preserved.
frameIndex
: Which frame to replace. Frame indexes are 0-based.source
: If this is a string, the frame is loaded from disk. If this is a Buffer, the frame is loaded from there.
async .save(path = this.path, options)
Save the image to path
. Options are described below in the Options for saving section.
If path
is null
, this will save the image to a Buffer and return it.
async .getImageData()
Get the raw RGBA pixel data for the image.
Returns a Buffer in the format [ r, g, b, a, r, g, b, a, ... ]
. Values are range 0 - 255.
Use this for non-animations.
On error, this returns a Buffer full of 0s.
async .setImageData(buffer, { width = 0, height = 0, preset = 0, quality = 75, exact = false, lossless = 0, method = 4, advanced = undefined })
Encode buf
as a new WebP using the provided settings and replace the image pixel data with it.
This preserves EXIF/ICCP/XMP if present.
Use this for non-animations.
buffer
: A Buffer object with the raw pixels in RGBA order.
Options:width
/height
If either are > 0, override the existing width and/or height with this value.
Use this if the pixel data in buf
has different dimensions than the original image.preset
: What image preset to use, if any.
Range is 0 - 5
Default is 0 (DEFAULT).
An enum of constants can be found under WebP.presetsquality
: What quality to set.
Range is 0 - 100.
Default is 75.exact
: Preserve data in transparent pixels.
Defaults to false
, which means transparent pixels may be modified to help with compression.lossless
: Save the data as a lossy/lossless image.
Range is 0 - 9.
Default is 0 (lossy).
Higher values will result in smaller files, but requires more processing time.method
: Compression method to use.
Range is 0 - 6.
Default is 4.
Higher values will result in smaller files, but requires more processing time.advanced
: Access to more advanced encoding settings offered by libwebp
-
imageHint
: Hint for what type of image it is (only used for lossless encoding for now, according to libwebp spec).
Range is 0 - 3.
Default is 0 (DEFAULT).
An enum of constants can be found under WebP.hints
-
targetSize
: Specifies the desired target size in bytes.
Default is 0 (no target).
Takes precedence over the method
parameter.
-
targetPSNR
: Specifies the minimum distortion to try to achieve.
Default is 0 (no target).
Takes precedence over the targetSize
parameter.
-
segments
: Maximum number of segments to use.
Range is 1 - 4.
Default is 4.
-
snsStrength
: Spacial Noise Shaping.
Range is 0 - 100.
Default is 50.
-
filterStrength
Range is 0 - 100.
Default is 0 (off).
-
filterSharpness
Range is 0 - 7, with 7 being the least sharp.
Default is 0 (off).
-
filterType
Range is 0 - 1.
Default is 1.
0 is simple; 1 is strong.
Only used if filterStrength
> 0 or autoFilter
> 0.
-
autoFilter
: Auto-adjust the filter's strength.
Range is 0 - 1.
Default is 0 (off).
-
alphaCompression
: Algorithm for encoding the alpha plane.
Range is 0 - 1.
Default is 1 (Lossless).
0 is off; 1 is lossless.
-
alphaFiltering
: Predictive filtering method for alpha place.
Range is 0 - 2.
Default is 1 (Fast).
0 is none; 1 is fast; 2 is best
-
alphaQuality
Range is 0 - 100.
Default is 100.
-
pass
: Number of entropy-analysis passes.
Range is 1 - 10.
Default is 1.
-
showCompressed
: Export the compressed picture back.
Range is 0 - 1.
Default is 0 (don't).
In-loop filtering is not applied.
-
preprocessing
: Preprocessing filter.
Range is 0 - 2.
Default is 0 (None).
0 is none; 1 is segment-smooth; 2 is pseudo-random dithering.
-
partitions
: log2(number of token partitions).
Range is 0 - 3.
Default is 0.
Higher values result in harder progressive decoding.
-
partitionLimit
: Quality degredation allowed to fit the 512k limit on prediction modes coding.
Range is 0 - 100.
Default is 0.
-
emulateJpegSize
: Compression parameters are remapped to better mat the expected output size from JPEG compression.
Range is 0 - 1.
Default is 0 (Off).
Generally, the output size will be smaller but the degredation will be lower.
-
threadLevel
: Try to use multi-threaded encoding.
Default is 0 (Off).
NOTE: Currently the WebAssembly is NOT compiled with support for threads, so this option does nothing.
NodeJS doesn't support threads in WebAssembly without an experimental flag, and my testing with it didn't appear to use threads regardless.
-
lowMemory
: Reduce memory usage but increase CPU use.
Range is 0 - 1.
Default is 0 (Off).
-
nearLossless
: Near lossless encoding.
Range is 0 - 100.
Default is 100 (off).
0 is max loss, 100 is off.
-
useDeltaPalette
: Reserved for future lossless feature.
Range is 0 - 0.
Default is 0 (Off).
Setting this will do nothing, as it's forced back to 0.
-
useSharpYUV
: Use sharp (and slow) RGB->YUV conversion.
Range is 0 - 1.
Default is 0 (Off).
-
qMin
: Minimum permissible quality factor.
Range is 0 - 100.
Default is 0.
-
qMax
: Maximum permissible quality factor.
Range is 0 - 100.
Default is 100.
If lossless
is set above 0, then setting quality
or method
is discouraged as they will override settings in the lossless preset.
Return value can be checked against the values in WebP.encodeResults
.
async .getFrameData(frameIndex)
Get the raw RGBA pixel data for a specific frame.
Use this for animations.
frameIndex
: Which frame to get. Frame indexes are 0-based.
Otherwise identical to .getImageData()
async .setFrameData(frameIndex, buffer, { width = 0, height = 0, preset = 0, quality = 75, exact = false, lossless = 0, method = 4, advanced = undefined })
Encode buffer
as a new WebP using the provided settings and replace an existing frame's pixel data with it.
Use this for animations.
frameIndex
: Which frame to get. Frame indexes are 0-based.
Otherwise identical to .setImageData()
.
Static functions
async Image.initLib()
Initialize the internal library used for [get/set]ImageData and [get/set]FrameData described above.
There is no need to call this unless you plan to use one of those 4 functions.
Image.from(webp)
Use the contents of webp
and return a new Image using them.
Mainly useful for passing Image into a Web Worker or NodeJS Worker and converting the passed object back into an Image instance.
Such an approach can be used to greatly speed up saving of animations or multiple images as libwebp is not multi-threaded beyond saving the alpha layer of lossy images.
async Image.save(path, options)
Save the options
using Image.getEmptyImage()
.
Works the same as .save()
otherwise.
Can be used to create an animation from scratch by passing frames
in options
.
Example: Image.save('animation.webp', { frames: ... })
for saving to file
OR
Example: Image.save(null, { frames: ... })
for saving to Buffer
async Image.getEmptyImage(ext)
Returns a basic, lossy 1x1 black image with no alpha or metadata.
Useful if you need to create a WebP from scratch, such as when converting from PNG.
.setImageData()
would be used to change the canvas size/contents.
Set ext
to true
to force the image to be an extended type, if desired. This is mainly for use internally.
async Image.generateFrame({ path = undefined, buffer = undefined, img = undefined, x = undefined, y = undefined, delay = undefined, blend = undefined, dispose = undefined })
Generates enough of an anmf
structure to be placed in .frames
.
Note that, at the moment, only static images are supported in this function.
path
/buffer
/img
Only one of these can be present.
path
will load image data from file.
buffer
will load from the buffer.
img
will use an existing Image instance.x
/y
/delay
/blend
/dispose
Explicitly set these properties. See the Options for saving section for what these do.
Options for saving
These options affect both static images and animations
exif
/iccp
/xmp
Save or override EXIF/ICCP/XMP chunks.
Pass true
to save the existing ones, or pass a Buffer to replace them.
Note that there is no verification whatsoever that the data passed is valid.
The options below are only used when saving an animation:
width
/height
: Width/height of the image.
Range 0 - 16777216.
The product of width*height must NOT exceed (2 ** 32) - 1.
Passing 0 to either flags it for being set automatically.bgColor
: The background color of the animation.
Format is [ r, g, b, a ].
Defaults to [ 255, 255, 255, 255 ].loops
: Number of times the animation loops.
Range is 0 - 65535, with 0 being an infinite loop.
Default is 0.x
/y
/delay
/blend
/dispose
: Changes the default frame x/y position where a frame omits it (see below).-
-
-
-
dispose
defaults to false
.
-
frames
: An array of objects defining each frame of the animation with the following properties.
-
-
x
/y
: x, y offset to place the frame within the animation.
Range 0 - 16777215.
Default is 0,0 (defined above).
-
-
delay
: Length of this frame in miliseconds.
Range 0 - 16777215.
Default is 100 (defined above).
According to the documentation, delays <= 10ms are WebP implementation defined, and many tools/browsers/etc assign their own minimum-allowed delay.
-
-
blend
: Boolean flag for whether or not to use alpha blending when drawing the frame.
Default is true
(defined above).
-
-
dispose
: Boolean flag to control frame disposal method.
true
causes the background color to be drawn under the frame.
false
draws the new frame directly.
Default is false
(defined above).
Information about the internal library
[get/set]ImageData and [get/set]FrameData are powered by Google's official libwebp library obtained from the GitHub mirror.
Commit 89c5b91 was the latest at the time of compilation.
This library was compiled with Emscripten with the command emcc -O3 -s WASM=1 -s MODULARIZE -s EXPORTED_RUNTIME_METHODS='[cwrap]' -s ALLOW_MEMORY_GROWTH=1 -s EXPORT_NAME=LibWebP -DHAVE_CONFIG_H -I libwebp binding.cpp libwebp/src/{dec,dsp,demux,enc,mux,utils}/*.c libwebp/sharpyuv/*.c --bind -o libwebp.js
.
binding.cpp is a shim I wrote to bridge the needed parts together and can be found in the libwebp/ directory.
libwebp.js, found in the root, is the Javascript interface to it.
At present, the only options for encoding are setting the lossless preset, quality, method, and exact flag.
If access to other options is desired (see upstream libwebp/src/webp/encode.h, struct WebPConfig for settings), leave a feature request and I'll add it.
The upstream command line tool cwebp
can be used to play with the features and see what you find useful.
Layout for internal Image data
{
path,
loaded,
data: {
type,
vp8: {
raw,
width, height
},
vp8l: {
raw,
alpha,
width, height
},
extended: {
raw,
hasICCP,
hasAlpha,
hasEXIF,
hasXMP,
hasAnim,
width, height
},
anim: {
raw,
bgColor,
loops,
frames: [
{
raw,
type,
x, y,
width, height,
delay,
blend, dispose,
vp8,
vp8l,
alph
},
...
]
},
alph: {
raw
},
iccp: {
raw
},
exif: {
raw
},
xmp: {
raw
}
}
}
Breaking changes from 1.x
Image.muxAnim and .muxAnim were merged into Image.save and .save respectively.
- Replace
Image.muxAnim({ path, frames, width, height, bgColor, loops, delay, x, y, blend, dispose, exif, iccp, xmp })
- With
Image.save(path, undefined, { frames, width, height, bgColor, loops, delay, x, y, blend, dispose, exif, iccp, xmp })
- Replace
.muxAnim({ path, width, height, bgColor, loops, delay, x, y, blend, dispose, exif, iccp, xmp })
- With
.save(path, { width, height, bgColor, loops, delay, x, y, blend, dispose, exif, iccp, xmp })
.anim.backgroundColor
renamed to .anim.bgColor
for brevity and consisteny.
.anim.loopCount
renamed to .anim.loop
for consistency.
.anim.frameCount
and .frameCount
were removed. Should use .anim.frames.length
and .frames.length
respectively instead.
.demuxAnim()
was renamed to .demux()
Breaking changes from 2.0.0 to 2.0.1
Image.generateFrame()'s duration
input renamed to delay
Breaking changes from 2.x to 3.0.0
File and buffer codepaths have been merged.
- Replace
.loadBuffer(buffer)
- With
.load(buffer)
- Replace
Image.loadBuffer(buffer)
- With
Image.load(buffer)
- Replace
.saveBuffer(settings)
- With
.save(null, settings)
- Replace
Image.saveBuffer(settings)
- With
Image.save(null, settings)
- Note that it's specifically
null
here. This is because the default behavior of .save() is still saving to the path it was loaded from.
- Replace
.demuxToBuffers({ setting, setting, ... })
- With
.demux({ buffers: true, setting, setting, ... })
- Replace
.demux(path, settings)
- With
.demux({ path, setting, setting, ... })
- Replace
.replaceFrameBuffer(frame, buffer)
- With
.replaceFrame(frame, buffer)