|
| 1 | +#include <stdlib.h> |
| 2 | +#include <iostream> |
| 3 | + |
| 4 | +#include <v8.h> |
| 5 | +#include <node.h> |
| 6 | +#include <node_buffer.h> |
| 7 | +#include "../v8_helpers.h" |
| 8 | + |
| 9 | +#include <FreeImage.h> |
| 10 | + |
| 11 | +#include "freeimage.h" |
| 12 | +#include "image.h" |
| 13 | + |
| 14 | +using namespace std; |
| 15 | +using namespace v8; |
| 16 | +using namespace node; |
| 17 | + |
| 18 | +namespace openvg_canvas { |
| 19 | +namespace freeimage { |
| 20 | + |
| 21 | +ISOLATE(freeimage_isolate) |
| 22 | + |
| 23 | +void FreeImage::Initialize(Handle<Object> target) { |
| 24 | + ISOLATE_INIT(freeimage_isolate) |
| 25 | + SCOPE(freeimage_isolate); |
| 26 | + |
| 27 | + // Prepare constructor template |
| 28 | + Local<FunctionTemplate> constructor = FunctionTemplate::New(New); |
| 29 | + constructor->SetClassName(String::NewSymbol("FreeImage")); |
| 30 | + constructor->InstanceTemplate()->SetInternalFieldCount(1); |
| 31 | + |
| 32 | + // Prototype |
| 33 | + Local<Template> proto = constructor->PrototypeTemplate(); |
| 34 | + proto->Set("getVersion" , FunctionTemplate::New(GetVersion )); |
| 35 | + proto->Set("loadFromMemory" , FunctionTemplate::New(LoadFromMemory )); |
| 36 | + proto->Set("convertFromRGBABits", FunctionTemplate::New(ConvertFromRGBABits)); |
| 37 | + |
| 38 | + target->Set(String::NewSymbol("FreeImage"), constructor->GetFunction()->NewInstance()); |
| 39 | + |
| 40 | + Image::Initialize(target); |
| 41 | +} |
| 42 | + |
| 43 | +FreeImage::FreeImage() { |
| 44 | + FreeImage_Initialise(FALSE); // FALSE means use external plugins |
| 45 | +} |
| 46 | + |
| 47 | +FreeImage::~FreeImage() { |
| 48 | + FreeImage_DeInitialise(); |
| 49 | +} |
| 50 | + |
| 51 | +void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) { |
| 52 | + cout << endl << "*** "; |
| 53 | + if(fif != FIF_UNKNOWN) { |
| 54 | + cout << FreeImage_GetFormatFromFIF(fif) << " Format" << endl; |
| 55 | + } |
| 56 | + cout << message; |
| 57 | + cout << " ***" << endl; |
| 58 | +} |
| 59 | + |
| 60 | +// TODO check for args.IsConstructCall() |
| 61 | +V8_METHOD(FreeImage::New) { |
| 62 | + SCOPE(freeimage_isolate); |
| 63 | + |
| 64 | + FreeImage* obj = new FreeImage(); |
| 65 | + obj->Wrap(args.This()); |
| 66 | + FreeImage_SetOutputMessage(FreeImageErrorHandler); |
| 67 | + |
| 68 | + V8_RETURN(args.This()); |
| 69 | +} |
| 70 | + |
| 71 | +V8_METHOD(FreeImage::GetVersion) { |
| 72 | + SCOPE(freeimage_isolate); |
| 73 | + |
| 74 | + V8_RETURN(scope.Close(String::New(FreeImage_GetVersion()))); |
| 75 | +} |
| 76 | + |
| 77 | +V8_METHOD(FreeImage::LoadFromMemory) { |
| 78 | + SCOPE(freeimage_isolate); |
| 79 | + |
| 80 | + Local<Object> bufferObj = args[0]->ToObject(); |
| 81 | + BYTE* bufferData = (BYTE*) Buffer::Data(bufferObj); |
| 82 | + size_t bufferLength = Buffer::Length(bufferObj); |
| 83 | + |
| 84 | + FIMEMORY *hmem = FreeImage_OpenMemory(bufferData, bufferLength); |
| 85 | + |
| 86 | + FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0); |
| 87 | + FIBITMAP *dib = FreeImage_LoadFromMemory(fif, hmem, 0); |
| 88 | + |
| 89 | + FreeImage_CloseMemory(hmem); |
| 90 | + |
| 91 | + // check that dib does not contains pixels |
| 92 | + if(!dib || !FreeImage_HasPixels(dib)) { |
| 93 | + V8_RETURN(Undefined()); |
| 94 | + } else { |
| 95 | + V8_RETURN(V8_PERSISTENT(Image::New(dib))); |
| 96 | + } |
| 97 | +} |
| 98 | + |
| 99 | +V8_METHOD(FreeImage::ConvertFromRGBABits) { |
| 100 | + SCOPE(freeimage_isolate); |
| 101 | + |
| 102 | + TypedArrayWrapper<uint32_t> rgba(args[0]); |
| 103 | + |
| 104 | + const uint32_t width = args[1]->Int32Value(); |
| 105 | + const uint32_t height = args[2]->Int32Value(); |
| 106 | + const uint32_t pitch = width * 4, bpp = 32; |
| 107 | + const uint32_t redMask = 0x00ff0000, |
| 108 | + greenMask = 0x0000ff00, |
| 109 | + blueMask = 0x000000ff; |
| 110 | + BOOL topdown = FALSE; |
| 111 | + |
| 112 | + BYTE* convertedBits = (BYTE *) malloc(height * width * 4); |
| 113 | + |
| 114 | + uint32_t* nextDest = (uint32_t*) convertedBits; |
| 115 | + uint32_t* nextSrc = (uint32_t*) rgba.pointer(); |
| 116 | + for(int i=height * width; i >= 0; i--, nextSrc++, nextDest++) { |
| 117 | + *nextDest = (*nextSrc & 0xffffff00) >> 8 | |
| 118 | + (*nextSrc & 0x000000ff) << 24; |
| 119 | + } |
| 120 | + |
| 121 | + FIBITMAP *dib = |
| 122 | + FreeImage_ConvertFromRawBits(convertedBits, width, height, pitch, bpp, |
| 123 | + redMask, greenMask, blueMask, topdown); |
| 124 | + |
| 125 | + free(convertedBits); |
| 126 | + |
| 127 | + // check that dib does not contains pixels |
| 128 | + if(!dib || !FreeImage_HasPixels(dib)) { |
| 129 | + V8_RETURN(Undefined()); |
| 130 | + } else { |
| 131 | + V8_RETURN(V8_PERSISTENT(Image::New(dib))); |
| 132 | + } |
| 133 | +} |
| 134 | + |
| 135 | +} // namespace freeimage |
| 136 | +} // namespace openvg_canvas |
| 137 | + |
| 138 | +NODE_MODULE(freeimage, openvg_canvas::freeimage::FreeImage::Initialize) |
0 commit comments