- q3 2004.05.30 . Reader.open(), Writer.open()を新設。引数としてファイル名を与える。 . Reader.new(), Writer.new()を変更。引数としてIO, StringIOなどread(), write()メソッド を持つオブジェクトを与える。 . 実行時に"string contains \0 character"警告が出るのを抑制。 diff -Naurw ruby-libpng-0.3.3.orig/libpng.h ruby-libpng-0.3.3/libpng.h --- ruby-libpng-0.3.3.orig/libpng.h 2000-06-27 08:35:29.000000000 +0900 +++ ruby-libpng-0.3.3/libpng.h 2004-05-29 00:04:52.000000000 +0900 @@ -33,7 +33,7 @@ #define PNG_BYTES_TO_CHECK 4 typedef struct _png_object { - FILE *fp; + VALUE io; png_structp obj; png_infop info; png_infop end_info; diff -Naurw ruby-libpng-0.3.3.orig/reader.c ruby-libpng-0.3.3/reader.c --- ruby-libpng-0.3.3.orig/reader.c 2000-07-03 19:30:41.000000000 +0900 +++ ruby-libpng-0.3.3/reader.c 2004-05-29 22:51:23.897537192 +0900 @@ -34,18 +34,34 @@ VALUE cReader; +static void close_io(png_object* png_obj) +{ + if (png_obj->io) { + // rb_funcall(png_obj->io, rb_intern("close"), 0); + png_obj->io = NULL; + } +} + +static void mark_obj(png_object* ptr) +{ + if (ptr->io) + rb_gc_mark(ptr->io); +} static void libpng_reader_free(png_obj) png_object *png_obj; { - if (png_obj->fp) - fclose(png_obj->fp); + close_io(png_obj); png_destroy_read_struct(&png_obj->obj, &png_obj->info, &png_obj->end_info); free(png_obj); } - +static VALUE reader_s_alloc(VALUE klass) +{ + png_object* png_obj; + return Data_Make_Struct(klass, png_object, mark_obj, libpng_reader_free, png_obj); +} static void png_default_error(png_ptr, message) @@ -106,47 +122,50 @@ } */ +static VALUE reader_s_open(VALUE klass, VALUE filename) +{ + VALUE io; + SafeStringValue(filename); + io = rb_file_open(RSTRING(filename)->ptr, "rb"); + return rb_class_new_instance(1, &io, klass); +} +static void read_data_fn(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_object* png_obj = png_get_io_ptr(png_ptr); + VALUE result = rb_funcall(png_obj->io, rb_intern("read"), 1, INT2NUM(length)); + memcpy(data, RSTRING(result)->ptr, RSTRING(result)->len); +} static VALUE -libpng_reader_new(klass, file) - VALUE klass, file; +reader_initialize( + VALUE self, + VALUE io) { - FILE *fp; - OpenFile *fptr; - VALUE new_obj; png_object *png_obj; - char buf[PNG_BYTES_TO_CHECK]; - - - Check_Type(file, T_STRING); + VALUE buf; - if ((fp = fopen(STR2CSTR(file), "rb")) == NULL){ - rb_raise(ePngError, "can't open %s", STR2CSTR(file)); - return Qnil; - } + Data_Get_Struct(self, png_object, png_obj); + png_obj->io = io; - if (fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK){ - rb_raise(rb_eException, "can't read %s", STR2CSTR(file)); + buf = rb_funcall(png_obj->io, rb_intern("read"), 1, INT2NUM(PNG_BYTES_TO_CHECK)); + StringValue(buf); + if (RSTRING(buf)->len != PNG_BYTES_TO_CHECK) { + rb_raise(rb_eException, "can't read IO"); return Qnil; } - if (png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)){ - rb_raise(ePngError, "not PNG file %s", STR2CSTR(file)); + if (png_sig_cmp(RSTRING(buf)->ptr, (png_size_t) 0, PNG_BYTES_TO_CHECK)) { + rb_raise(ePngError, "not PNG file"); return Qnil; } /* create PNG object */ - - new_obj = Data_Make_Struct(klass, png_object, NULL, libpng_reader_free, png_obj); - - png_obj->fp = fp; - png_obj->obj = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, png_default_error, png_default_warning); if (png_obj->obj == NULL){ - fclose(fp); + close_io(png_obj); rb_raise(ePngError, "can't create PNG object (failer to create read struct)"); return Qnil; } @@ -157,20 +176,20 @@ png_obj->end_info = png_create_info_struct(png_obj->obj); if (png_obj->info == NULL || png_obj->end_info == NULL){ - fclose(fp); + close_io(png_obj); png_destroy_read_struct(&png_obj->obj, &png_obj->info, &png_obj->end_info); rb_raise(ePngError, "can't create PNG object (failer to create info struct)"); return Qnil; } if (setjmp(png_jmpbuf(png_obj->obj))){ - fclose(fp); + close_io(png_obj); png_destroy_read_struct(&png_obj->obj, &png_obj->info, &png_obj->end_info); rb_raise(ePngError, "PNG read error"); return Qnil; } - png_init_io(png_obj->obj, png_obj->fp); + png_set_read_fn(png_obj->obj, png_obj, read_data_fn); png_read_info(png_obj->obj, png_obj->info); @@ -180,9 +199,7 @@ png_set_read_user_transform_fn(read_ptr, read_user_transform); */ - rb_obj_call_init(new_obj, 1, &file); - - return new_obj; + return Qnil; } @@ -1894,13 +1911,13 @@ Init_reader() { cReader = rb_define_class_under(mPng, "Reader", rb_cObject); - + rb_define_alloc_func(cReader, reader_s_alloc); /* define class methods */ - rb_define_singleton_method(cReader, "new", libpng_reader_new, 1); - + rb_define_singleton_method(cReader, "open", reader_s_open, 1); /* define instance methods */ + rb_define_method(cReader, "initialize", reader_initialize, 1); rb_define_method(cReader, "get_bit_depth", libpng_reader_get_bit_depth, 0); #if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) diff -Naurw ruby-libpng-0.3.3.orig/sample/pngcat.rb ruby-libpng-0.3.3/sample/pngcat.rb --- ruby-libpng-0.3.3.orig/sample/pngcat.rb 2000-06-26 21:42:31.000000000 +0900 +++ ruby-libpng-0.3.3/sample/pngcat.rb 2004-05-29 22:54:34.829511120 +0900 @@ -15,13 +15,13 @@ in_name = [] rpng = [] -wpng = Writer.new out_name +wpng = Writer.open(out_name) print "PNG image writer creater. (for #{out_name})\n" for i in 0..3 in_name[i] = number[i].chr + ".png" - rpng[i] = Reader.new in_name[i] + rpng[i] = Reader.open(in_name[i]) print "PNG image reader created (for #{in_name[i]}).\n" end @@ -59,7 +59,7 @@ for i in 0..3 in_images[i] = rpng[i].read_image - print "Reading image data from #{in_name[i]}\n" + print "Reading image data from '#{in_name[i]}': #{in_images[i][0].size} bytes * #{in_images[i].size} lines.\n" end diff -Naurw ruby-libpng-0.3.3.orig/writer.c ruby-libpng-0.3.3/writer.c --- ruby-libpng-0.3.3.orig/writer.c 2000-06-30 23:56:22.000000000 +0900 +++ ruby-libpng-0.3.3/writer.c 2004-05-29 23:27:46.569720584 +0900 @@ -28,12 +28,25 @@ VALUE cWriter; +static void close_io(png_object* png_obj) +{ + if (png_obj->io) { + // rb_funcall(png_obj->io, rb_intern("close"), 0); // GCに任せる + png_obj->io = NULL; + } +} + +static void mark_obj(png_object* ptr) +{ + if (ptr->io) + rb_gc_mark(ptr->io); +} + static void writer_free(png_obj) png_object *png_obj; { - if (png_obj->fp) - fclose(png_obj->fp); + close_io(png_obj); if (png_obj->info->valid & PNG_INFO_PLTE) free(png_obj->info->palette); if (png_obj->info->valid & PNG_INFO_tRNS) @@ -43,7 +56,11 @@ free(png_obj); } - +static VALUE writer_s_alloc(VALUE klass) +{ + png_object* png_obj; + return Data_Make_Struct(klass, png_object, mark_obj, writer_free, png_obj); +} static void png_default_error(png_ptr, message) @@ -85,41 +102,49 @@ -static VALUE -writer_new(klass, file) - VALUE klass, file; +static VALUE writer_s_open(VALUE klass, VALUE filename) { - FILE *fp; - OpenFile *fptr; - VALUE new_obj; - png_object *png_obj; - - - Check_Type(file, T_STRING); + VALUE io; + SafeStringValue(filename); + io = rb_file_open(RSTRING(filename)->ptr, "wb"); + return rb_class_new_instance(1, &io, klass); +} - if ((fp = fopen(STR2CSTR(file), "wb")) == NULL){ - rb_raise(rb_eException, "can't open: %s", STR2CSTR(file)); - return Qnil; +static void write_data_fn(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_object* png_obj = png_get_io_ptr(png_ptr); + rb_funcall(png_obj->io, rb_intern("write"), 1, rb_str_new(data, length)); } - /* create PNG object */ +static void flush_io_fn(png_structp png_ptr) +{ + png_object* png_obj = png_get_io_ptr(png_ptr); + rb_funcall(png_obj->io, rb_intern("flush"), 0); +} - new_obj = Data_Make_Struct(klass, png_object, NULL, writer_free, png_obj); +static VALUE +writer_initialize( + VALUE self, + VALUE io) +{ + png_object *png_obj; - png_obj->fp = fp; + Data_Get_Struct(self, png_object, png_obj); + png_obj->io = io; + /* create PNG object */ png_obj->obj = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, png_default_error, png_default_warning); if (png_obj->obj == NULL){ - fclose(fp); + close_io(png_obj); rb_raise(rb_eException, "can't create PNG object (failer to create write struct)"); return Qnil; } png_obj->info = png_create_info_struct(png_obj->obj); if (png_obj->info == NULL){ - fclose(fp); + close_io(png_obj); png_destroy_write_struct(&png_obj->obj, (png_infopp)NULL); rb_raise(rb_eException, "can't create PNG object (failer to create info struct)"); return Qnil; @@ -127,25 +152,23 @@ png_obj->end_info = png_create_info_struct(png_obj->obj); if (png_obj->end_info == NULL){ - fclose(fp); + close_io(png_obj); png_destroy_write_struct(&png_obj->obj, &png_obj->info); rb_raise(rb_eException, "can't create PNG object (failer to create info struct)"); return Qnil; } if (setjmp(png_jmpbuf(png_obj->obj))){ - fclose(fp); + close_io(png_obj); png_destroy_info_struct(png_obj->obj, &png_obj->end_info); png_destroy_write_struct(&png_obj->obj, &png_obj->info); rb_raise(rb_eException, "can't create PNG object (failer to create write struct)"); return Qnil; } - png_init_io(png_obj->obj, png_obj->fp); + png_set_write_fn(png_obj->obj, png_obj, write_data_fn, flush_io_fn); - rb_obj_call_init(new_obj, 1, &file); - - return new_obj; + return Qnil; } @@ -1278,7 +1301,7 @@ -static void +static VALUE libpng_writer_set_write_status_fn(obj, proc) VALUE obj, proc; { @@ -1321,9 +1344,11 @@ height = RARRAY(image)->len; for (row=0; rowptr[row])->len); - png_memcpy(image_data[row], STR2CSTR(RARRAY(image)->ptr[row]), - RSTRING(RARRAY(image)->ptr[row])->len); + struct RString* str; + Check_Type(RARRAY(image)->ptr[row], T_STRING); + str = RSTRING(RARRAY(image)->ptr[row]); + image_data[row] = ALLOC_N(png_byte, str->len); + png_memcpy(image_data[row], str->ptr, str->len); /* for (i=0;iptr[row])->len;i++) printf("%2x ", image_data[row][i]); @@ -1368,8 +1393,13 @@ Init_writer() { cWriter = rb_define_class_under(mPng, "Writer", rb_cObject); + rb_define_alloc_func(cWriter, writer_s_alloc); + + /* define class methods */ + rb_define_singleton_method(cWriter, "open", writer_s_open, 1); - rb_define_singleton_method(cWriter, "new", writer_new, 1); + /* define instance methods */ + rb_define_method(cWriter, "initialize", writer_initialize, 1); #if defined(PNG_READ_BACKGROUND_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED