Skip to content

Commit

Permalink
Merge pull request #31 from randytarampi/feat/support-progressive-jpegs
Browse files Browse the repository at this point in the history
Progressive JPEG support per #29

Closes #29 and EyalAr#245
  • Loading branch information
randytarampi authored Apr 28, 2020
2 parents eda2fde + 32ea2a9 commit 08e9ada
Show file tree
Hide file tree
Showing 10 changed files with 44 additions and 9 deletions.
3 changes: 2 additions & 1 deletion DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,12 @@ a raw pixels buffer and encode it into a jpeg image buffer.
The arguments for the encoding methods differ for each encoding format.
We list them here:

0. JPEG: `encoder.jpeg(pixbuff, width, height, quality, callback)`
0. JPEG: `encoder.jpeg(pixbuff, width, height, quality, progressive, callback)`
0. `pixbuff` - Raw RGBA pixels buffer (a Buffer object)
0. `width` - The with of the image
0. `height` - The height of the image
0. `quality` - JPEG quality (0-100)
0. `progressive` - should produce progressive JPEG (true/false)
0. `callback` - callback function
0. PNG: `encoder.png(pixbuff, width, height, compression, interlaced, trans, callback)`
0. `pixbuff` - Raw RGBA pixels buffer (a Buffer object)
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,7 @@ encoded data as a NodeJS Buffer object.
The `params` object should have the following fields:

- `quality {Integer}`: Defaults to `100`.
- `progressive {Boolean}`: Defaults to `false`.

Note that when encoding to JPEG the alpha channel is discarded.

Expand Down
Binary file added examples/lena_progressive.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions examples/progressive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Example for using LWIP to shift image's hue by 50 degrees.
*/

const lwip = require('../');

lwip.open('lena.jpg', (err, image) => {
if (err) return console.log(err);
image.writeFile('lena_progressive.jpg', 'jpg', { progressive: true },
err => {
if (err) return console.log(err);
console.log('done');
});
});
1 change: 1 addition & 0 deletions lib/Image.js
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,7 @@ module.exports = class Image {
this.__lwip.width(),
this.__lwip.height(),
params.quality,
params.progressive,
encoderCb
);
} else if (type === 'png') {
Expand Down
6 changes: 4 additions & 2 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,10 @@ function normalizeJpegParams(params){
if (params.quality !== 0)
params.quality = params.quality || defs.defaults.DEF_JPEG_QUALITY;
if (params.quality !== parseInt(params.quality) ||
params.quality < 0 || params.quality > 100)
throw Error('Invalid JPEG quality');
params.quality < 0 || params.quality > 100)
throw Error('Invalid JPEG quality');
if (params.progressive) params.progressive = true;
else params.progressive = false;
}

function getClosest2Exp(num){
Expand Down
2 changes: 2 additions & 0 deletions src/encoder/encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class EncodeToJpegBufferWorker : public Nan::AsyncWorker {
size_t width,
size_t height,
int quality,
bool progressive,
Nan::Callback * callback
);
~EncodeToJpegBufferWorker();
Expand All @@ -42,6 +43,7 @@ class EncodeToJpegBufferWorker : public Nan::AsyncWorker {
int _quality;
char * _jpegbuf;
size_t _jpegbufsize;
bool _progressive;
};

class EncodeToPngBufferWorker : public Nan::AsyncWorker {
Expand Down
6 changes: 4 additions & 2 deletions src/encoder/init.cpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
#include "encoder.h"

// encoder.jpeg(pixbuf, width, height, quality, callback)
// encoder.jpeg(pixbuf, width, height, quality, progressive, callback)
NAN_METHOD(encodeToJpegBuffer) {
Nan::HandleScope();

Local<Object> buff = info[0].As<Object>();
size_t width = info[1].As<Integer>()->Value();
size_t height = info[2].As<Integer>()->Value();
int quality = info[3].As<Integer>()->Value();
Nan::Callback * callback = new Nan::Callback(info[4].As<Function>());
bool progressive = info[4].As<Boolean>()->Value();
Nan::Callback * callback = new Nan::Callback(info[5].As<Function>());

Nan::AsyncQueueWorker(
new EncodeToJpegBufferWorker(
buff,
width,
height,
quality,
progressive,
callback
));
}
Expand Down
7 changes: 6 additions & 1 deletion src/encoder/jpeg_worker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ EncodeToJpegBufferWorker::EncodeToJpegBufferWorker(
size_t width,
size_t height,
int quality,
bool progressive,
Nan::Callback * callback
): Nan::AsyncWorker(callback), _width(width), _height(height),
_quality(quality), _jpegbuf(NULL), _jpegbufsize(0) {
_quality(quality), _jpegbuf(NULL), _jpegbufsize(0), _progressive(progressive) {
SaveToPersistent("buff", buff); // make sure buff isn't GC'ed
_pixbuf = (unsigned char *) Buffer::Data(buff);
}
Expand Down Expand Up @@ -45,8 +46,12 @@ void EncodeToJpegBufferWorker::Execute () {
cinfo.image_height = _height;
cinfo.input_components = dimbuf;
cinfo.in_color_space = colortype;
cinfo.progressive_mode = (boolean)_progressive;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, _quality, TRUE);
if (_progressive) {
jpeg_simple_progression(&cinfo);
}
jpeg_start_compress(&cinfo, TRUE);

// shared memory cimg. no new memory is allocated.
Expand Down
13 changes: 10 additions & 3 deletions tests/02.operations/101.writeFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ describe('lwip.writeFile', () => {
});
});

describe('params specified progressive=true', function() {
it('should succeed', function(done) {
image.writeFile(outpathJpeg, {
progressive: true
}, done);
});
});

});

describe('with type specified', () => {
Expand All @@ -64,13 +72,12 @@ describe('lwip.writeFile', () => {
describe('params specified', () => {
it('should succeed', done => {
image.writeFile(outpathJpeg, 'jpeg', {
quality: 20
quality: 20,
progressive: true,
}, done);
});
});

});

});

describe('png', () => {
Expand Down

0 comments on commit 08e9ada

Please sign in to comment.