drawing video borders in ruby is too slow, do it in extension
[booh] / ext / rbbooh.c
index 2d886888f2ab7b1449518472414486c5afe09b4c..56b101f0dfd3d4b09e119d342f529609b5467023 100644 (file)
 #include <math.h>
 
 #define GDK_PIXBUF_ENABLE_BACKEND
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <gdk-pixbuf/gdk-pixdata.h>
+#include <gtk/gtk.h>
 #include "rbgobject.h"
 
 #define _SELF(s) GDK_PIXBUF(RVAL2GOBJ(s)) 
 
+#include <libexif/exif-data.h>
+
 static VALUE
 whitebalance(self, level)
     VALUE self, level; 
@@ -89,10 +90,92 @@ gammacorrect(self, level)
         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_gtkadds()
+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);
 }