4 * A.k.a `Best web-album Of the world, Or your money back, Humerus'.
6 * The acronyn sucks, however this is a tribute to Dragon Ball by
7 * Akira Toriyama, where the last enemy beaten by heroes of Dragon
8 * Ball is named "Boo". But there was already a free software project
9 * called Boo, so this one will be it "Booh". Or whatever.
12 * Copyright (c) 2005 Guillaume Cottenceau
14 * This software may be freely redistributed under the terms of the GNU
15 * public license version 2.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #define GDK_PIXBUF_ENABLE_BACKEND
27 #include "rbgobject.h"
29 #define _SELF(s) GDK_PIXBUF(RVAL2GOBJ(s))
31 #include <libexif/exif-data.h>
34 whitebalance(self, level)
37 double red_filter[256], blue_filter[256];
39 guchar* pixels = gdk_pixbuf_get_pixels(_SELF(self));
40 int rowstride = gdk_pixbuf_get_rowstride(_SELF(self));
42 double factor = 1 + fabs(NUM2DBL(level))/100;
43 if (NUM2DBL(level) < 0) {
47 for (i = 0; i < 256; i++) {
48 red_filter[i] = pow(((double)i)/255, 1/factor) * 255;
49 blue_filter[i] = pow(((double)i)/255, factor) * 255;
52 for (y = 0; y < gdk_pixbuf_get_height(_SELF(self)); y++) {
53 guchar* pixline = &(pixels[rowstride*y]);
54 for (x = 0; x < gdk_pixbuf_get_width(_SELF(self)); x++) {
55 pixline[x*3] = red_filter[pixline[x*3]];
56 pixline[x*3+2] = blue_filter[pixline[x*3+2]];
64 gammacorrect(self, level)
69 guchar* pixels = gdk_pixbuf_get_pixels(_SELF(self));
70 int rowstride = gdk_pixbuf_get_rowstride(_SELF(self));
72 double factor = 1 + fabs(NUM2DBL(level))/100;
73 if (NUM2DBL(level) > 0) {
77 for (i = 0; i < 256; i++) {
78 filter[i] = pow(((double)i)/255, factor) * 255;
81 for (y = 0; y < gdk_pixbuf_get_height(_SELF(self)); y++) {
82 guchar* pixline = &(pixels[rowstride*y]);
83 for (x = 0; x < gdk_pixbuf_get_width(_SELF(self)); x++) {
84 pixline[x*3] = filter[pixline[x*3]];
85 pixline[x*3+1] = filter[pixline[x*3+1]];
86 pixline[x*3+2] = filter[pixline[x*3+2]];
93 static ExifEntry* exif_entry(VALUE filename, ExifTag tag, ExifData** data) {
96 *data = exif_data_new_from_file(StringValuePtr(filename));
98 fprintf(stderr, "libexif failed loading file '%s'\n", StringValuePtr(filename));
102 for (i = 0; i < EXIF_IFD_COUNT; i++) {
103 ExifEntry* entry = exif_content_get_entry((*data)->ifd[i], tag);
111 static VALUE exif_orientation(VALUE module, VALUE filename) {
112 ExifData* data = NULL;
115 entry = exif_entry(filename, EXIF_TAG_ORIENTATION, &data);
121 if (!entry || !entry->parent || !entry->parent->parent)
123 o = exif_data_get_byte_order(entry->parent->parent);
124 v_short = exif_get_short(entry->data, o);
125 ret = INT2NUM(v_short);
126 exif_data_free(data);
131 exif_data_free(data);
135 static VALUE exif_datetimeoriginal(VALUE module, VALUE filename) {
136 ExifData* data = NULL;
139 entry = exif_entry(filename, EXIF_TAG_DATE_TIME_ORIGINAL, &data);
142 VALUE ret = rb_str_new((const char*) entry->data, entry->size);
143 exif_data_free(data);
148 exif_data_free(data);
152 static VALUE draw_borders(VALUE self, VALUE pixbuf, VALUE x1, VALUE x2, VALUE ystart, VALUE yend) {
153 GdkDrawable* drawable = GDK_DRAWABLE(RVAL2GOBJ(self));
154 int y = NUM2INT(ystart);
155 int yend_ = NUM2INT(yend);
156 GdkPixbuf* pb = GDK_PIXBUF(RVAL2GOBJ(pixbuf));
157 int height = gdk_pixbuf_get_height(pb);
159 int render_height = MIN(height, yend_ - y);
160 gdk_draw_pixbuf(drawable, NULL, pb, 0, 0, NUM2INT(x1), y, -1, render_height, GDK_RGB_DITHER_NONE, -1, -1);
161 gdk_draw_pixbuf(drawable, NULL, pb, 0, 0, NUM2INT(x2), y, -1, render_height, GDK_RGB_DITHER_NONE, -1, -1);
167 static VALUE rotate_noleak(VALUE self, VALUE angle) {
169 GdkPixbuf* dest = gdk_pixbuf_rotate_simple(_SELF(self), RVAL2GENUM(angle, GDK_TYPE_PIXBUF_ROTATION));
172 ret = GOBJ2RVAL(dest);
173 g_object_unref(dest);
177 static VALUE modify_bg(VALUE self, VALUE state, VALUE color) {
178 gtk_widget_modify_bg(GTK_WIDGET(RVAL2GOBJ(self)), RVAL2GENUM(state, GTK_TYPE_STATE_TYPE),
179 NIL_P(color) ? NULL : (GdkColor*) RVAL2BOXED(color, GDK_TYPE_COLOR));
186 RGObjClassInfo* cinfo = (RGObjClassInfo*)rbgobj_lookup_class_by_gtype(GDK_TYPE_PIXBUF, Qnil);
187 rb_define_method(cinfo->klass, "whitebalance!", whitebalance, 1);
188 rb_define_method(cinfo->klass, "gammacorrect!", gammacorrect, 1);
189 rb_define_method(cinfo->klass, "rotate", rotate_noleak, 1);
191 cinfo = (RGObjClassInfo*)rbgobj_lookup_class_by_gtype(GDK_TYPE_DRAWABLE, Qnil);
192 rb_define_method(cinfo->klass, "draw_borders", draw_borders, 5);
194 cinfo = (RGObjClassInfo*)rbgobj_lookup_class_by_gtype(GTK_TYPE_WIDGET, Qnil);
195 rb_define_method(cinfo->klass, "modify_bg", modify_bg, 2);
197 VALUE exif = rb_define_module("Exif");
198 rb_define_module_function(exif, "orientation", exif_orientation, 1);
199 rb_define_module_function(exif, "datetimeoriginal", exif_datetimeoriginal, 1);