ext/jpeg/jpeg_image.c in jpeg-0.5.1 vs ext/jpeg/jpeg_image.c in jpeg-0.6.0
- old
+ new
@@ -12,10 +12,11 @@
static void jpeg_image_free(struct rb_jpeg_image *p);
static VALUE jpeg_image_width(VALUE self);
static VALUE jpeg_image_height(VALUE self);
static VALUE jpeg_image_size(VALUE self);
static VALUE jpeg_image_color_info(VALUE self);
+static VALUE jpeg_image_raw_data(VALUE self);
extern VALUE rb_eJpegError;
void Init_jpeg_image(void) {
rb_cJpegImage = rb_define_class_under(rb_mJpeg, "Image", rb_cObject);
@@ -23,21 +24,23 @@
rb_define_singleton_method(rb_cJpegImage, "open", jpeg_image_s_open, -1);
rb_define_method(rb_cJpegImage, "width", jpeg_image_width, 0);
rb_define_method(rb_cJpegImage, "height", jpeg_image_height, 0);
rb_define_method(rb_cJpegImage, "size", jpeg_image_size, 0);
rb_define_method(rb_cJpegImage, "color_info", jpeg_image_color_info, 0);
+ rb_define_method(rb_cJpegImage, "raw_data", jpeg_image_raw_data, 0);
}
void jpeg_image_exit(j_common_ptr jpeg) {
char buffer[JMSG_LENGTH_MAX];
jpeg->err->format_message(jpeg, buffer);
- rb_raise(rb_eJpegError, buffer);
+ rb_raise(rb_eJpegError, "%s", buffer);
}
static VALUE jpeg_image_alloc(VALUE klass) {
struct rb_jpeg_image *jpeg = ALLOC(struct rb_jpeg_image);
+ jpeg->fp = NULL;
jpeg->read = (void *)ALLOC(struct jpeg_decompress_struct);
jpeg->error = (void *)ALLOC(struct jpeg_error_mgr);
jpeg->read->err = jpeg_std_error(jpeg->error);
jpeg->error->error_exit = jpeg_image_exit;
jpeg_create_decompress(jpeg->read);
@@ -55,62 +58,114 @@
xfree(p->read);
}
if (p->error) {
xfree(p->error);
}
+ if (p->fp) {
+ fclose(p->fp);
+ }
xfree(p);
}
static VALUE jpeg_image_s_open(int argc, VALUE *argv, VALUE self) {
VALUE path;
VALUE jpeg;
struct rb_jpeg_image *p_jpeg;
- FILE *fp;
char *filename;
rb_scan_args(argc, argv, "1", &path);
Check_Type(path, T_STRING);
jpeg = rb_funcall(rb_cJpegImage, rb_intern("new"), 0);
Data_Get_Struct(jpeg, struct rb_jpeg_image, p_jpeg);
filename = StringValuePtr(path);
- if ((fp = fopen(filename, "rb")) == NULL) {
+ if ((p_jpeg->fp = fopen(filename, "rb")) == NULL) {
rb_raise(rb_eJpegError, "Open file failed: %s", filename);
}
- jpeg_stdio_src(p_jpeg->read, fp);
+ jpeg_stdio_src(p_jpeg->read, p_jpeg->fp);
jpeg_read_header(p_jpeg->read, TRUE);
- jpeg_start_decompress(p_jpeg->read);
- fclose(fp);
return jpeg;
}
static VALUE jpeg_image_width(VALUE self) {
struct rb_jpeg_image *p_jpeg;
Data_Get_Struct(self, struct rb_jpeg_image, p_jpeg);
- return rb_int_new(p_jpeg->read->output_width);
+ return rb_int_new(p_jpeg->read->image_width);
}
static VALUE jpeg_image_height(VALUE self) {
struct rb_jpeg_image *p_jpeg;
Data_Get_Struct(self, struct rb_jpeg_image, p_jpeg);
- return rb_int_new(p_jpeg->read->output_height);
+ return rb_int_new(p_jpeg->read->image_height);
}
static VALUE jpeg_image_size(VALUE self) {
struct rb_jpeg_image *p_jpeg;
VALUE array;
Data_Get_Struct(self, struct rb_jpeg_image, p_jpeg);
array = rb_ary_new();
- rb_ary_push(array, rb_int_new(p_jpeg->read->output_width));
- rb_ary_push(array, rb_int_new(p_jpeg->read->output_height));
+ rb_ary_push(array, rb_int_new(p_jpeg->read->image_width));
+ rb_ary_push(array, rb_int_new(p_jpeg->read->image_height));
return array;
}
static VALUE jpeg_image_color_info(VALUE self) {
struct rb_jpeg_image *p_jpeg;
Data_Get_Struct(self, struct rb_jpeg_image, p_jpeg);
- return ID2SYM(rb_intern( p_jpeg->read->out_color_components == 3 ? "rgb" : "gray" ));
+ return ID2SYM(rb_intern( p_jpeg->read->out_color_space == JCS_GRAYSCALE ? "gray" : "rgb" ));
+}
+
+static VALUE jpeg_image_raw_data(VALUE self) {
+ struct rb_jpeg_image *p_jpeg;
+ VALUE matrix;
+ VALUE line;
+ VALUE point;
+ int64_t line_size;
+ int64_t i;
+ JSAMPARRAY buffer;
+
+ matrix = rb_iv_get(self, "@raw_data");
+
+ if (RTEST(matrix)) {
+ return matrix;
+ }
+
+ Data_Get_Struct(self, struct rb_jpeg_image, p_jpeg);
+
+ jpeg_start_decompress(p_jpeg->read);
+
+ line_size = p_jpeg->read->output_width * p_jpeg->read->out_color_components;
+ if ((buffer = (*p_jpeg->read->mem->alloc_sarray)((j_common_ptr) p_jpeg->read, JPOOL_IMAGE, line_size, 1)) == NULL) {
+ rb_raise(rb_eJpegError, "Could not allocate memory (%ld bytes) to decode the image", line_size);
+ }
+
+ matrix = rb_ary_new();
+ while (p_jpeg->read->output_scanline < p_jpeg->read->output_height) {
+ jpeg_read_scanlines(p_jpeg->read, buffer , 1);
+
+ line = rb_ary_new();
+ if (p_jpeg->read->out_color_components == 3) {
+ for (i = 0; i < line_size; i += 3) {
+ point = rb_ary_new();
+ rb_ary_push(point, rb_int_new(buffer[0][i]));
+ rb_ary_push(point, rb_int_new(buffer[0][i + 1]));
+ rb_ary_push(point, rb_int_new(buffer[0][i + 2]));
+ rb_ary_push(line, point);
+ }
+ } else {
+ for (i = 0; i < line_size; i++) {
+ rb_ary_push(line, rb_int_new(buffer[0][i]));
+ }
+ }
+
+ rb_ary_push(matrix, line);
+ }
+ jpeg_finish_decompress(p_jpeg->read);
+
+ rb_iv_set(self, "@raw_data", matrix);
+
+ return matrix;
}