Browse Source

Merge branch 'jpeg'

v1.x
Tj Holowaychuk 14 years ago
parent
commit
8530ce0182
  1. 1
      lib/image.js
  2. 78
      src/Image.cc
  3. 10
      src/Image.h
  4. 3
      wscript

1
lib/image.js

@ -21,6 +21,7 @@ var Canvas = require('../build/default/canvas')
Image.prototype.inspect = function(){
return '[Image'
+ (this.complete ? ':' + this.width + 'x' + this.height : '')
+ (this.src ? ' ' + this.src : '')
+ (this.complete ? ' complete' : '')
+ ']';

78
src/Image.cc

@ -9,6 +9,7 @@
#include "Image.h"
#include <stdlib.h>
#include <string.h>
#include <jpeglib.h>
Persistent<FunctionTemplate> Image::constructor;
@ -264,13 +265,90 @@ Image::error(Local<Value> err) {
/*
* Load cairo surface from the image src.
*
* TODO: better format detection
* TODO: support more formats
*/
cairo_status_t
Image::loadSurface() {
switch (extension(filename)) {
case Image::PNG: return loadPNG();
case Image::JPEG: return loadJPEG();
}
return CAIRO_STATUS_READ_ERROR;
}
/*
* Load PNG.
*/
cairo_status_t
Image::loadPNG() {
_surface = cairo_image_surface_create_from_png(filename);
width = cairo_image_surface_get_width(_surface);
height = cairo_image_surface_get_height(_surface);
return cairo_surface_status(_surface);
}
/*
* Load JPEG, convert RGB to ARGB.
*/
cairo_status_t
Image::loadJPEG() {
// TODO: error handling
// TODO: move to node IO
FILE *stream = fopen(filename, "r");
struct jpeg_decompress_struct info;
struct jpeg_error_mgr err;
info.err = jpeg_std_error(&err);
jpeg_create_decompress(&info);
jpeg_stdio_src(&info, stream);
jpeg_read_header(&info, 1);
jpeg_start_decompress(&info);
width = info.output_width;
height = info.output_height;
int stride = width * 4;
uint8_t *data = (uint8_t *) malloc(width * height * 4);
uint8_t *src = (uint8_t *) malloc(width * 3);
for (int y = 0; y < height; ++y) {
jpeg_read_scanlines(&info, &src, 1);
uint32_t *row = (uint32_t *)(data + stride * y);
for (int x = 0; x < width; ++x) {
int bx = 3 * x;
uint32_t *pixel = row + x;
*pixel = 255 << 24
| src[bx + 0] << 16
| src[bx + 1] << 8
| src[bx + 2];
}
}
_surface = cairo_image_surface_create_for_data(
data
, CAIRO_FORMAT_ARGB32
, width
, height
, width * 4);
fclose(stream);
jpeg_finish_decompress(&info);
jpeg_destroy_decompress(&info);
return cairo_surface_status(_surface);
}
/*
* Return UNKNOWN, JPEG, or PNG based on the filename.
*/
Image::type
Image::extension(const char *filename) {
size_t len = strlen(filename);
filename += len;
if (0 == strcmp(".jpeg", filename - 5)) return Image::JPEG;
if (0 == strcmp(".jpg", filename - 4)) return Image::JPEG;
if (0 == strcmp(".png", filename - 4)) return Image::PNG;
return Image::UNKNOWN;
}

10
src/Image.h

@ -32,6 +32,8 @@ class Image: public node::ObjectWrap {
inline uint8_t *data(){ return cairo_image_surface_get_data(_surface); }
inline int stride(){ return cairo_image_surface_get_stride(_surface); }
cairo_status_t loadSurface();
cairo_status_t loadPNG();
cairo_status_t loadJPEG();
void error(Local<Value>);
void loadSync();
void loaded();
@ -44,6 +46,14 @@ class Image: public node::ObjectWrap {
, COMPLETE
} state;
typedef enum {
UNKNOWN
, JPEG
, PNG
} type;
static type extension(const char *filename);
private:
cairo_surface_t *_surface;
~Image();

3
wscript

@ -11,6 +11,7 @@ def configure(conf):
conf.check_tool('compiler_cxx')
conf.check_tool('node_addon')
conf.env.append_value('CPPFLAGS', '-DNDEBUG')
conf.check(lib='jpeg', uselib_store='JPEG')
conf.check_cfg(package='cairo', mandatory=1, args='--cflags --libs')
flags = ['-O3', '-Wall']
conf.env.append_value('CCFLAGS', flags)
@ -20,4 +21,4 @@ def build(bld):
obj = bld.new_task_gen('cxx', 'shlib', 'node_addon')
obj.target = 'canvas'
obj.source = bld.glob('src/*.cc')
obj.uselib = ['CAIRO']
obj.uselib = ['CAIRO', 'JPEG']
Loading…
Cancel
Save