diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..979cfa6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +build +examples/*.jpeg +examples/*.jpg +node_modules +bindings + diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..5eb4a7f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +before_install: [] +env: + global: [] +install: + - 'a() { set -e; }' + - "z() { E=$?; test $E -eq 0 && return 0; printf \"\\n\\033[1;31mThe command failed with exit code $?.\\033[0m\"; set -e; return $E; }" + - (a; npm install );z +script: + - (a; npm test );z +git: + depth: 10 +language: objective-c +notifications: + email: false +matrix: + fast_finish: true diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..4c2269d --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,11 @@ +environment: + global: {} +init: [] +install: + - cmd: 'setlocal & npm install & endlocal' +build_script: + - cmd: 'setlocal & npm test & endlocal' +clone_depth: 10 +cache: + - '%CYG_CACHE%' +test: 'off' diff --git a/binding.gyp b/binding.gyp index 49570ce..db9f683 100644 --- a/binding.gyp +++ b/binding.gyp @@ -10,6 +10,9 @@ "src/dynamic_jpeg_stack.cpp", "src/module.cpp", ], + "include_dirs" : [ + "=0.1.93" - }, - "scripts": { - "install": "node-gyp configure build" - } + "name": "jpeg", + "version": "2.0.0", + "main": "bindings/jpeg", + "description": "A C++ module for node-js that converts RGB and RGBA buffers to a JPEG images (in memory).", + "keywords": [ + "jpg", + "rgba", + "rgb", + "image", + "picture" + ], + "author": { + "name": "Peteris Krumins", + "email": "peteris.krumins@gmail.com", + "web": "http://www.catonmat.net", + "twitter": "pkrumins" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "http://github.com/pkrumins/node-jpeg.git" + }, + "directories": { + "examples": "examples", + "src": "src" + }, + "engines": { + "node": ">=0.1.93" + }, + "scripts": { + "install": "node-gyp configure build" + }, + "dependencies": { + "nan": "^1.7.0", + "node-pre-gyp": "0.6.x" + }, + "devDependencies": { + "aws-sdk": "~2.0.0-rc.15" + }, + "bundledDependencies": [ + "node-pre-gyp" + ], + "scripts": { + "install": "node-pre-gyp install --fallback-to-build" + }, + "binary": { + "module_name": "jpeg", + "module_path": "./bindings", + "host": "https://tessel-builds.s3-us-west-2.amazonaws.com", + "remote_path": "./pre-gyp/{name}/v{version}" + } } - diff --git a/src/buffer_compat.cpp b/src/buffer_compat.cpp index 24dac9c..e517619 100644 --- a/src/buffer_compat.cpp +++ b/src/buffer_compat.cpp @@ -19,14 +19,14 @@ size_t BufferLength(node::Buffer *b) { char *BufferData(v8::Local buf_obj) { - v8::HandleScope scope; + NanScope(); node::Buffer *buf = node::ObjectWrap::Unwrap(buf_obj); return buf->data(); } size_t BufferLength(v8::Local buf_obj) { - v8::HandleScope scope; + NanScope(); node::Buffer *buf = node::ObjectWrap::Unwrap(buf_obj); return buf->length(); } @@ -45,13 +45,13 @@ size_t BufferLength(node::Buffer *b) { char *BufferData(v8::Local buf_obj) { - v8::HandleScope scope; + NanScope(); return node::Buffer::Data(buf_obj); } size_t BufferLength(v8::Local buf_obj) { - v8::HandleScope scope; + NanScope(); return node::Buffer::Length(buf_obj); } diff --git a/src/buffer_compat.h b/src/buffer_compat.h deleted file mode 100644 index fa7c61c..0000000 --- a/src/buffer_compat.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef buffer_compat_h -#define buffer_compat_h - -#include -#include -#include - -char *BufferData(node::Buffer *b); -size_t BufferLength(node::Buffer *b); - -char *BufferData(v8::Local buf_obj); -size_t BufferLength(v8::Local buf_obj); - - -#endif // buffer_compat_h diff --git a/src/common.cpp b/src/common.cpp index 968f4a1..5f7dc1d 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -4,22 +4,9 @@ using namespace v8; -Handle -ErrorException(const char *msg) -{ - HandleScope scope; - return Exception::Error(String::New(msg)); -} - -Handle -VException(const char *msg) { - HandleScope scope; - return ThrowException(ErrorException(msg)); -} - bool str_eq(const char *s1, const char *s2) { - return strcmp(s1, s2) == 0; + return strcmp(s1, s2) == 0; } unsigned char * diff --git a/src/common.h b/src/common.h index d172fc6..8ef1138 100644 --- a/src/common.h +++ b/src/common.h @@ -1,11 +1,15 @@ #ifndef COMMON_H #define COMMON_H +#include #include #include -v8::Handle ErrorException(const char *msg); -v8::Handle VException(const char *msg); +using v8::Handle; +using v8::Number; +using v8::Value; +using v8::Persistent; +using v8::Function; struct Point { int x, y; @@ -28,7 +32,7 @@ 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 callback; + NanCallback* callback; void *jpeg_obj; char *jpeg; int jpeg_len; diff --git a/src/dynamic_jpeg_stack.cpp b/src/dynamic_jpeg_stack.cpp index 3bc4eaa..c193e52 100644 --- a/src/dynamic_jpeg_stack.cpp +++ b/src/dynamic_jpeg_stack.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -7,17 +8,20 @@ #include "common.h" #include "dynamic_jpeg_stack.h" #include "jpeg_encoder.h" -#include "buffer_compat.h" -using namespace v8; -using namespace node; +using v8::Object; +using v8::Handle; +using v8::Local; +using v8::Function; +using v8::FunctionTemplate; +using v8::String; void DynamicJpegStack::Initialize(v8::Handle target) { - HandleScope scope; + NanScope(); - Local t = FunctionTemplate::New(New); + Local t = NanNew(New); t->InstanceTemplate()->SetInternalFieldCount(1); NODE_SET_PROTOTYPE_METHOD(t, "encode", JpegEncodeAsync); NODE_SET_PROTOTYPE_METHOD(t, "encodeSync", JpegEncodeSync); @@ -26,7 +30,7 @@ DynamicJpegStack::Initialize(v8::Handle target) NODE_SET_PROTOTYPE_METHOD(t, "setBackground", SetBackground); NODE_SET_PROTOTYPE_METHOD(t, "setQuality", SetQuality); NODE_SET_PROTOTYPE_METHOD(t, "dimensions", Dimensions); - target->Set(String::NewSymbol("DynamicJpegStack"), t->GetFunction()); + target->Set(NanNew("DynamicJpegStack"), t->GetFunction()); } DynamicJpegStack::DynamicJpegStack(buffer_type bbuf_type) : @@ -64,20 +68,11 @@ DynamicJpegStack::update_optimal_dimension(int x, int y, int w, int h) Handle DynamicJpegStack::JpegEncodeSync() { - HandleScope scope; - - try { - JpegEncoder jpeg_encoder(data, bg_width, bg_height, quality, BUF_RGB); - jpeg_encoder.setRect(Rect(dyn_rect.x, dyn_rect.y, dyn_rect.w, dyn_rect.h)); - jpeg_encoder.encode(); - int jpeg_len = jpeg_encoder.get_jpeg_len(); - Buffer *retbuf = Buffer::New(jpeg_len); - memcpy(Buffer::Data(retbuf), jpeg_encoder.get_jpeg(), jpeg_len); - return scope.Close(retbuf->handle_); - } - catch (const char *err) { - return VException(err); - } + JpegEncoder jpeg_encoder(data, bg_width, bg_height, quality, BUF_RGB); + jpeg_encoder.setRect(Rect(dyn_rect.x, dyn_rect.y, dyn_rect.w, dyn_rect.h)); + jpeg_encoder.encode(); + Handle retbuf = NanNewBufferHandle((const char*) jpeg_encoder.get_jpeg(), jpeg_encoder.get_jpeg_len()); + return retbuf; } void @@ -192,85 +187,93 @@ DynamicJpegStack::Reset() Handle DynamicJpegStack::Dimensions() { - HandleScope scope; - - Local dim = Object::New(); - dim->Set(String::NewSymbol("x"), Integer::New(dyn_rect.x)); - dim->Set(String::NewSymbol("y"), Integer::New(dyn_rect.y)); - dim->Set(String::NewSymbol("width"), Integer::New(dyn_rect.w)); - dim->Set(String::NewSymbol("height"), Integer::New(dyn_rect.h)); - - return scope.Close(dim); + Handle dim = NanNew(); + dim->Set(NanNew("x"), NanNew(dyn_rect.x)); + dim->Set(NanNew("y"), NanNew(dyn_rect.y)); + dim->Set(NanNew("width"), NanNew(dyn_rect.w)); + dim->Set(NanNew("height"), NanNew(dyn_rect.h)); + return dim; } -Handle -DynamicJpegStack::New(const Arguments &args) +NAN_METHOD(DynamicJpegStack::New) { - HandleScope scope; + NanScope(); - if (args.Length() > 1) - return VException("One argument max - buffer type."); + if (args.Length() > 1) { + NanThrowError("One argument max - buffer type."); + } buffer_type buf_type = BUF_RGB; if (args.Length() == 1) { - if (!args[0]->IsString()) - return VException("First argument must be a string. Either 'rgb', 'bgr', 'rgba' or 'bgra'."); + if (!args[0]->IsString()) { + NanThrowError("First argument must be a string. Either 'rgb', 'bgr', 'rgba' or 'bgra'."); + } - String::AsciiValue bt(args[0]->ToString()); + NanUtf8String bt(args[0]->ToString()); if (!(str_eq(*bt, "rgb") || str_eq(*bt, "bgr") || str_eq(*bt, "rgba") || str_eq(*bt, "bgra"))) { - return VException("Buffer type must be 'rgb', 'bgr', 'rgba' or 'bgra'."); + NanThrowError("Buffer type must be 'rgb', 'bgr', 'rgba' or 'bgra'."); } - if (str_eq(*bt, "rgb")) + if (str_eq(*bt, "rgb")) { buf_type = BUF_RGB; - else if (str_eq(*bt, "bgr")) + } else if (str_eq(*bt, "bgr")) { buf_type = BUF_BGR; - else if (str_eq(*bt, "rgba")) + } else if (str_eq(*bt, "rgba")) { buf_type = BUF_RGBA; - else if (str_eq(*bt, "bgra")) + } else if (str_eq(*bt, "bgra")) { buf_type = BUF_BGRA; - else - return VException("Buffer type wasn't 'rgb', 'bgr', 'rgba' or 'bgra'."); + } else { + NanThrowError("Buffer type wasn't 'rgb', 'bgr', 'rgba' or 'bgra'."); + } } DynamicJpegStack *jpeg = new DynamicJpegStack(buf_type); jpeg->Wrap(args.This()); - return args.This(); + NanReturnThis(); } -Handle -DynamicJpegStack::JpegEncodeSync(const Arguments &args) +NAN_METHOD(DynamicJpegStack::JpegEncodeSync) { - HandleScope scope; + NanScope(); DynamicJpegStack *jpeg = ObjectWrap::Unwrap(args.This()); - return scope.Close(jpeg->JpegEncodeSync()); + try { + NanReturnValue(jpeg->JpegEncodeSync()); + } + catch (const char *err) { + NanThrowError(err); + } } -Handle -DynamicJpegStack::Push(const Arguments &args) +NAN_METHOD(DynamicJpegStack::Push) { - HandleScope scope; + NanScope(); - if (args.Length() != 5) - return VException("Five arguments required - buffer, x, y, width, height."); + if (args.Length() != 5) { + NanThrowError("Five arguments required - buffer, x, y, width, height."); + } - if (!Buffer::HasInstance(args[0])) - return VException("First argument must be Buffer."); - if (!args[1]->IsInt32()) - return VException("Second argument must be integer x."); - if (!args[2]->IsInt32()) - return VException("Third argument must be integer y."); - if (!args[3]->IsInt32()) - return VException("Fourth argument must be integer w."); - if (!args[4]->IsInt32()) - return VException("Fifth argument must be integer h."); + if (!node::Buffer::HasInstance(args[0])) { + NanThrowError("First argument must be Buffer."); + } + if (!args[1]->IsInt32()) { + NanThrowError("Second argument must be integer x."); + } + if (!args[2]->IsInt32()) { + NanThrowError("Third argument must be integer y."); + } + if (!args[3]->IsInt32()) { + NanThrowError("Fourth argument must be integer w."); + } + if (!args[4]->IsInt32()) { + NanThrowError("Fifth argument must be integer h."); + } DynamicJpegStack *jpeg = ObjectWrap::Unwrap(args.This()); if (!jpeg->data) - return VException("No background has been set, use setBackground or setSolidBackground to set."); + NanThrowError("No background has been set, use setBackground or setSolidBackground to set."); Local data_buf = args[0]->ToObject(); int x = args[1]->Int32Value(); @@ -278,41 +281,48 @@ DynamicJpegStack::Push(const Arguments &args) int w = args[3]->Int32Value(); int h = args[4]->Int32Value(); - if (x < 0) - return VException("Coordinate x smaller than 0."); - if (y < 0) - return VException("Coordinate y smaller than 0."); - if (w < 0) - return VException("Width smaller than 0."); - if (h < 0) - return VException("Height smaller than 0."); - if (x >= jpeg->bg_width) - return VException("Coordinate x exceeds DynamicJpegStack's background dimensions."); - if (y >= jpeg->bg_height) - return VException("Coordinate y exceeds DynamicJpegStack's background dimensions."); - if (x+w > jpeg->bg_width) - return VException("Pushed fragment exceeds DynamicJpegStack's width."); - if (y+h > jpeg->bg_height) - return VException("Pushed fragment exceeds DynamicJpegStack's height."); - - jpeg->Push((unsigned char *)Buffer::Data(data_buf), x, y, w, h); - - return Undefined(); + if (x < 0) { + NanThrowError("Coordinate x smaller than 0."); + } + if (y < 0) { + NanThrowError("Coordinate y smaller than 0."); + } + if (w < 0) { + NanThrowError("Width smaller than 0."); + } + if (h < 0) { + NanThrowError("Height smaller than 0."); + } + if (x >= jpeg->bg_width) { + NanThrowError("Coordinate x exceeds DynamicJpegStack's background dimensions."); + } + if (y >= jpeg->bg_height) { + NanThrowError("Coordinate y exceeds DynamicJpegStack's background dimensions."); + } + if (x+w > jpeg->bg_width) { + NanThrowError("Pushed fragment exceeds DynamicJpegStack's width."); + } + if (y+h > jpeg->bg_height) { + NanThrowError("Pushed fragment exceeds DynamicJpegStack's height."); + } + + jpeg->Push((unsigned char *)node::Buffer::Data(data_buf), x, y, w, h); + + NanReturnUndefined(); } -Handle -DynamicJpegStack::SetBackground(const Arguments &args) +NAN_METHOD(DynamicJpegStack::SetBackground) { - HandleScope scope; + NanScope(); if (args.Length() != 3) - return VException("Four arguments required - buffer, width, height"); - if (!Buffer::HasInstance(args[0])) - return VException("First argument must be Buffer."); + NanThrowError("Four arguments required - buffer, width, height"); + if (!node::Buffer::HasInstance(args[0])) + NanThrowError("First argument must be Buffer."); if (!args[1]->IsInt32()) - return VException("Second argument must be integer width."); + NanThrowError("Second argument must be integer width."); if (!args[2]->IsInt32()) - return VException("Third argument must be integer height."); + NanThrowError("Third argument must be integer height."); DynamicJpegStack *jpeg = ObjectWrap::Unwrap(args.This()); Local data_buf = args[0]->ToObject(); @@ -320,61 +330,62 @@ DynamicJpegStack::SetBackground(const Arguments &args) int h = args[2]->Int32Value(); if (w < 0) - return VException("Coordinate x smaller than 0."); + NanThrowError("Coordinate x smaller than 0."); if (h < 0) - return VException("Coordinate y smaller than 0."); + NanThrowError("Coordinate y smaller than 0."); try { - jpeg->SetBackground((unsigned char *)Buffer::Data(data_buf), w, h); + jpeg->SetBackground((unsigned char *)node::Buffer::Data(data_buf), w, h); } catch (const char *err) { - return VException(err); + NanThrowError(err); } - return Undefined(); + NanReturnUndefined(); } -Handle -DynamicJpegStack::Reset(const Arguments &args) +NAN_METHOD(DynamicJpegStack::Reset) { - HandleScope scope; + NanScope(); DynamicJpegStack *jpeg = ObjectWrap::Unwrap(args.This()); jpeg->Reset(); - return Undefined(); + NanReturnUndefined(); } -Handle -DynamicJpegStack::Dimensions(const Arguments &args) +NAN_METHOD(DynamicJpegStack::Dimensions) { - HandleScope scope; + NanScope(); DynamicJpegStack *jpeg = ObjectWrap::Unwrap(args.This()); - return scope.Close(jpeg->Dimensions()); + NanReturnValue(jpeg->Dimensions()); } -Handle -DynamicJpegStack::SetQuality(const Arguments &args) +NAN_METHOD(DynamicJpegStack::SetQuality) { - HandleScope scope; + NanScope(); - if (args.Length() != 1) - return VException("One argument required - quality"); + if (args.Length() != 1) { + NanThrowError("One argument required - quality"); + } - if (!args[0]->IsInt32()) - return VException("First argument must be integer quality"); + if (!args[0]->IsInt32()) { + NanThrowError("First argument must be integer quality"); + } int q = args[0]->Int32Value(); - if (q < 0) - return VException("Quality must be greater or equal to 0."); - if (q > 100) - return VException("Quality must be less than or equal to 100."); + if (q < 0) { + NanThrowError("Quality must be greater or equal to 0."); + } + if (q > 100) { + NanThrowError("Quality must be less than or equal to 100."); + } DynamicJpegStack *jpeg = ObjectWrap::Unwrap(args.This()); jpeg->SetQuality(q); - return Undefined(); + NanReturnUndefined(); } void @@ -406,7 +417,7 @@ DynamicJpegStack::UV_JpegEncode(uv_work_t *req) void DynamicJpegStack::UV_JpegEncodeAfter(uv_work_t *req) { - HandleScope scope; + NanScope(); encode_request *enc_req = (encode_request *)req->data; delete req; @@ -415,26 +426,20 @@ DynamicJpegStack::UV_JpegEncodeAfter(uv_work_t *req) Handle argv[3]; if (enc_req->error) { - argv[0] = Undefined(); - argv[1] = Undefined(); - argv[2] = ErrorException(enc_req->error); + argv[0] = NanUndefined(); + argv[1] = NanUndefined(); + argv[2] = NanError(enc_req->error); } else { - Buffer *buf = Buffer::New(enc_req->jpeg_len); - memcpy(Buffer::Data(buf), enc_req->jpeg, enc_req->jpeg_len); - argv[0] = buf->handle_; + Handle buf = NanNewBufferHandle(enc_req->jpeg, enc_req->jpeg_len); + argv[0] = buf; argv[1] = jpeg->Dimensions(); - argv[2] = Undefined(); + argv[2] = NanUndefined(); } - TryCatch try_catch; // don't quite see the necessity of this + enc_req->callback->Call(3, argv); - enc_req->callback->Call(Context::GetCurrent()->Global(), 3, argv); - - if (try_catch.HasCaught()) - FatalException(try_catch); - - enc_req->callback.Dispose(); + delete enc_req->callback; free(enc_req->jpeg); free(enc_req->error); @@ -442,25 +447,27 @@ DynamicJpegStack::UV_JpegEncodeAfter(uv_work_t *req) free(enc_req); } -Handle -DynamicJpegStack::JpegEncodeAsync(const Arguments &args) +NAN_METHOD(DynamicJpegStack::JpegEncodeAsync) { - HandleScope scope; + NanScope(); - if (args.Length() != 1) - return VException("One argument required - callback function."); + if (args.Length() != 1) { + NanThrowError("One argument required - callback function."); + } - if (!args[0]->IsFunction()) - return VException("First argument must be a function."); + if (!args[0]->IsFunction()) { + NanThrowError("First argument must be a function."); + } Local callback = Local::Cast(args[0]); DynamicJpegStack *jpeg = ObjectWrap::Unwrap(args.This()); encode_request *enc_req = (encode_request *)malloc(sizeof(*enc_req)); - if (!enc_req) - return VException("malloc in DynamicJpegStack::JpegEncodeAsync failed."); + if (!enc_req) { + NanThrowError("malloc in DynamicJpegStack::JpegEncodeAsync failed."); + } - enc_req->callback = Persistent::New(callback); + enc_req->callback = new NanCallback(callback); enc_req->jpeg_obj = jpeg; enc_req->jpeg = NULL; enc_req->jpeg_len = 0; @@ -472,6 +479,6 @@ DynamicJpegStack::JpegEncodeAsync(const Arguments &args) jpeg->Ref(); - return Undefined(); + NanReturnUndefined(); } diff --git a/src/dynamic_jpeg_stack.h b/src/dynamic_jpeg_stack.h index f2069ef..baaa7af 100644 --- a/src/dynamic_jpeg_stack.h +++ b/src/dynamic_jpeg_stack.h @@ -35,14 +35,14 @@ class DynamicJpegStack : public node::ObjectWrap { void Reset(); static void Initialize(v8::Handle target); - static v8::Handle New(const v8::Arguments &args); - static v8::Handle JpegEncodeSync(const v8::Arguments &args); - static v8::Handle JpegEncodeAsync(const v8::Arguments &args); - static v8::Handle Push(const v8::Arguments &args); - static v8::Handle SetBackground(const v8::Arguments &args); - static v8::Handle SetQuality(const v8::Arguments &args); - static v8::Handle Dimensions(const v8::Arguments &args); - static v8::Handle Reset(const v8::Arguments &args); + static NAN_METHOD(New); + static NAN_METHOD(JpegEncodeSync); + static NAN_METHOD(JpegEncodeAsync); + static NAN_METHOD(Push); + static NAN_METHOD(SetBackground); + static NAN_METHOD(SetQuality); + static NAN_METHOD(Dimensions); + static NAN_METHOD(Reset); }; #endif diff --git a/src/fixed_jpeg_stack.cpp b/src/fixed_jpeg_stack.cpp index 4815344..7101d9b 100644 --- a/src/fixed_jpeg_stack.cpp +++ b/src/fixed_jpeg_stack.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -7,48 +8,44 @@ #include "common.h" #include "fixed_jpeg_stack.h" #include "jpeg_encoder.h" -#include "buffer_compat.h" -using namespace v8; -using namespace node; +using v8::Object; +using v8::Handle; +using v8::Local; +using v8::Function; +using v8::FunctionTemplate; +using v8::String; void -FixedJpegStack::Initialize(v8::Handle target) +FixedJpegStack::Initialize(Handle target) { - HandleScope scope; + NanScope(); - Local t = FunctionTemplate::New(New); + Local t = NanNew(New); t->InstanceTemplate()->SetInternalFieldCount(1); NODE_SET_PROTOTYPE_METHOD(t, "encode", JpegEncodeAsync); NODE_SET_PROTOTYPE_METHOD(t, "encodeSync", JpegEncodeSync); NODE_SET_PROTOTYPE_METHOD(t, "push", Push); NODE_SET_PROTOTYPE_METHOD(t, "setQuality", SetQuality); - target->Set(String::NewSymbol("FixedJpegStack"), t->GetFunction()); + target->Set(NanNew("FixedJpegStack"), t->GetFunction()); } FixedJpegStack::FixedJpegStack(int wwidth, int hheight, buffer_type bbuf_type) : width(wwidth), height(hheight), quality(60), buf_type(bbuf_type) { data = (unsigned char *)calloc(width*height*3, sizeof(*data)); - if (!data) throw "calloc in FixedJpegStack::FixedJpegStack failed!"; + if (!data) { + throw "calloc in FixedJpegStack::FixedJpegStack failed!"; + } } Handle FixedJpegStack::JpegEncodeSync() { - HandleScope scope; - - try { - JpegEncoder jpeg_encoder(data, width, height, quality, BUF_RGB); - jpeg_encoder.encode(); - int jpeg_len = jpeg_encoder.get_jpeg_len(); - Buffer *retbuf = Buffer::New(jpeg_len); - memcpy(Buffer::Data(retbuf), jpeg_encoder.get_jpeg(), jpeg_len); - return scope.Close(retbuf->handle_); - } - catch (const char *err) { - return VException(err); - } + JpegEncoder jpeg_encoder(data, width, height, quality, BUF_RGB); + jpeg_encoder.encode(); + Handle retbuf = NanNewBufferHandle((const char*) jpeg_encoder.get_jpeg(), jpeg_encoder.get_jpeg_len()); + return retbuf; } void @@ -116,83 +113,96 @@ FixedJpegStack::SetQuality(int q) quality = q; } -Handle -FixedJpegStack::New(const Arguments &args) +NAN_METHOD(FixedJpegStack::New) { - HandleScope scope; + NanScope(); - if (args.Length() < 2) - return VException("At least two arguments required - width, height, [and buffer type]"); - if (!args[0]->IsInt32()) - return VException("First argument must be integer width."); - if (!args[1]->IsInt32()) - return VException("Second argument must be integer height."); + if (args.Length() < 2) { + NanThrowError("At least two arguments required - width, height, [and buffer type]"); + } + if (!args[0]->IsInt32()) { + NanThrowError("First argument must be integer width."); + } + if (!args[1]->IsInt32()) { + NanThrowError("Second argument must be integer height."); + } int w = args[0]->Int32Value(); int h = args[1]->Int32Value(); - if (w < 0) - return VException("Width can't be negative."); - if (h < 0) - return VException("Height can't be negative."); + if (w < 0) { + NanThrowError("Width can't be negative."); + } + if (h < 0) { + NanThrowError("Height can't be negative."); + } buffer_type buf_type = BUF_RGB; if (args.Length() == 3) { - if (!args[2]->IsString()) - return VException("Third argument must be a string. Either 'rgb', 'bgr', 'rgba' or 'bgra'."); + if (!args[2]->IsString()) { + NanThrowError("Third argument must be a string. Either 'rgb', 'bgr', 'rgba' or 'bgra'."); + } - String::AsciiValue bt(args[2]->ToString()); + NanUtf8String bt(args[2]->ToString()); if (!(str_eq(*bt, "rgb") || str_eq(*bt, "bgr") || str_eq(*bt, "rgba") || str_eq(*bt, "bgra"))) { - return VException("Buffer type must be 'rgb', 'bgr', 'rgba' or 'bgra'."); + NanThrowError("Buffer type must be 'rgb', 'bgr', 'rgba' or 'bgra'."); } - if (str_eq(*bt, "rgb")) + if (str_eq(*bt, "rgb")) { buf_type = BUF_RGB; - else if (str_eq(*bt, "bgr")) + } else if (str_eq(*bt, "bgr")) { buf_type = BUF_BGR; - else if (str_eq(*bt, "rgba")) + } else if (str_eq(*bt, "rgba")) { buf_type = BUF_RGBA; - else if (str_eq(*bt, "bgra")) + } else if (str_eq(*bt, "bgra")) { buf_type = BUF_BGRA; - else - return VException("Buffer type wasn't 'rgb', 'bgr', 'rgba' or 'bgra'."); + } else { + NanThrowError("Buffer type wasn't 'rgb', 'bgr', 'rgba' or 'bgra'."); + } } try { FixedJpegStack *jpeg = new FixedJpegStack(w, h, buf_type); jpeg->Wrap(args.This()); - return args.This(); + NanReturnThis(); } catch (const char *err) { - return VException(err); + NanThrowError(err); } } -Handle -FixedJpegStack::JpegEncodeSync(const Arguments &args) +NAN_METHOD(FixedJpegStack::JpegEncodeSync) { - HandleScope scope; + NanScope(); FixedJpegStack *jpeg = ObjectWrap::Unwrap(args.This()); - return scope.Close(jpeg->JpegEncodeSync()); + try { + NanReturnValue(jpeg->JpegEncodeSync()); + } catch (const char *err) { + NanThrowError(err); + } } -Handle -FixedJpegStack::Push(const Arguments &args) +NAN_METHOD(FixedJpegStack::Push) { - HandleScope scope; - - if (!Buffer::HasInstance(args[0])) - return VException("First argument must be Buffer."); - if (!args[1]->IsInt32()) - return VException("Second argument must be integer x."); - if (!args[2]->IsInt32()) - return VException("Third argument must be integer y."); - if (!args[3]->IsInt32()) - return VException("Fourth argument must be integer w."); - if (!args[4]->IsInt32()) - return VException("Fifth argument must be integer h."); + NanScope(); + + if (!node::Buffer::HasInstance(args[0])) { + NanThrowError("First argument must be Buffer."); + } + if (!args[1]->IsInt32()) { + NanThrowError("Second argument must be integer x."); + } + if (!args[2]->IsInt32()) { + NanThrowError("Third argument must be integer y."); + } + if (!args[3]->IsInt32()) { + NanThrowError("Fourth argument must be integer w."); + } + if (!args[4]->IsInt32()) { + NanThrowError("Fifth argument must be integer h."); + } FixedJpegStack *jpeg = ObjectWrap::Unwrap(args.This()); Local data_buf = args[0]->ToObject(); @@ -201,50 +211,61 @@ FixedJpegStack::Push(const Arguments &args) int w = args[3]->Int32Value(); int h = args[4]->Int32Value(); - if (x < 0) - return VException("Coordinate x smaller than 0."); - if (y < 0) - return VException("Coordinate y smaller than 0."); - if (w < 0) - return VException("Width smaller than 0."); - if (h < 0) - return VException("Height smaller than 0."); - if (x >= jpeg->width) - return VException("Coordinate x exceeds FixedJpegStack's dimensions."); - if (y >= jpeg->height) - return VException("Coordinate y exceeds FixedJpegStack's dimensions."); - if (x+w > jpeg->width) - return VException("Pushed fragment exceeds FixedJpegStack's width."); - if (y+h > jpeg->height) - return VException("Pushed fragment exceeds FixedJpegStack's height."); - - jpeg->Push((unsigned char *)Buffer::Data(data_buf), x, y, w, h); - - return Undefined(); + if (x < 0) { + NanThrowError("Coordinate x smaller than 0."); + } + if (y < 0) { + NanThrowError("Coordinate y smaller than 0."); + } + if (w < 0) { + NanThrowError("Width smaller than 0."); + } + if (h < 0) { + NanThrowError("Height smaller than 0."); + } + if (x >= jpeg->width) { + NanThrowError("Coordinate x exceeds FixedJpegStack's dimensions."); + } + if (y >= jpeg->height) { + NanThrowError("Coordinate y exceeds FixedJpegStack's dimensions."); + } + if (x+w > jpeg->width) { + NanThrowError("Pushed fragment exceeds FixedJpegStack's width."); + } + if (y+h > jpeg->height) { + NanThrowError("Pushed fragment exceeds FixedJpegStack's height."); + } + + jpeg->Push((unsigned char *)node::Buffer::Data(data_buf), x, y, w, h); + + NanReturnUndefined(); } -Handle -FixedJpegStack::SetQuality(const Arguments &args) +NAN_METHOD(FixedJpegStack::SetQuality) { - HandleScope scope; + NanScope(); - if (args.Length() != 1) - return VException("One argument required - quality"); + if (args.Length() != 1) { + NanThrowError("One argument required - quality"); + } - if (!args[0]->IsInt32()) - return VException("First argument must be integer quality"); + if (!args[0]->IsInt32()) { + NanThrowError("First argument must be integer quality"); + } int q = args[0]->Int32Value(); - if (q < 0) - return VException("Quality must be greater or equal to 0."); - if (q > 100) - return VException("Quality must be less than or equal to 100."); + if (q < 0) { + NanThrowError("Quality must be greater or equal to 0."); + } + if (q > 100) { + NanThrowError("Quality must be less than or equal to 100."); + } FixedJpegStack *jpeg = ObjectWrap::Unwrap(args.This()); jpeg->SetQuality(q); - return Undefined(); + NanReturnUndefined(); } void @@ -274,7 +295,7 @@ FixedJpegStack::UV_JpegEncode(uv_work_t *req) void FixedJpegStack::UV_JpegEncodeAfter(uv_work_t *req) { - HandleScope scope; + NanScope(); encode_request *enc_req = (encode_request *)req->data; delete req; @@ -282,24 +303,18 @@ FixedJpegStack::UV_JpegEncodeAfter(uv_work_t *req) Handle argv[2]; if (enc_req->error) { - argv[0] = Undefined(); - argv[1] = ErrorException(enc_req->error); + argv[0] = NanUndefined(); + argv[1] = NanError(enc_req->error); } else { - Buffer *buf = Buffer::New(enc_req->jpeg_len); - memcpy(Buffer::Data(buf), enc_req->jpeg, enc_req->jpeg_len); - argv[0] = buf->handle_; - argv[1] = Undefined(); + Handle buf = NanNewBufferHandle(enc_req->jpeg, enc_req->jpeg_len); + argv[0] = buf; + argv[1] = NanUndefined(); } - TryCatch try_catch; // don't quite see the necessity of this - - enc_req->callback->Call(Context::GetCurrent()->Global(), 2, argv); + enc_req->callback->Call(2, argv); - if (try_catch.HasCaught()) - FatalException(try_catch); - - enc_req->callback.Dispose(); + delete enc_req->callback; free(enc_req->jpeg); free(enc_req->error); @@ -307,25 +322,27 @@ FixedJpegStack::UV_JpegEncodeAfter(uv_work_t *req) free(enc_req); } -Handle -FixedJpegStack::JpegEncodeAsync(const Arguments &args) +NAN_METHOD(FixedJpegStack::JpegEncodeAsync) { - HandleScope scope; + NanScope(); - if (args.Length() != 1) - return VException("One argument required - callback function."); + if (args.Length() != 1) { + NanThrowError("One argument required - callback function."); + } - if (!args[0]->IsFunction()) - return VException("First argument must be a function."); + if (!args[0]->IsFunction()) { + NanThrowError("First argument must be a function."); + } - Local callback = Local::Cast(args[0]); + Local callback = args[0].As(); FixedJpegStack *jpeg = ObjectWrap::Unwrap(args.This()); encode_request *enc_req = (encode_request *)malloc(sizeof(*enc_req)); - if (!enc_req) - return VException("malloc in FixedJpegStack::JpegEncodeAsync failed."); + if (!enc_req) { + NanThrowError("malloc in FixedJpegStack::JpegEncodeAsync failed."); + } - enc_req->callback = Persistent::New(callback); + enc_req->callback = new NanCallback(callback); enc_req->jpeg_obj = jpeg; enc_req->jpeg = NULL; enc_req->jpeg_len = 0; @@ -336,6 +353,6 @@ FixedJpegStack::JpegEncodeAsync(const Arguments &args) uv_queue_work(uv_default_loop(), req, UV_JpegEncode, (uv_after_work_cb)UV_JpegEncodeAfter); jpeg->Ref(); - return Undefined(); + NanReturnUndefined(); } diff --git a/src/fixed_jpeg_stack.h b/src/fixed_jpeg_stack.h index 3aaa43b..9f6e03b 100644 --- a/src/fixed_jpeg_stack.h +++ b/src/fixed_jpeg_stack.h @@ -23,11 +23,11 @@ class FixedJpegStack : public node::ObjectWrap { void Push(unsigned char *data_buf, int x, int y, int w, int h); void SetQuality(int q); - static v8::Handle New(const v8::Arguments &args); - static v8::Handle JpegEncodeSync(const v8::Arguments &args); - static v8::Handle JpegEncodeAsync(const v8::Arguments &args); - static v8::Handle Push(const v8::Arguments &args); - static v8::Handle SetQuality(const v8::Arguments &args); + static NAN_METHOD(New); + static NAN_METHOD(JpegEncodeSync); + static NAN_METHOD(JpegEncodeAsync); + static NAN_METHOD(Push); + static NAN_METHOD(SetQuality); }; #endif diff --git a/src/jpeg.cpp b/src/jpeg.cpp index a2ca062..cce19f4 100644 --- a/src/jpeg.cpp +++ b/src/jpeg.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -7,23 +8,25 @@ #include "common.h" #include "jpeg.h" #include "jpeg_encoder.h" -#include "buffer_compat.h" using namespace v8; using namespace node; +using v8::Object; +using v8::Handle; + void -Jpeg::Initialize(v8::Handle target) +Jpeg::Initialize(Handle target) { - HandleScope scope; + NanScope(); - Local t = FunctionTemplate::New(New); + Local t = NanNew(New); t->InstanceTemplate()->SetInternalFieldCount(1); 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, "setSmoothing", SetSmoothing); - target->Set(String::NewSymbol("Jpeg"), t->GetFunction()); + target->Set(NanNew("Jpeg"), t->GetFunction()); } Jpeg::Jpeg(unsigned char *ddata, int wwidth, int hheight, buffer_type bbuf_type) : @@ -32,19 +35,16 @@ Jpeg::Jpeg(unsigned char *ddata, int wwidth, int hheight, buffer_type bbuf_type) Handle Jpeg::JpegEncodeSync() { - HandleScope scope; - try { jpeg_encoder.encode(); } catch (const char *err) { - return VException(err); + NanThrowError(err); } - int jpeg_len = jpeg_encoder.get_jpeg_len(); - Buffer *retbuf = Buffer::New(jpeg_len); - memcpy(Buffer::Data(retbuf), jpeg_encoder.get_jpeg(), jpeg_len); - return scope.Close(retbuf->handle_); + Handle retbuf = NanNewBufferHandle((const char *) jpeg_encoder.get_jpeg(), jpeg_encoder.get_jpeg_len()); + // memcpy(Buffer::Data(retbuf), , jpeg_len); + return retbuf; } void @@ -59,112 +59,125 @@ Jpeg::SetSmoothing(int s) jpeg_encoder.set_smoothing(s); } -Handle -Jpeg::New(const Arguments &args) +NAN_METHOD(Jpeg::New) { - HandleScope scope; + NanScope(); - if (args.Length() < 3) - return VException("At least three arguments required - buffer, width, height, [and buffer type]"); - if (!Buffer::HasInstance(args[0])) - return VException("First argument must be Buffer."); - if (!args[1]->IsInt32()) - return VException("Second argument must be integer width."); - if (!args[2]->IsInt32()) - return VException("Third argument must be integer height."); + if (args.Length() < 3) { + NanThrowError("At least three arguments required - buffer, width, height, [and buffer type]"); + } + if (!Buffer::HasInstance(args[0])) { + NanThrowError("First argument must be Buffer."); + } + if (!args[1]->IsInt32()) { + NanThrowError("Second argument must be integer width."); + } + if (!args[2]->IsInt32()) { + NanThrowError("Third argument must be integer height."); + } int w = args[1]->Int32Value(); int h = args[2]->Int32Value(); - if (w < 0) - return VException("Width can't be negative."); - if (h < 0) - return VException("Height can't be negative."); + if (w < 0) { + NanThrowError("Width can't be negative."); + } + if (h < 0) { + NanThrowError("Height can't be negative."); + } buffer_type buf_type = BUF_RGB; if (args.Length() == 4) { - if (!args[3]->IsString()) - return VException("Fifth argument must be a string. Either 'rgb', 'bgr', 'rgba' or 'bgra'."); + if (!args[3]->IsString()) { + NanThrowError("Fifth argument must be a string. Either 'rgb', 'bgr', 'rgba' or 'bgra'."); + } - String::AsciiValue bt(args[3]->ToString()); + NanUtf8String bt(args[3]->ToString()); if (!(str_eq(*bt, "rgb") || str_eq(*bt, "bgr") || str_eq(*bt, "rgba") || str_eq(*bt, "bgra"))) { - return VException("Buffer type must be 'rgb', 'bgr', 'rgba' or 'bgra'."); + NanThrowError("Buffer type must be 'rgb', 'bgr', 'rgba' or 'bgra'."); } - if (str_eq(*bt, "rgb")) + if (str_eq(*bt, "rgb")) { buf_type = BUF_RGB; - else if (str_eq(*bt, "bgr")) + } else if (str_eq(*bt, "bgr")) { buf_type = BUF_BGR; - else if (str_eq(*bt, "rgba")) + } else if (str_eq(*bt, "rgba")) { buf_type = BUF_RGBA; - else if (str_eq(*bt, "bgra")) + } else if (str_eq(*bt, "bgra")) { buf_type = BUF_BGRA; - else - return VException("Buffer type wasn't 'rgb', 'bgr', 'rgba' or 'bgra'."); + } else { + NanThrowError("Buffer type wasn't 'rgb', 'bgr', 'rgba' or 'bgra'."); + } } Local buffer = args[0]->ToObject(); Jpeg *jpeg = new Jpeg((unsigned char*) Buffer::Data(buffer), w, h, buf_type); jpeg->Wrap(args.This()); - return args.This(); + NanReturnThis(); } -Handle -Jpeg::JpegEncodeSync(const Arguments &args) +NAN_METHOD(Jpeg::JpegEncodeSync) { - HandleScope scope; + NanScope(); Jpeg *jpeg = ObjectWrap::Unwrap(args.This()); - return scope.Close(jpeg->JpegEncodeSync()); + NanReturnValue(jpeg->JpegEncodeSync()); } -Handle -Jpeg::SetQuality(const Arguments &args) +NAN_METHOD(Jpeg::SetQuality) { - HandleScope scope; + NanScope(); - if (args.Length() != 1) - return VException("One argument required - quality"); + if (args.Length() != 1) { + NanThrowError("One argument required - quality"); + } - if (!args[0]->IsInt32()) - return VException("First argument must be integer quality"); + if (!args[0]->IsInt32()) { + NanThrowError("First argument must be integer quality"); + } int q = args[0]->Int32Value(); - if (q < 0) - return VException("Quality must be greater or equal to 0."); - if (q > 100) - return VException("Quality must be less than or equal to 100."); + if (q < 0) { + NanThrowError("Quality must be greater or equal to 0."); + } + if (q > 100) { + NanThrowError("Quality must be less than or equal to 100."); + } Jpeg *jpeg = ObjectWrap::Unwrap(args.This()); jpeg->SetQuality(q); - return Undefined(); + NanReturnUndefined(); } -v8::Handle Jpeg::SetSmoothing(const v8::Arguments &args) +NAN_METHOD(Jpeg::SetSmoothing) { - HandleScope scope; + NanScope(); - if (args.Length() != 1) - return VException("One argument required - quality"); + if (args.Length() != 1) { + NanThrowError("One argument required - quality"); + } - if (!args[0]->IsInt32()) - return VException("First argument must be integer quality"); + if (!args[0]->IsInt32()) { + NanThrowError("First argument must be integer quality"); + } int s = args[0]->Int32Value(); - if (s < 0) - return VException("Smoothing must be greater or equal to 0."); - if (s > 100) - return VException("Smoothing must be less than or equal to 100."); + if (s < 0) { + NanThrowError("Smoothing must be greater or equal to 0."); + } + if (s > 100) { + NanThrowError("Smoothing must be less than or equal to 100."); + } Jpeg *jpeg = ObjectWrap::Unwrap(args.This()); jpeg->SetSmoothing(s); - return Undefined(); + NanReturnUndefined(); } void @@ -193,7 +206,7 @@ Jpeg::UV_JpegEncode(uv_work_t *req) void Jpeg::UV_JpegEncodeAfter(uv_work_t *req) { - HandleScope scope; + NanScope(); encode_request *enc_req = (encode_request *)req->data; delete req; @@ -201,24 +214,23 @@ Jpeg::UV_JpegEncodeAfter(uv_work_t *req) Handle argv[2]; if (enc_req->error) { - argv[0] = Undefined(); - argv[1] = ErrorException(enc_req->error); + argv[0] = NanUndefined(); + argv[1] = NanError(enc_req->error); } else { - Buffer *buf = Buffer::New(enc_req->jpeg_len); - memcpy(Buffer::Data(buf), enc_req->jpeg, enc_req->jpeg_len); - argv[0] = buf->handle_; - argv[1] = Undefined(); + Handle buf = NanNewBufferHandle(enc_req->jpeg, enc_req->jpeg_len); + argv[0] = buf; + argv[1] = NanUndefined(); } TryCatch try_catch; // don't quite see the necessity of this - enc_req->callback->Call(Context::GetCurrent()->Global(), 2, argv); + enc_req->callback->Call(2, argv); if (try_catch.HasCaught()) FatalException(try_catch); - enc_req->callback.Dispose(); + delete enc_req->callback; free(enc_req->jpeg); free(enc_req->error); @@ -226,25 +238,27 @@ Jpeg::UV_JpegEncodeAfter(uv_work_t *req) free(enc_req); } -Handle -Jpeg::JpegEncodeAsync(const Arguments &args) +NAN_METHOD(Jpeg::JpegEncodeAsync) { - HandleScope scope; + NanScope(); - if (args.Length() != 1) - return VException("One argument required - callback function."); + if (args.Length() != 1) { + NanThrowError("One argument required - callback function."); + } - if (!args[0]->IsFunction()) - return VException("First argument must be a function."); + if (!args[0]->IsFunction()) { + NanThrowError("First argument must be a function."); + } - Local callback = Local::Cast(args[0]); + Local callback = args[0].As(); Jpeg *jpeg = ObjectWrap::Unwrap(args.This()); encode_request *enc_req = (encode_request *)malloc(sizeof(*enc_req)); - if (!enc_req) - return VException("malloc in Jpeg::JpegEncodeAsync failed."); + if (!enc_req) { + NanThrowError("malloc in Jpeg::JpegEncodeAsync failed."); + } - enc_req->callback = Persistent::New(callback); + enc_req->callback = new NanCallback(callback); enc_req->jpeg_obj = jpeg; enc_req->jpeg = NULL; enc_req->jpeg_len = 0; @@ -256,6 +270,6 @@ Jpeg::JpegEncodeAsync(const Arguments &args) jpeg->Ref(); - return Undefined(); + NanReturnUndefined(); } diff --git a/src/jpeg.h b/src/jpeg.h index acee92b..ff46205 100644 --- a/src/jpeg.h +++ b/src/jpeg.h @@ -1,28 +1,35 @@ #ifndef JPEG_H #define JPEG_H +#include #include #include #include "jpeg_encoder.h" +using v8::FunctionTemplate; +using v8::Handle; +using v8::Object; +using v8::String; +using v8::Value; + class Jpeg : public node::ObjectWrap { JpegEncoder jpeg_encoder; static void UV_JpegEncode(uv_work_t *req); static void UV_JpegEncodeAfter(uv_work_t *req); public: - static void Initialize(v8::Handle target); + static void Initialize(Handle target); Jpeg(unsigned char *ddata, int wwidth, int hheight, buffer_type bbuf_type); - v8::Handle JpegEncodeSync(); + Handle JpegEncodeSync(); void SetQuality(int q); void SetSmoothing(int s); - static v8::Handle New(const v8::Arguments &args); - static v8::Handle JpegEncodeSync(const v8::Arguments &args); - static v8::Handle JpegEncodeAsync(const v8::Arguments &args); - static v8::Handle SetQuality(const v8::Arguments &args); - static v8::Handle SetSmoothing(const v8::Arguments &args); + static NAN_METHOD(New); + static NAN_METHOD(JpegEncodeSync); + static NAN_METHOD(JpegEncodeAsync); + static NAN_METHOD(SetQuality); + static NAN_METHOD(SetSmoothing); }; #endif diff --git a/src/module.cpp b/src/module.cpp index 539139c..c064392 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -1,18 +1,15 @@ +#include #include #include "jpeg.h" #include "fixed_jpeg_stack.h" #include "dynamic_jpeg_stack.h" -using namespace v8; - -extern "C" void -init(Handle target) +void InitAll(Handle target) { - HandleScope scope; Jpeg::Initialize(target); FixedJpegStack::Initialize(target); DynamicJpegStack::Initialize(target); } -NODE_MODULE(jpeg, init) +NODE_MODULE(jpeg, InitAll)