Skip to content

Commit

Permalink
Jpeg class is now async!
Browse files Browse the repository at this point in the history
  • Loading branch information
pkrumins committed Aug 9, 2010
1 parent 30fce44 commit 4020d26
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 9 deletions.
14 changes: 14 additions & 0 deletions examples/jpeg-example-async.js
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,14 @@
var fs = require('fs');
var sys = require('sys');
var Jpeg = require('../jpeg').Jpeg;
var Buffer = require('buffer').Buffer;

// the rgba-terminal.dat file is 1152000 bytes long.
var rgba = new Buffer(1152000);
rgba.write(fs.readFileSync('./rgba-terminal.dat', 'binary'), 'binary');

var jpeg = new Jpeg(rgba, 720, 400, 'rgba');
jpeg.encode(function (image) {
fs.writeFileSync('./jpeg-async.jpeg', image, 'binary');
})

2 changes: 1 addition & 1 deletion examples/jpeg-example.js
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var rgba = new Buffer(1152000);
rgba.write(fs.readFileSync('./rgba-terminal.dat', 'binary'), 'binary'); rgba.write(fs.readFileSync('./rgba-terminal.dat', 'binary'), 'binary');


var jpeg = new Jpeg(rgba, 720, 400, 'rgba'); var jpeg = new Jpeg(rgba, 720, 400, 'rgba');
var jpeg_img = jpeg.encode(); var jpeg_img = jpeg.encodeSync();


fs.writeFileSync('./jpeg.jpeg', jpeg_img, 'binary'); fs.writeFileSync('./jpeg.jpeg', jpeg_img, 'binary');


22 changes: 22 additions & 0 deletions examples/jpeg-example2-async.js
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,22 @@
var fs = require('fs');
var sys = require('sys');
var Jpeg = require('../jpeg').Jpeg;
var Buffer = require('buffer').Buffer;

var WIDTH = 400, HEIGHT = 300;

var rgba = new Buffer(WIDTH*HEIGHT*3);

for (var i=0; i<HEIGHT; i++) {
for (var j=0; j<WIDTH; j++) {
rgba[i*WIDTH*3 + j*3 + 0] = 255*j/WIDTH;
rgba[i*WIDTH*3 + j*3 + 1] = 255*i/HEIGHT;
rgba[i*WIDTH*3 + j*3 + 2] = 0xff/2;
}
}

var jpeg = new Jpeg(rgba, WIDTH, HEIGHT, 'rgb');
var jpeg_img = jpeg.encode();

fs.writeFileSync('./jpeg-gradient.jpeg', jpeg_img, 'binary');

2 changes: 1 addition & 1 deletion examples/jpeg-example2.js
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ for (var i=0; i<HEIGHT; i++) {
} }


var jpeg = new Jpeg(rgba, WIDTH, HEIGHT, 'rgb'); var jpeg = new Jpeg(rgba, WIDTH, HEIGHT, 'rgb');
var jpeg_img = jpeg.encode(); var jpeg_img = jpeg.encodeSync();


fs.writeFileSync('./jpeg-gradient.jpeg', jpeg_img, 'binary'); fs.writeFileSync('./jpeg-gradient.jpeg', jpeg_img, 'binary');


9 changes: 8 additions & 1 deletion src/common.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@


using namespace v8; using namespace v8;


Handle<Value>
ErrorException(const char *msg)
{
HandleScope scope;
return Exception::Error(String::New(msg));
}

Handle<Value> Handle<Value>
VException(const char *msg) { VException(const char *msg) {
HandleScope scope; HandleScope scope;
return ThrowException(Exception::Error(String::New(msg))); return ThrowException(ErrorException(msg));
} }


bool str_eq(const char *s1, const char *s2) bool str_eq(const char *s1, const char *s2)
Expand Down
9 changes: 9 additions & 0 deletions src/common.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <node.h> #include <node.h>
#include <cstring> #include <cstring>


v8::Handle<v8::Value> ErrorException(const char *msg);
v8::Handle<v8::Value> VException(const char *msg); v8::Handle<v8::Value> VException(const char *msg);


struct Point { struct Point {
Expand All @@ -26,5 +27,13 @@ unsigned char *bgr_to_rgb(const unsigned char *rgb, int rgb_size);


typedef enum { BUF_RGB, BUF_BGR, BUF_RGBA, BUF_BGRA } buffer_type; typedef enum { BUF_RGB, BUF_BGR, BUF_RGBA, BUF_BGRA } buffer_type;


struct encode_request {
v8::Persistent<v8::Function> callback;
void *jpeg_obj;
char *jpeg;
int jpeg_len;
char *error;
};

#endif #endif


102 changes: 98 additions & 4 deletions src/jpeg.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ Jpeg::Initialize(v8::Handle<v8::Object> target)


Local<FunctionTemplate> t = FunctionTemplate::New(New); Local<FunctionTemplate> t = FunctionTemplate::New(New);
t->InstanceTemplate()->SetInternalFieldCount(1); t->InstanceTemplate()->SetInternalFieldCount(1);
NODE_SET_PROTOTYPE_METHOD(t, "encode", JpegEncode); NODE_SET_PROTOTYPE_METHOD(t, "encode", JpegEncodeAsync);
NODE_SET_PROTOTYPE_METHOD(t, "encodeSync", JpegEncodeSync);
NODE_SET_PROTOTYPE_METHOD(t, "setQuality", SetQuality); NODE_SET_PROTOTYPE_METHOD(t, "setQuality", SetQuality);
target->Set(String::NewSymbol("Jpeg"), t->GetFunction()); target->Set(String::NewSymbol("Jpeg"), t->GetFunction());
} }
Expand All @@ -27,7 +28,7 @@ Jpeg::Jpeg(Buffer *ddata, int wwidth, int hheight, buffer_type bbuf_type) :
jpeg_encoder((unsigned char *)ddata->data(), wwidth, hheight, 60, bbuf_type) {} jpeg_encoder((unsigned char *)ddata->data(), wwidth, hheight, 60, bbuf_type) {}


Handle<Value> Handle<Value>
Jpeg::JpegEncode() Jpeg::JpegEncodeSync()
{ {
HandleScope scope; HandleScope scope;


Expand Down Expand Up @@ -102,12 +103,12 @@ Jpeg::New(const Arguments &args)
} }


Handle<Value> Handle<Value>
Jpeg::JpegEncode(const Arguments &args) Jpeg::JpegEncodeSync(const Arguments &args)
{ {
HandleScope scope; HandleScope scope;


Jpeg *jpeg = ObjectWrap::Unwrap<Jpeg>(args.This()); Jpeg *jpeg = ObjectWrap::Unwrap<Jpeg>(args.This());
return scope.Close(jpeg->JpegEncode()); return scope.Close(jpeg->JpegEncodeSync());
} }


Handle<Value> Handle<Value>
Expand All @@ -134,3 +135,96 @@ Jpeg::SetQuality(const Arguments &args)
return Undefined(); return Undefined();
} }


int
Jpeg::EIO_JpegEncode(eio_req *req)
{
encode_request *enc_req = (encode_request *)req->data;
Jpeg *jpeg = (Jpeg *)enc_req->jpeg_obj;

try {
jpeg->jpeg_encoder.encode();
enc_req->jpeg_len = jpeg->jpeg_encoder.get_jpeg_len();
enc_req->jpeg = (char *)malloc(sizeof(*enc_req->jpeg)*enc_req->jpeg_len);
if (!enc_req->jpeg) {
enc_req->error = strdup("malloc in Jpeg::EIO_JpegEncode failed.");
return 0;
}
else {
memcpy(enc_req->jpeg, jpeg->jpeg_encoder.get_jpeg(), enc_req->jpeg_len);
}
}
catch (const char *err) {
enc_req->error = strdup(err);
}

return 0;
}

int
Jpeg::EIO_JpegEncodeAfter(eio_req *req)
{
HandleScope scope;

ev_unref(EV_DEFAULT_UC);
encode_request *enc_req = (encode_request *)req->data;

Handle<Value> argv[2];

if (enc_req->error) {
argv[0] = Undefined();
argv[1] = ErrorException(enc_req->error);
}
else {
argv[0] = Local<Value>::New(Encode(enc_req->jpeg, enc_req->jpeg_len, BINARY));
argv[1] = Undefined();
}

TryCatch try_catch; // don't quite see the necessity of this

enc_req->callback->Call(Context::GetCurrent()->Global(), 2, argv);

if (try_catch.HasCaught())
FatalException(try_catch);

enc_req->callback.Dispose();
free(enc_req->jpeg);
free(enc_req->error);

((Jpeg *)enc_req->jpeg_obj)->Unref();
free(enc_req);

return 0;
}

Handle<Value>
Jpeg::JpegEncodeAsync(const Arguments &args)
{
HandleScope scope;

if (args.Length() != 1)
return VException("One argument required - callback function.");

if (!args[0]->IsFunction())
return VException("First argument must be a function.");

Local<Function> callback = Local<Function>::Cast(args[0]);
Jpeg *jpeg = ObjectWrap::Unwrap<Jpeg>(args.This());

encode_request *enc_req = (encode_request *)malloc(sizeof(*enc_req));
if (!enc_req)
return VException("malloc in Jpeg::JpegEncodeAsync failed.");

enc_req->callback = Persistent<Function>::New(callback);
enc_req->jpeg_obj = jpeg;
enc_req->jpeg = NULL;
enc_req->jpeg_len = 0;
enc_req->error = NULL;

eio_custom(EIO_JpegEncode, EIO_PRI_DEFAULT, EIO_JpegEncodeAfter, enc_req);

ev_ref(EV_DEFAULT_UC);
jpeg->Ref();

return Undefined();
}

7 changes: 5 additions & 2 deletions src/jpeg.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@
class Jpeg : public node::ObjectWrap { class Jpeg : public node::ObjectWrap {
JpegEncoder jpeg_encoder; JpegEncoder jpeg_encoder;


static int EIO_JpegEncode(eio_req *req);
static int EIO_JpegEncodeAfter(eio_req *req);
public: public:
static void Initialize(v8::Handle<v8::Object> target); static void Initialize(v8::Handle<v8::Object> target);
Jpeg(node::Buffer *ddata, int wwidth, int hheight, buffer_type bbuf_type); Jpeg(node::Buffer *ddata, int wwidth, int hheight, buffer_type bbuf_type);
v8::Handle<v8::Value> JpegEncode(); v8::Handle<v8::Value> JpegEncodeSync();
void SetQuality(int q); void SetQuality(int q);


static v8::Handle<v8::Value> New(const v8::Arguments &args); static v8::Handle<v8::Value> New(const v8::Arguments &args);
static v8::Handle<v8::Value> JpegEncode(const v8::Arguments &args); static v8::Handle<v8::Value> JpegEncodeSync(const v8::Arguments &args);
static v8::Handle<v8::Value> JpegEncodeAsync(const v8::Arguments &args);
static v8::Handle<v8::Value> SetQuality(const v8::Arguments &args); static v8::Handle<v8::Value> SetQuality(const v8::Arguments &args);
}; };


Expand Down
1 change: 1 addition & 0 deletions wscript
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def build(bld):
obj.target = "jpeg" obj.target = "jpeg"
obj.source = "src/common.cpp src/jpeg_encoder.cpp src/jpeg.cpp src/fixed_jpeg_stack.cpp src/dynamic_jpeg_stack.cpp src/module.cpp" obj.source = "src/common.cpp src/jpeg_encoder.cpp src/jpeg.cpp src/fixed_jpeg_stack.cpp src/dynamic_jpeg_stack.cpp src/module.cpp"
obj.uselib = "JPEG" obj.uselib = "JPEG"
obj.cxxflags = ["-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE"]


def shutdown(): def shutdown():
if Options.commands['clean']: if Options.commands['clean']:
Expand Down

0 comments on commit 4020d26

Please sign in to comment.