Re: gdk_pixbuf_flip() and eog metafiles



Federico Mena Quintero <federico ximian com> writes:

| Ole Aamot nr no writes:
| > I read about gdk_pixbuf_flip() in the list archive.
| I don't think that function exists yet.  Should be a 5-minute thing to
| write.

I'll try to finish both (horizontal flipping should work), unless there are
any objections to the appended, premature patch.

2001-05-02  Ole Aamot  <oka perceptron nr no>

        * gdk-pixbuf/gdk-pixbuf-orient.[ch] (gdk_pixbuf_flip): Horizontal
        flipping basicly works, but vertical flipping is not yet
        implemented.
        * gdk-pixbuf/testpixbuf-orient.c: Test for gdk_pixbuf_flip()
        * gdk-pixbuf/Makefile.am: Adding the files above.

I don't think it was so simple, but perhaps you know more efficient ways 
to do this?

| > Sometimes orientation correction is necessary before
| > the image is displayed.
|
| NO!  NO!  NO!  What we need to do is to fire-bomb the factories of all
| digital camera manufacturers who are to cheap to put a goddamn mercury
| sensor in their stupid cameras.  I paid nearly USD 1000 for my stupid
| camera and it sucks to have to rotate images by hand :)

Oh, this explains why there is a tag named "Orientation"
in the EXIF standard.

| > Is there work on meta files for archiving under way?
|
| Meta files of what?

Meta files would be a way to get eog display an image "correctly" without
modifying the actual images.  Anyway, perhaps that is a bad idea for eog.

The ``GNOME Photo collector'' (http://gpc.sourceforge.net) saves various 
meta information about images into a postgresql database.  Rather useful.

-- Ole

This patch lives at http://www.nr.no/~oka/2001-05-02-gdk_pixbuf_flip.patch

diff --exclude=CVS -ruN gdk-pixbuf/ChangeLog gdk-pixbuf.oka/ChangeLog
--- gdk-pixbuf/ChangeLog	Fri Apr 27 02:03:21 2001
+++ gdk-pixbuf.oka/ChangeLog	Wed May  2 15:07:25 2001
@@ -1,3 +1,10 @@
+2001-05-02  Ole Aamot  <oka perceptron nr no>
+
+	* gdk-pixbuf/gdk-pixbuf-orient.[ch] (gdk_pixbuf_flip): Horizontal
+	flipping basicly works, but vertical flipping is not yet implemented.
+	* gdk-pixbuf/testpixbuf-orient.c: Test for gdk_pixbuf_flip()
+	* gdk-pixbuf/Makefile.am: Adding the files above.
+
 2001-04-26  Federico Mena Quintero  <federico ximian com>
 
 	Released 0.11.0.
diff --exclude=CVS -ruN gdk-pixbuf/gdk-pixbuf/Makefile.am gdk-pixbuf.oka/gdk-pixbuf/Makefile.am
--- gdk-pixbuf/gdk-pixbuf/Makefile.am	Thu Mar  1 21:16:28 2001
+++ gdk-pixbuf.oka/gdk-pixbuf/Makefile.am	Wed May  2 14:44:33 2001
@@ -150,7 +150,8 @@
 builtin_libraries = 
 endif
 
-noinst_PROGRAMS = test-gdk-pixbuf testpixbuf testpixbuf-drawable testanimation testpixbuf-scale
+noinst_PROGRAMS = test-gdk-pixbuf testpixbuf testpixbuf-drawable \
+	testanimation testpixbuf-scale testpixbuf-orient
 TESTS = test-gdk-pixbuf
 
 DEPS = libgdk_pixbuf.la
@@ -168,12 +169,14 @@
 testpixbuf_LDADD = $(LDADDS) -lgmodule
 testpixbuf_drawable_LDADD = $(LDADDS)
 testpixbuf_scale_LDADD = $(LDADDS)
+testpixbuf_orient_LDADD = $(LDADDS)
 testanimation_LDADD = $(LDADDS) -lgmodule
 else
 test_gdk_pixbuf_LDADD = $(LDADDS) $(GNOME_LIBS) -lgmodule
 testpixbuf_LDADD = $(LDADDS) $(GNOME_LIBS) -lgmodule
 testpixbuf_drawable_LDADD = $(LDADDS) $(GNOME_LIBS)
 testpixbuf_scale_LDADD = $(LDADDS) $(GNOME_LIBS)
+testpixbuf_orient_LDADD = $(LDADDS) $(GNOME_LIBS)
 testanimation_LDADD = $(LDADDS) $(GNOME_LIBS) -lgmodule
 endif
 
@@ -193,6 +196,7 @@
 	gdk-pixbuf-drawable.c		\
 	gdk-pixbuf-io.c			\
 	gdk-pixbuf-loader.c		\
+	gdk-pixbuf-orient.c		\
 	gdk-pixbuf-render.c		\
 	gdk-pixbuf-scale.c		\
 	gdk-pixbuf-util.c		\
@@ -228,6 +232,7 @@
 	gdk-pixbuf.h			\
 	gdk-pixbuf-loader.h		\
 	gdk-pixbuf-features.h		\
+	gdk-pixbuf-orient.h		\
 	gdk-pixbuf-xlib.h		\
 	gdk-pixbuf-xlibrgb.h		\
 	$(CANVAS_PIXBUF_HEADERFILES)
diff --exclude=CVS -ruN gdk-pixbuf/gdk-pixbuf/gdk-pixbuf-orient.c gdk-pixbuf.oka/gdk-pixbuf/gdk-pixbuf-orient.c
--- gdk-pixbuf/gdk-pixbuf/gdk-pixbuf-orient.c	Thu Jan  1 01:00:00 1970
+++ gdk-pixbuf.oka/gdk-pixbuf/gdk-pixbuf-orient.c	Wed May  2 15:00:32 2001
@@ -0,0 +1,166 @@
+/* GdkPixbuf library - Orientation functions.
+ *
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "gdk-pixbuf-private.h"
+
+
+
+/**
+ * gdk_pixbuf_flip:
+ * @pixbuf: a #GdkPixbuf
+ * @horizontal: Whether to flip in horizontal direction.  If @horizontal is
+ * #TRUE, then flip around in horizontal direction.
+ * @vertical: Whether to flip in vertical direction.  If @vertical is #TRUE,
+ * then flip in vertical direction.  (NOT IMPLEMENTED YET!)
+ * @in_place: If in_place is #TRUE, the original @pixbuf is modified.
+ *
+ * Flips @pixbuf around horizontally and/or vertically.
+ *
+ * Return value: The original @pixbuf is modified and returned, if
+ * in_place is #TRUE.  If in_place is #FALSE, a newly created pixbuf
+ * with a reference count of 1 is returned.
+ **/
+GdkPixbuf *
+gdk_pixbuf_flip (GdkPixbuf *pixbuf,
+		 gboolean horizontal,
+		 gboolean vertical,
+		 gboolean in_place)
+{
+	GdkPixbuf *dest;
+	gint src_has_alpha;
+	gint width, height, src_rs;
+	gint dst_rs;
+
+	guchar *src_pix, *src_p;
+	guchar *dst_pix, *dst_p;
+
+	gint i, j;
+	gint alpha;
+
+	g_warning ("%s is not finished.\n", __PRETTY_FUNCTION__);
+	
+	g_return_if_fail (pixbuf != NULL);
+
+	width = gdk_pixbuf_get_width (pixbuf);
+	height = gdk_pixbuf_get_height (pixbuf);
+	src_has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
+
+	alpha = src_has_alpha ? 4 : 3;
+	
+	src_rs = gdk_pixbuf_get_rowstride (pixbuf);
+	src_pix = gdk_pixbuf_get_pixels (pixbuf);
+
+	if (in_place==TRUE) {
+		dest = pixbuf;
+		dst_rs = gdk_pixbuf_get_rowstride (pixbuf);
+		dst_pix = gdk_pixbuf_get_pixels (pixbuf);
+	} else {
+		dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, src_has_alpha, 8, width, height);
+		dst_rs = gdk_pixbuf_get_rowstride (dest);
+		dst_pix = gdk_pixbuf_get_pixels (dest);
+	}
+
+	if (horizontal==TRUE) {
+		for (i = 0; i < height; i++) {
+			src_p = src_pix + (src_rs * i);
+			dst_p = dst_pix + (dst_rs * i);
+			
+			for (j = 0; j < width; j++) {
+				*(dst_p++) = *(src_p++);
+				*(dst_p++) = *(src_p++);
+				*(dst_p++) = *(src_p++);
+				if (src_has_alpha)
+					*(dst_p) = *(src_p++);
+				dst_p = dst_p - (alpha + 3);
+			}
+		}
+	}
+	
+	return dest;
+}
+
+
+
+/**
+ * gdk_pixbuf_rotate:
+ * @pixbuf: a #GdkPixbuf
+ * @angle: angle modulo 90-degree (ie 90, 180, 270 degrees angle)
+ * @in_place: If in_place is #TRUE, the original data is modified
+ * and the same value as @pixbuf is returned.
+ *
+ * Rotates @pixbuf by 90-degree multiples in the counter-clockwise
+ * direction.
+ *
+ * Return value: The original @pixbuf is modified and returned, if
+ * in_place is #TRUE.
+ * If in_place is false, we try to allocate a new #GdkPixbuf and return
+ * NULL on failure; on success we write the flipped data there.
+ **/
+
+GdkPixbuf *
+gdk_pixbuf_rotate (GdkPixbuf *pixbuf,
+		   gint angle,
+		   gboolean in_place)
+{
+	GdkPixbuf *dest;
+	gint src_has_alpha;
+	
+	gint src_w, src_h, src_rs;
+	gint dst_w, dst_h, dst_rs;
+
+	guchar *src_pix, *src_p;
+	guchar *dst_pix, *dst_p;
+
+	gint i, j;
+	gint alpha;
+
+	g_warning ("%s is not finished.\n", __PRETTY_FUNCTION__);
+
+	g_return_val_if_fail (pixbuf != NULL, NULL);
+	g_return_val_if_fail (angle % 90 == 0, NULL);
+
+	src_w = gdk_pixbuf_get_width (pixbuf);
+	src_h = gdk_pixbuf_get_height (pixbuf);
+
+	src_has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
+	src_rs = gdk_pixbuf_get_rowstride (pixbuf);
+	src_pix = gdk_pixbuf_get_pixels (pixbuf);
+
+	alpha = (src_has_alpha ? 4 : 3);
+
+	/* NOT FINISHED! */
+				
+	if (in_place==TRUE) {
+		dest = pixbuf;
+		dst_rs = gdk_pixbuf_get_rowstride (pixbuf);
+		dst_pix = gdk_pixbuf_get_pixels (pixbuf);
+	} else {
+		dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, src_has_alpha, 8, dst_w, dst_h);
+		dst_rs = gdk_pixbuf_get_rowstride (dest);
+		dst_pix = gdk_pixbuf_get_pixels (dest);
+	}
+	return dest;
+}
+
+
+
+
+
diff --exclude=CVS -ruN gdk-pixbuf/gdk-pixbuf/gdk-pixbuf-orient.h gdk-pixbuf.oka/gdk-pixbuf/gdk-pixbuf-orient.h
--- gdk-pixbuf/gdk-pixbuf/gdk-pixbuf-orient.h	Thu Jan  1 01:00:00 1970
+++ gdk-pixbuf.oka/gdk-pixbuf/gdk-pixbuf-orient.h	Wed May  2 14:43:53 2001
@@ -0,0 +1,37 @@
+/* GdkPixbuf library - Orientation functions.
+ *
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GDK_PIXBUF_ORIENT_H
+#define GDK_PIXBUF_ORIENT_H
+
+#include "gdk-pixbuf.h"
+
+GdkPixbuf *gdk_pixbuf_flip (GdkPixbuf *pixbuf,
+			    gboolean horizontal,
+			    gboolean vertical,
+			    gboolean in_place);
+
+GdkPixbuf *gdk_pixbuf_rotate (GdkPixbuf *pixbuf,
+			      int angle,
+			      gboolean in_place);
+
+#endif /* GDK_PIXBUF_ORIENT_H */
+
+
diff --exclude=CVS -ruN gdk-pixbuf/gdk-pixbuf/testpixbuf-orient.c gdk-pixbuf.oka/gdk-pixbuf/testpixbuf-orient.c
--- gdk-pixbuf/gdk-pixbuf/testpixbuf-orient.c	Thu Jan  1 01:00:00 1970
+++ gdk-pixbuf.oka/gdk-pixbuf/testpixbuf-orient.c	Wed May  2 14:53:34 2001
@@ -0,0 +1,165 @@
+/* testpix-orient.c -- Testing orientation functions
+ *
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+	
+#include <stdio.h>
+#include <png.h>
+
+#include "gdk-pixbuf.h"
+#include "gdk-pixbuf-orient.h"
+
+#define FLIPH TRUE
+#define FLIPV TRUE
+
+gboolean
+save_pixbuf_to_file_as_png (GdkPixbuf *pixbuf, char *filename)
+{
+	FILE *handle;
+  	char *buffer;
+	gboolean has_alpha;
+	int width, height, depth, rowstride;
+  	guchar *pixels;
+  	png_structp png_ptr;
+  	png_infop info_ptr;
+  	png_text text[2];
+  	int i;
+
+	g_return_val_if_fail (pixbuf != NULL, FALSE);
+	g_return_val_if_fail (filename != NULL, FALSE);
+	g_return_val_if_fail (filename[0] != '\0', FALSE);
+
+        handle = fopen (filename, "wb");
+        if (handle == NULL)
+        	return FALSE;
+
+	png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+	if (png_ptr == NULL) {
+		fclose (handle);
+		return FALSE;
+	}
+
+	info_ptr = png_create_info_struct (png_ptr);
+	if (info_ptr == NULL) {
+		png_destroy_write_struct (&png_ptr, (png_infopp)NULL);
+		fclose (handle);
+	    	return FALSE;
+	}
+
+	if (setjmp (png_ptr->jmpbuf)) {
+		png_destroy_write_struct (&png_ptr, &info_ptr);
+		fclose (handle);
+		return FALSE;
+	}
+
+	png_init_io (png_ptr, handle);
+
+        has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
+	width = gdk_pixbuf_get_width (pixbuf);
+	height = gdk_pixbuf_get_height (pixbuf);
+	depth = gdk_pixbuf_get_bits_per_sample (pixbuf);
+	pixels = gdk_pixbuf_get_pixels (pixbuf);
+	rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+
+	png_set_IHDR (png_ptr, info_ptr, width, height,
+		      depth, PNG_COLOR_TYPE_RGB_ALPHA,
+		      PNG_INTERLACE_NONE,
+		      PNG_COMPRESSION_TYPE_DEFAULT,
+		      PNG_FILTER_TYPE_DEFAULT);
+
+	/* Some text to go with the png image */
+	text[0].key = "Title";
+	text[0].text = filename;
+	text[0].compression = PNG_TEXT_COMPRESSION_NONE;
+	text[1].key = "Software";
+	text[1].text = "testpixbuf-orient (gdk-pixbuf)";
+	text[1].compression = PNG_TEXT_COMPRESSION_NONE;
+	png_set_text (png_ptr, info_ptr, text, 2);
+
+	/* Write header data */
+	png_write_info (png_ptr, info_ptr);
+
+	/* if there is no alpha in the data, allocate buffer to expand into */
+	if (has_alpha)
+		buffer = NULL;
+	else
+		buffer = g_malloc(4 * width);
+	
+	/* pump the raster data into libpng, one scan line at a time */	
+	for (i = 0; i < height; i++) {
+		if (has_alpha) {
+			png_bytep row_pointer = pixels;
+			png_write_row (png_ptr, row_pointer);
+		} else {
+			/* expand RGB to RGBA using an opaque alpha value */
+			int x;
+			char *buffer_ptr = buffer;
+			char *source_ptr = pixels;
+			for (x = 0; x < width; x++) {
+				*buffer_ptr++ = *source_ptr++;
+				*buffer_ptr++ = *source_ptr++;
+				*buffer_ptr++ = *source_ptr++;
+				*buffer_ptr++ = 255;
+			}
+			png_write_row (png_ptr, (png_bytep) buffer);
+		}
+		pixels += rowstride;
+	}
+	
+	png_write_end (png_ptr, info_ptr);
+	png_destroy_write_struct (&png_ptr, &info_ptr);
+	
+	g_free (buffer);
+		
+	fclose (handle);
+	return TRUE;
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+	GdkPixbuf *pixbuf, *flippedout_h, *flippedout_v, *flippedout_hv;
+
+	int angle;
+
+	gtk_init (&argc, &argv);
+	gdk_rgb_init ();
+
+	if (argc != 2) {
+		fprintf (stderr, "Usage: testpixbuf-orient FILE\n");
+		exit (1);
+	}
+
+	pixbuf = gdk_pixbuf_new_from_file (argv[1]);
+	
+	if (!pixbuf) {
+		fprintf (stderr, "Cannot load %s\n", argv[1]);
+		exit(1);
+	}
+
+	flippedout_h = gdk_pixbuf_flip(pixbuf, TRUE, FALSE, FALSE);
+/*  	flippedout_v = gdk_pixbuf_flip(pixbuf, FALSE, TRUE, FALSE); */
+
+	save_pixbuf_to_file_as_png (pixbuf,"testorient-unflipped-original.png");
+	save_pixbuf_to_file_as_png (flippedout_h,"testorient-flipped-horizontal.png");
+/*  	save_pixbuf_to_file_as_png (flippedout_v,"testorient-flipped-vertical.png"); */
+	
+	exit(0);
+}




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]