diff --git a/binding.gyp b/binding.gyp index e0b74437..63812364 100644 --- a/binding.gyp +++ b/binding.gyp @@ -60,7 +60,9 @@ 'src/screen.c', 'src/screengrab.c', 'src/snprintf.c', - 'src/MMBitmap.c' + 'src/MMBitmap.c', + 'src/io.c', + 'src/bmp_io.c' ] }] } \ No newline at end of file diff --git a/index.js b/index.js index 3e0713cb..eb69942f 100644 --- a/index.js +++ b/index.js @@ -17,6 +17,11 @@ function bitmap(width, height, byteWidth, bitsPerPixel, bytesPerPixel, image) { return robotjs.getColor(this, x, y); }; + + this.save = function(path) + { + return robotjs.saveBitmap(this, path); + }; } module.exports.screen.capture = function(x, y, width, height) diff --git a/src/bmp_io.h b/src/bmp_io.h index 6d521193..96e601d8 100644 --- a/src/bmp_io.h +++ b/src/bmp_io.h @@ -5,6 +5,11 @@ #include "MMBitmap.h" #include "io.h" +#ifdef __cplusplus +extern "C" +{ +#endif + enum _BMPReadError { kBMPGenericError = 0, kBMPAccessError, @@ -51,4 +56,8 @@ int saveMMBitmapAsBMP(MMBitmapRef bitmap, const char *path); */ void flipBitmapData(void *data, size_t width, size_t height, size_t bytewidth); +#ifdef __cplusplus +} +#endif + #endif /* BMP_IO_H */ diff --git a/src/io.h b/src/io.h index 47eb974f..7fac20ed 100644 --- a/src/io.h +++ b/src/io.h @@ -6,6 +6,10 @@ #include #include +#ifdef __cplusplus +extern "C" +{ +#endif enum _MMImageType { kInvalidImageType = 0, @@ -43,4 +47,9 @@ int saveMMBitmapToFile(MMBitmapRef bitmap, const char *path, MMImageType type); * Returned string is constant and hence should not be freed. */ const char *MMIOErrorString(MMImageType type, MMIOError error); +#ifdef __cplusplus +} +#endif + + #endif /* IO_H */ diff --git a/src/robotjs.cc b/src/robotjs.cc index fcd4f00a..235ad1b0 100644 --- a/src/robotjs.cc +++ b/src/robotjs.cc @@ -10,6 +10,8 @@ #include "MMBitmap.h" #include "snprintf.h" #include "microsleep.h" +#include "io.h" +#include "bmp_io.h" using namespace v8; @@ -695,6 +697,40 @@ NAN_METHOD(captureScreen) |____/|_|\__|_| |_| |_|\__,_| .__/ |_| */ + +class BMP +{ + public: + size_t width; + size_t height; + size_t byteWidth; + uint8_t bitsPerPixel; + uint8_t bytesPerPixel; + uint8_t *image; +}; + +//Convert object from Javascript to a C++ class (BMP). +BMP buildBMP(Local info) +{ + Local obj = Nan::To(info).ToLocalChecked(); + + BMP img; + + img.width = obj->Get(Nan::New("width").ToLocalChecked())->Uint32Value(); + img.height = obj->Get(Nan::New("height").ToLocalChecked())->Uint32Value(); + img.byteWidth = obj->Get(Nan::New("byteWidth").ToLocalChecked())->Uint32Value(); + img.bitsPerPixel = obj->Get(Nan::New("bitsPerPixel").ToLocalChecked())->Uint32Value(); + img.bytesPerPixel = obj->Get(Nan::New("bytesPerPixel").ToLocalChecked())->Uint32Value(); + + char* buf = node::Buffer::Data(obj->Get(Nan::New("image").ToLocalChecked())); + + //Convert the buffer to a uint8_t which createMMBitmap requires. + img.image = (uint8_t *)malloc(img.byteWidth * img.height); + memcpy(img.image, buf, img.byteWidth * img.height); + + return img; +} + NAN_METHOD(getColor) { MMBitmapRef bitmap; @@ -704,23 +740,13 @@ NAN_METHOD(getColor) size_t y = info[1]->Int32Value(); //Get our image object from JavaScript. - Local obj = Nan::To(info[0]).ToLocalChecked(); + BMP img = buildBMP(Nan::To(info[0]).ToLocalChecked()); - size_t width = obj->Get(Nan::New("width").ToLocalChecked())->Uint32Value(); - size_t height = obj->Get(Nan::New("height").ToLocalChecked())->Uint32Value(); - size_t byteWidth = obj->Get(Nan::New("byteWidth").ToLocalChecked())->Uint32Value(); - uint8_t bitsPerPixel = obj->Get(Nan::New("bitsPerPixel").ToLocalChecked())->Uint32Value(); - uint8_t bytesPerPixel = obj->Get(Nan::New("bytesPerPixel").ToLocalChecked())->Uint32Value(); - - char* buf = node::Buffer::Data(obj->Get(Nan::New("image").ToLocalChecked())); + //Create the bitmap. + bitmap = createMMBitmap(img.image, img.width, img.height, img.byteWidth, img.bitsPerPixel, img.bytesPerPixel); - uint8_t *data = (uint8_t *)malloc(byteWidth * height); - memcpy(data, buf, byteWidth * height); - - bitmap = createMMBitmap(data, width, height, byteWidth, bitsPerPixel, bytesPerPixel); - color = MMRGBHexAtPoint(bitmap, x, y); - + char hex[7]; padHex(color, hex); @@ -731,6 +757,32 @@ NAN_METHOD(getColor) } +NAN_METHOD(saveBitmap) +{ + MMBitmapRef bitmap; + MMImageType type = kBMPImageType; + + //Get our image object from JavaScript. + BMP img = buildBMP(Nan::To(info[0]).ToLocalChecked()); + + char *path; + Nan::Utf8String string(info[1]); + + path = *string; + + //Create the bitmap. + bitmap = createMMBitmap(img.image, img.width, img.height, img.byteWidth, img.bitsPerPixel, img.bytesPerPixel); + + if (saveMMBitmapToFile(bitmap, path, type) != 0) { + return Nan::ThrowError("Could not save image to file."); + } + + destroyMMBitmap(bitmap); + + info.GetReturnValue().Set(Nan::New(1)); + +} + NAN_MODULE_INIT(InitAll) { Nan::Set(target, Nan::New("dragMouse").ToLocalChecked(), @@ -780,6 +832,9 @@ NAN_MODULE_INIT(InitAll) Nan::Set(target, Nan::New("getColor").ToLocalChecked(), Nan::GetFunction(Nan::New(getColor)).ToLocalChecked()); + + Nan::Set(target, Nan::New("saveBitmap").ToLocalChecked(), + Nan::GetFunction(Nan::New(saveBitmap)).ToLocalChecked()); } NODE_MODULE(robotjs, InitAll)