If you are looking for Ruby extension to use GD library, plese check here.
因为实在无法忍受JRuby调用JAVA API处理Jpeg的龟速,所以花了点时间改了一下Ruby/GD的代码,使其能运行在mswin32版Ruby 1.9.1下。成果是有一点,不过还是有暂时无法解决的问题。
Ruby/GD用到的API主要是IO部分,从Ruby的头文件定义来看,变动不小。以下这几个宏,是我从RMagick等其他扩展里抄来的:
// GetReadFile doesn't exist in Ruby 1.9.0 #if !defined(GetReadFile) #define GetReadFile(fptr) rb_io_stdio_file(fptr) #define GetWriteFile(fptr) rb_io_stdio_file(fptr) #endif // rb_io_t replaces OpenFile in Ruby 1.9.0 #if defined(HAVE_RB_IO_T) #undef OpenFile #define OpenFile rb_io_t #endif // These macros are required in 1.9.1 but aren't defined prior to 1.8.6. #if !defined(RSTRING_LEN) #define RSTRING_LEN(s) (RSTRING((s))->len) #endif #if !defined(RSTRING_PTR) #define RSTRING_PTR(s) (RSTRING((s))->ptr) #endif // Backport these two macros to 1.8 #if !defined(RARRAY_LEN) #define RARRAY_LEN(a) RARRAY((a))->len #endif // Matz says this macro is read-only! (see http://www.ruby-forum.com/topic/146072) #if !defined(RARRAY_PTR) #define RARRAY_PTR(a) RARRAY((a))->ptr #endif
变化很大,而且还没解决的问题在rb_io_t结构体上。Ruby 1.8中,该结构体包括两个*File指针,虽然不清楚区别是什么,反正是可写的。而Ruby 1.9中rb_io_t增加了很多内容,*File指针变为一个,而且不可写。
static VALUE img_from_jpeg(VALUE img, VALUE out, VALUE quality) { gdImagePtr im; OpenFile *fptr; FILE *f; Data_Get_Struct(img, gdImage, im); Check_Type(out, T_FILE); rb_io_binmode(out); GetOpenFile(out, fptr); rb_io_check_writable(fptr); f = GetWriteFile(fptr); gdImageJpeg(im, f, FIX2INT(quality)); return img; }
以上函数就这么看似乎没什么不对,可就是会出错。
另外,我还发现Ruby/GD的API设计也怪怪的,有那么点不合理。比如载入Jpeg文件,Ruby/GD有两个方法:GD::Image.newFromJpeg和GD::Image.new_from_jpeg。这两个并非同名函数,前者接受的参数是File对象,后者接受文件路径。再比如copy方法,其定义为:srcimg.copy(destimg, dx, dy, sx, sy, w, h)。调用该方法后,有变化的是作为参数的destimg,而非调用者的srcimg,这似乎与平常的习惯相反。
改到最后,虽然只有newFromXXX系列函数不能用,可怎么着都觉得有点不舒服。最后还是以Ruby/GD为蓝本,改写了一个扩展出来,有兴趣的话参见这里。至于我改的Ruby/GD就不提供下载了,实在需要的话,留言吧。
没有评论 :
发表评论