14 changed files with 326 additions and 12 deletions
@ -0,0 +1,29 @@ |
|||
|
|||
/*! |
|||
* Canvas - PixelArray |
|||
* Copyright (c) 2010 LearnBoost <tj@learnboost.com> |
|||
* MIT Licensed |
|||
*/ |
|||
|
|||
/** |
|||
* Module dependencies. |
|||
*/ |
|||
|
|||
var Canvas = require('../build/default/canvas') |
|||
, PixelArray = Canvas.CanvasPixelArray; |
|||
|
|||
/** |
|||
* Custom inspect. |
|||
*/ |
|||
|
|||
PixelArray.prototype.inspect = function(){ |
|||
var buf = '[PixelArray '; |
|||
for (var i = 0, len = this.length; i < len; i += 4) { |
|||
buf += '\n ' + i + ': rgba(' |
|||
+ this[i + 0] + ',' |
|||
+ this[i + 1] + ',' |
|||
+ this[i + 2] + ',' |
|||
+ this[i + 3] + ')'; |
|||
} |
|||
return buf + '\n]'; |
|||
}; |
@ -0,0 +1,61 @@ |
|||
|
|||
//
|
|||
// ImageData.cc
|
|||
//
|
|||
// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
|
|||
//
|
|||
|
|||
#include "ImageData.h" |
|||
|
|||
/*
|
|||
* Initialize ImageData. |
|||
*/ |
|||
|
|||
void |
|||
ImageData::Initialize(Handle<Object> target) { |
|||
HandleScope scope; |
|||
Local<FunctionTemplate> t = FunctionTemplate::New(ImageData::New); |
|||
t->InstanceTemplate()->SetInternalFieldCount(1); |
|||
t->SetClassName(String::NewSymbol("ImageData")); |
|||
|
|||
// Prototype
|
|||
Local<ObjectTemplate> proto = t->PrototypeTemplate(); |
|||
proto->SetAccessor(String::NewSymbol("width"), GetWidth); |
|||
proto->SetAccessor(String::NewSymbol("height"), GetHeight); |
|||
target->Set(String::NewSymbol("ImageData"), t->GetFunction()); |
|||
} |
|||
|
|||
/*
|
|||
* Initialize a new ImageData object. |
|||
*/ |
|||
|
|||
Handle<Value> |
|||
ImageData::New(const Arguments &args) { |
|||
HandleScope scope; |
|||
// TODO: arg assertions
|
|||
PixelArray *arr = ObjectWrap::Unwrap<PixelArray>(args[0]->ToObject()); |
|||
ImageData *imageData = new ImageData(arr); |
|||
args.This()->Set(String::NewSymbol("data"), args[0]); |
|||
imageData->Wrap(args.This()); |
|||
return args.This(); |
|||
} |
|||
|
|||
/*
|
|||
* Get width. |
|||
*/ |
|||
|
|||
Handle<Value> |
|||
ImageData::GetWidth(Local<String> prop, const AccessorInfo &info) { |
|||
ImageData *imageData = ObjectWrap::Unwrap<ImageData>(info.This()); |
|||
return Number::New(imageData->pixelArray()->width()); |
|||
} |
|||
|
|||
/*
|
|||
* Get height. |
|||
*/ |
|||
|
|||
Handle<Value> |
|||
ImageData::GetHeight(Local<String> prop, const AccessorInfo &info) { |
|||
ImageData *imageData = ObjectWrap::Unwrap<ImageData>(info.This()); |
|||
return Number::New(imageData->pixelArray()->height()); |
|||
} |
@ -0,0 +1,27 @@ |
|||
|
|||
//
|
|||
// ImageData.h
|
|||
//
|
|||
// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
|
|||
//
|
|||
|
|||
#ifndef __NODE_IMAGE_DATA_H__ |
|||
#define __NODE_IMAGE_DATA_H__ |
|||
|
|||
#include "Canvas.h" |
|||
#include "PixelArray.h" |
|||
#include <stdlib.h> |
|||
|
|||
class ImageData: public node::ObjectWrap { |
|||
public: |
|||
static void Initialize(Handle<Object> target); |
|||
static Handle<Value> New(const Arguments &args); |
|||
static Handle<Value> GetWidth(Local<String> prop, const AccessorInfo &info); |
|||
static Handle<Value> GetHeight(Local<String> prop, const AccessorInfo &info); |
|||
inline PixelArray *pixelArray(){ return _arr; } |
|||
ImageData(PixelArray *arr): _arr(arr) {} |
|||
private: |
|||
PixelArray *_arr; |
|||
}; |
|||
|
|||
#endif |
@ -0,0 +1,130 @@ |
|||
|
|||
//
|
|||
// PixelArray.cc
|
|||
//
|
|||
// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
|
|||
//
|
|||
|
|||
#include "PixelArray.h" |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
|
|||
/*
|
|||
* Initialize PixelArray. |
|||
*/ |
|||
|
|||
void |
|||
PixelArray::Initialize(Handle<Object> target) { |
|||
HandleScope scope; |
|||
Local<FunctionTemplate> t = FunctionTemplate::New(PixelArray::New); |
|||
t->InstanceTemplate()->SetInternalFieldCount(1); |
|||
t->SetClassName(String::NewSymbol("CanvasPixelArray")); |
|||
|
|||
Local<ObjectTemplate> proto = t->InstanceTemplate(); |
|||
proto->SetAccessor(String::NewSymbol("length"), GetLength); |
|||
target->Set(String::NewSymbol("CanvasPixelArray"), t->GetFunction()); |
|||
} |
|||
|
|||
/*
|
|||
* Initialize a new PixelArray. |
|||
*/ |
|||
|
|||
Handle<Value> |
|||
PixelArray::New(const Arguments &args) { |
|||
HandleScope scope; |
|||
PixelArray *arr; |
|||
// TODO: arg handling
|
|||
|
|||
switch (args.Length()) { |
|||
// width, height
|
|||
case 2: |
|||
arr = new PixelArray( |
|||
args[0]->Int32Value() |
|||
, args[1]->Int32Value()); |
|||
break; |
|||
// canvas, x, y, width, height
|
|||
case 5: { |
|||
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args[0]->ToObject()); |
|||
arr = new PixelArray( |
|||
canvas |
|||
, args[1]->Int32Value() |
|||
, args[2]->Int32Value() |
|||
, args[3]->Int32Value() |
|||
, args[4]->Int32Value()); |
|||
} |
|||
break; |
|||
default: |
|||
return ThrowException(Exception::TypeError(String::New("invalid arguments"))); |
|||
} |
|||
// Let v8 handle accessors (and clamping)
|
|||
args.This()->SetIndexedPropertiesToPixelData( |
|||
arr->data() |
|||
, arr->length()); |
|||
|
|||
arr->Wrap(args.This()); |
|||
return args.This(); |
|||
} |
|||
|
|||
/*
|
|||
* Get length. |
|||
*/ |
|||
|
|||
Handle<Value> |
|||
PixelArray::GetLength(Local<String> prop, const AccessorInfo &info) { |
|||
return Number::New(info.This()->GetIndexedPropertiesPixelDataLength()); |
|||
} |
|||
|
|||
/*
|
|||
* Initialize a new PixelArray copying data |
|||
* from the canvas surface using the given rect. |
|||
*/ |
|||
|
|||
PixelArray::PixelArray(Canvas *canvas, int sx, int sy, int width, int height): |
|||
_width(width), _height(height) { |
|||
|
|||
// Alloc space for our new data
|
|||
uint8_t *dst = alloc(); |
|||
uint8_t *src = canvas->data(); |
|||
int s = stride(); |
|||
|
|||
// Normalize data (argb -> rgba)
|
|||
for (int y = 0; y < height; ++y) { |
|||
uint32_t *row = (uint32_t *)(src + s * y); |
|||
for (int x = 0; x < width; ++x) { |
|||
int bx = x * 4; |
|||
uint32_t *pixel = row + x; |
|||
|
|||
// premultiplied
|
|||
uint8_t a = *pixel >> 24; |
|||
dst[bx + 3] = a; |
|||
dst[bx + 0] = (*pixel >> 16) * 255 / a; |
|||
dst[bx + 1] = (*pixel >> 8) * 255 / a; |
|||
dst[bx + 2] = *pixel * 255 / a; |
|||
} |
|||
dst += s; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* Initialize an empty PixelArray with the given dimensions. |
|||
*/ |
|||
|
|||
PixelArray::PixelArray(int width, int height): |
|||
_width(width), _height(height) { |
|||
alloc(); |
|||
} |
|||
|
|||
/*
|
|||
* Allocate / zero data buffer. |
|||
*/ |
|||
|
|||
uint8_t * |
|||
PixelArray::alloc() { |
|||
_data = (uint8_t *) malloc(length()); |
|||
memset(_data, 0, length()); |
|||
return _data; |
|||
} |
|||
|
|||
PixelArray::~PixelArray() { |
|||
free(_data); |
|||
} |
@ -0,0 +1,32 @@ |
|||
|
|||
//
|
|||
// PixelArray.h
|
|||
//
|
|||
// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
|
|||
//
|
|||
|
|||
#ifndef __NODE_PIXEL_ARRAY_H__ |
|||
#define __NODE_PIXEL_ARRAY_H__ |
|||
|
|||
#include "Canvas.h" |
|||
|
|||
class PixelArray: public node::ObjectWrap { |
|||
public: |
|||
static void Initialize(Handle<Object> target); |
|||
static Handle<Value> New(const Arguments &args); |
|||
static Handle<Value> GetLength(Local<String> prop, const AccessorInfo &info); |
|||
inline int length(){ return _width * _height * 4; } |
|||
inline int width(){ return _width; } |
|||
inline int height(){ return _height; } |
|||
inline int stride(){ return _width * 4; } |
|||
inline uint8_t *data(){ return _data; } |
|||
PixelArray(Canvas *canvas, int x, int y, int width, int height); |
|||
PixelArray(int width, int height); |
|||
~PixelArray(); |
|||
private: |
|||
uint8_t *alloc(); |
|||
uint8_t *_data; |
|||
int _width, _height; |
|||
}; |
|||
|
|||
#endif |
Loading…
Reference in new issue