/* * * BOOH * * * A.k.a `Best web-album Of the world, Or your money back, Humerus'. * * The acronyn sucks, however this is a tribute to Dragon Ball by * Akira Toriyama, where the last enemy beaten by heroes of Dragon * Ball is named "Boo". But there was already a free software project * called Boo, so this one will be it "Booh". Or whatever. * * * Copyright (c) 2005 Guillaume Cottenceau * * This software may be freely redistributed under the terms of the GNU * public license version 2. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #define GDK_PIXBUF_ENABLE_BACKEND #include #include "rbgobject.h" #define _SELF(s) GDK_PIXBUF(RVAL2GOBJ(s)) #include static VALUE whitebalance(self, level) VALUE self, level; { double red_filter[256], blue_filter[256]; int i, x, y; guchar* pixels = gdk_pixbuf_get_pixels(_SELF(self)); int rowstride = gdk_pixbuf_get_rowstride(_SELF(self)); double factor = 1 + fabs(NUM2DBL(level))/100; if (NUM2DBL(level) < 0) { factor = 1/factor; } for (i = 0; i < 256; i++) { red_filter[i] = pow(((double)i)/255, 1/factor) * 255; blue_filter[i] = pow(((double)i)/255, factor) * 255; } for (y = 0; y < gdk_pixbuf_get_height(_SELF(self)); y++) { guchar* pixline = &(pixels[rowstride*y]); for (x = 0; x < gdk_pixbuf_get_width(_SELF(self)); x++) { pixline[x*3] = red_filter[pixline[x*3]]; pixline[x*3+2] = blue_filter[pixline[x*3+2]]; } } return self; } static VALUE gammacorrect(self, level) VALUE self, level; { double filter[256]; int i, x, y; guchar* pixels = gdk_pixbuf_get_pixels(_SELF(self)); int rowstride = gdk_pixbuf_get_rowstride(_SELF(self)); double factor = 1 + fabs(NUM2DBL(level))/100; if (NUM2DBL(level) > 0) { factor = 1/factor; } for (i = 0; i < 256; i++) { filter[i] = pow(((double)i)/255, factor) * 255; } for (y = 0; y < gdk_pixbuf_get_height(_SELF(self)); y++) { guchar* pixline = &(pixels[rowstride*y]); for (x = 0; x < gdk_pixbuf_get_width(_SELF(self)); x++) { pixline[x*3] = filter[pixline[x*3]]; pixline[x*3+1] = filter[pixline[x*3+1]]; pixline[x*3+2] = filter[pixline[x*3+2]]; } } return self; } static ExifEntry* exif_entry(VALUE filename, ExifTag tag, ExifData** data) { unsigned int i; *data = exif_data_new_from_file(StringValuePtr(filename)); if (*data == NULL) { fprintf(stderr, "libexif failed loading file '%s'\n", StringValuePtr(filename)); return NULL; } for (i = 0; i < EXIF_IFD_COUNT; i++) { ExifEntry* entry = exif_content_get_entry((*data)->ifd[i], tag); if (entry) return entry; } return NULL; } static VALUE exif_orientation(VALUE module, VALUE filename) { ExifData* data = NULL; ExifEntry* entry; entry = exif_entry(filename, EXIF_TAG_ORIENTATION, &data); if (entry != NULL) { VALUE ret; ExifByteOrder o; ExifShort v_short; if (!entry || !entry->parent || !entry->parent->parent) return Qnil; o = exif_data_get_byte_order(entry->parent->parent); v_short = exif_get_short(entry->data, o); ret = INT2NUM(v_short); exif_data_free(data); return ret; } if (data) exif_data_free(data); return Qnil; } static VALUE exif_datetimeoriginal(VALUE module, VALUE filename) { ExifData* data = NULL; ExifEntry* entry; entry = exif_entry(filename, EXIF_TAG_DATE_TIME_ORIGINAL, &data); if (entry != NULL) { VALUE ret = rb_str_new((const char*) entry->data, entry->size); exif_data_free(data); return ret; } if (data) exif_data_free(data); return Qnil; } static VALUE draw_borders(VALUE self, VALUE pixbuf, VALUE x1, VALUE x2, VALUE ystart, VALUE yend) { GdkDrawable* drawable = GDK_DRAWABLE(RVAL2GOBJ(self)); int y = NUM2INT(ystart); int yend_ = NUM2INT(yend); GdkPixbuf* pb = GDK_PIXBUF(RVAL2GOBJ(pixbuf)); int height = gdk_pixbuf_get_height(pb); while (y < yend_) { int render_height = MIN(height, yend_ - y); gdk_draw_pixbuf(drawable, NULL, pb, 0, 0, NUM2INT(x1), y, -1, render_height, GDK_RGB_DITHER_NONE, -1, -1); gdk_draw_pixbuf(drawable, NULL, pb, 0, 0, NUM2INT(x2), y, -1, render_height, GDK_RGB_DITHER_NONE, -1, -1); y += height; } return self; } void Init_libadds() { RGObjClassInfo* cinfo = (RGObjClassInfo*)rbgobj_lookup_class_by_gtype(GDK_TYPE_PIXBUF, Qnil); rb_define_method(cinfo->klass, "whitebalance!", whitebalance, 1); rb_define_method(cinfo->klass, "gammacorrect!", gammacorrect, 1); cinfo = (RGObjClassInfo*)rbgobj_lookup_class_by_gtype(GDK_TYPE_DRAWABLE, Qnil); rb_define_method(cinfo->klass, "draw_borders", draw_borders, 5); VALUE exif = rb_define_module("Exif"); rb_define_module_function(exif, "orientation", exif_orientation, 1); rb_define_module_function(exif, "datetimeoriginal", exif_datetimeoriginal, 1); }