Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Jpeg class is now async!

  • Loading branch information...
commit 4020d264f7495af27c2c37cf914c23a67c698b33 1 parent 30fce44
@pkrumins authored
View
14 examples/jpeg-example-async.js
@@ -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');
+})
+
View
2  examples/jpeg-example.js
@@ -8,7 +8,7 @@ var rgba = new Buffer(1152000);
rgba.write(fs.readFileSync('./rgba-terminal.dat', 'binary'), 'binary');
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');
View
22 examples/jpeg-example2-async.js
@@ -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');
+
View
2  examples/jpeg-example2.js
@@ -16,7 +16,7 @@ for (var i=0; i<HEIGHT; i++) {
}
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');
View
9 src/common.cpp
@@ -5,9 +5,16 @@
using namespace v8;
Handle<Value>
+ErrorException(const char *msg)
+{
+ HandleScope scope;
+ return Exception::Error(String::New(msg));
+}
+
+Handle<Value>
VException(const char *msg) {
HandleScope scope;
- return ThrowException(Exception::Error(String::New(msg)));
+ return ThrowException(ErrorException(msg));
}
bool str_eq(const char *s1, const char *s2)
View
9 src/common.h
@@ -4,6 +4,7 @@
#include <node.h>
#include <cstring>
+v8::Handle<v8::Value> ErrorException(const char *msg);
v8::Handle<v8::Value> VException(const char *msg);
struct Point {
@@ -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;
+struct encode_request {
+ v8::Persistent<v8::Function> callback;
+ void *jpeg_obj;
+ char *jpeg;
+ int jpeg_len;
+ char *error;
+};
+
#endif
View
102 src/jpeg.cpp
@@ -18,7 +18,8 @@ Jpeg::Initialize(v8::Handle<v8::Object> target)
Local<FunctionTemplate> t = FunctionTemplate::New(New);
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);
target->Set(String::NewSymbol("Jpeg"), t->GetFunction());
}
@@ -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) {}
Handle<Value>
-Jpeg::JpegEncode()
+Jpeg::JpegEncodeSync()
{
HandleScope scope;
@@ -102,12 +103,12 @@ Jpeg::New(const Arguments &args)
}
Handle<Value>
-Jpeg::JpegEncode(const Arguments &args)
+Jpeg::JpegEncodeSync(const Arguments &args)
{
HandleScope scope;
Jpeg *jpeg = ObjectWrap::Unwrap<Jpeg>(args.This());
- return scope.Close(jpeg->JpegEncode());
+ return scope.Close(jpeg->JpegEncodeSync());
}
Handle<Value>
@@ -134,3 +135,96 @@ Jpeg::SetQuality(const Arguments &args)
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();
+}
+
View
7 src/jpeg.h
@@ -9,14 +9,17 @@
class Jpeg : public node::ObjectWrap {
JpegEncoder jpeg_encoder;
+ static int EIO_JpegEncode(eio_req *req);
+ static int EIO_JpegEncodeAfter(eio_req *req);
public:
static void Initialize(v8::Handle<v8::Object> target);
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);
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);
};
View
1  wscript
@@ -19,6 +19,7 @@ def build(bld):
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.uselib = "JPEG"
+ obj.cxxflags = ["-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE"]
def shutdown():
if Options.commands['clean']:
Please sign in to comment.
Something went wrong with that request. Please try again.