Browse Source

Refactor JPEG decoding into decodeJPEGIntoSurface

v1.x
c-spencer 13 years ago
parent
commit
d5838bc4aa
  1. 128
      src/Image.cc
  2. 12
      src/Image.h

128
src/Image.cc

@ -12,11 +12,6 @@
#include <errno.h>
#include <node_buffer.h>
#ifdef HAVE_JPEG
#include <jpeglib.h>
#include <jerror.h>
#endif
#ifdef HAVE_GIF
#include <gif_lib.h>
typedef struct {
@ -601,45 +596,28 @@ static void jpeg_mem_src (j_decompress_ptr cinfo, void* buffer, long nbytes) {
#endif
/*
* Load jpeg from buffer.
*/
cairo_status_t
Image::loadJPEGFromBuffer(uint8_t *buf, unsigned len) {
// TODO: remove this duplicate logic
// JPEG setup
struct jpeg_decompress_struct info;
struct jpeg_error_mgr err;
info.err = jpeg_std_error(&err);
jpeg_create_decompress(&info);
jpeg_mem_src(&info, buf, len);
jpeg_read_header(&info, 1);
jpeg_start_decompress(&info);
width = info.output_width;
height = info.output_height;
// Data alloc
Image::decodeJPEGIntoSurface(jpeg_decompress_struct *info) {
int stride = width * 4;
uint8_t *data = (uint8_t *) malloc(width * height * 4);
cairo_status_t status;
uint8_t *data = (uint8_t *) malloc(width * height * 4);
if (!data) {
jpeg_finish_decompress(&info);
jpeg_destroy_decompress(&info);
jpeg_finish_decompress(info);
jpeg_destroy_decompress(info);
return CAIRO_STATUS_NO_MEMORY;
}
uint8_t *src = (uint8_t *) malloc(width * 3);
if (!src) {
free(data);
jpeg_finish_decompress(&info);
jpeg_destroy_decompress(&info);
jpeg_finish_decompress(info);
jpeg_destroy_decompress(info);
return CAIRO_STATUS_NO_MEMORY;
}
// Copy RGB -> ARGB
for (int y = 0; y < height; ++y) {
jpeg_read_scanlines(&info, &src, 1);
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;
@ -651,7 +629,6 @@ Image::loadJPEGFromBuffer(uint8_t *buf, unsigned len) {
}
}
// New image surface
_surface = cairo_image_surface_create_for_data(
data
, CAIRO_FORMAT_ARGB32
@ -659,94 +636,69 @@ Image::loadJPEGFromBuffer(uint8_t *buf, unsigned len) {
, height
, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width));
// Cleanup
free(src);
jpeg_finish_decompress(&info);
jpeg_destroy_decompress(&info);
cairo_status_t status = cairo_surface_status(_surface);
jpeg_finish_decompress(info);
jpeg_destroy_decompress(info);
status = cairo_surface_status(_surface);
if (status) {
free(data);
free(src);
return status;
}
free(src);
_data = data;
return CAIRO_STATUS_SUCCESS;
}
/*
* Load JPEG, convert RGB to ARGB.
* Load jpeg from buffer.
*/
cairo_status_t
Image::loadJPEG(FILE *stream) {
Image::loadJPEGFromBuffer(uint8_t *buf, unsigned len) {
// TODO: remove this duplicate logic
// JPEG setup
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_mem_src(&info, buf, len);
jpeg_read_header(&info, 1);
jpeg_start_decompress(&info);
width = info.output_width;
height = info.output_height;
// Data alloc
int stride = width * 4;
uint8_t *data = (uint8_t *) malloc(width * height * 4);
return decodeJPEGIntoSurface(&info);
}
if (!data) {
fclose(stream);
jpeg_finish_decompress(&info);
jpeg_destroy_decompress(&info);
return CAIRO_STATUS_NO_MEMORY;
}
/*
* Load JPEG, convert RGB to ARGB.
*/
uint8_t *src = (uint8_t *) malloc(width * 3);
cairo_status_t
Image::loadJPEG(FILE *stream) {
// JPEG setup
struct jpeg_decompress_struct info;
struct jpeg_error_mgr err;
info.err = jpeg_std_error(&err);
jpeg_create_decompress(&info);
if (!src) {
free(data);
fclose(stream);
jpeg_finish_decompress(&info);
jpeg_destroy_decompress(&info);
return CAIRO_STATUS_NO_MEMORY;
}
jpeg_stdio_src(&info, stream);
// Copy RGB -> ARGB
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];
}
}
jpeg_read_header(&info, 1);
jpeg_start_decompress(&info);
width = info.output_width;
height = info.output_height;
// New image surface
_surface = cairo_image_surface_create_for_data(
data
, CAIRO_FORMAT_ARGB32
, width
, height
, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width));
cairo_status_t status;
// Cleanup
free(src);
status = decodeJPEGIntoSurface(&info);
fclose(stream);
jpeg_finish_decompress(&info);
jpeg_destroy_decompress(&info);
cairo_status_t status = cairo_surface_status(_surface);
if (status) {
free(data);
return status;
}
return CAIRO_STATUS_SUCCESS;
return status;
}
#endif /* HAVE_JPEG */

12
src/Image.h

@ -10,6 +10,11 @@
#include "Canvas.h"
#ifdef HAVE_JPEG
#include <jpeglib.h>
#include <jerror.h>
#endif
class Image: public node::ObjectWrap {
public:
char *filename;
@ -47,6 +52,7 @@ class Image: public node::ObjectWrap {
#ifdef HAVE_JPEG
cairo_status_t loadJPEGFromBuffer(uint8_t *buf, unsigned len);
cairo_status_t loadJPEG(FILE *stream);
cairo_status_t decodeJPEGIntoSurface(jpeg_decompress_struct *info);
#endif
void error(Local<Value> error);
void loaded();
@ -59,6 +65,12 @@ class Image: public node::ObjectWrap {
, COMPLETE
} state;
enum {
DATA_IMAGE,
DATA_MIME,
DATA_IMAGE_AND_MIME
} data_mode;
typedef enum {
UNKNOWN
, GIF

Loading…
Cancel
Save