changeset 1879:880d06578486

anaglyph support
author Vladimir Nadvornik <nadvornik@suse.cz>
date Fri, 28 Jan 2011 14:34:57 +0100
parents 11850512dbdd
children b69a33a93ace
files src/pixbuf-renderer.c src/pixbuf-renderer.h src/renderer-tiles.c
diffstat 3 files changed, 62 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/pixbuf-renderer.c	Fri Jan 28 13:13:27 2011 +0100
+++ b/src/pixbuf-renderer.c	Fri Jan 28 14:34:57 2011 +0100
@@ -428,11 +428,11 @@
 	pr->norm_center_x = 0.5;
 	pr->norm_center_y = 0.5;
 	
-	pr->stereo_mode = PR_STEREO_HORIZ;
+	pr->stereo_mode = PR_STEREO_ANAGLYPH;
 	
 	pr->renderer = (void *)renderer_tiles_new(pr, pr->stereo_mode);
 	
-	pr->renderer2 = (pr->stereo_mode && (PR_STEREO_HORIZ || PR_STEREO_VERT)) ?
+	pr->renderer2 = (pr->stereo_mode & (PR_STEREO_HORIZ | PR_STEREO_VERT)) ?
 	              (void *)renderer_tiles_new(pr, pr->stereo_mode | PR_STEREO_RIGHT) : NULL;
 
 	gtk_widget_set_double_buffered(box, FALSE);
@@ -2249,6 +2249,44 @@
 
 /*
  *-------------------------------------------------------------------
+ * stereo support
+ *-------------------------------------------------------------------
+ */
+
+#define COLOR_BYTES 3   /* rgb */
+void pr_create_anaglyph(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h)
+{
+	gint srs, drs;
+	guchar *s_pix, *d_pix;
+	guchar *sp, *dp;
+	guchar *spi, *dpi;
+	gint i, j;
+
+	srs = gdk_pixbuf_get_rowstride(right);
+	s_pix = gdk_pixbuf_get_pixels(right);
+	spi = s_pix + (x * COLOR_BYTES);
+
+	drs = gdk_pixbuf_get_rowstride(pixbuf);
+	d_pix = gdk_pixbuf_get_pixels(pixbuf);
+	dpi =  d_pix + x * COLOR_BYTES;
+
+	for (i = y; i < y + h; i++)
+		{
+		sp = spi + (i * srs);
+		dp = dpi + (i * drs);
+		for (j = 0; j < w; j++)
+			{
+			*dp = *sp; /* copy red channel */
+			sp += COLOR_BYTES;
+			dp += COLOR_BYTES;
+			}
+		}
+}
+ 
+ 
+
+/*
+ *-------------------------------------------------------------------
  * public
  *-------------------------------------------------------------------
  */
--- a/src/pixbuf-renderer.h	Fri Jan 28 13:13:27 2011 +0100
+++ b/src/pixbuf-renderer.h	Fri Jan 28 14:34:57 2011 +0100
@@ -354,5 +354,7 @@
 				     gint *res_w, gint *res_h);
 
 GList *pr_source_tile_compute_region(PixbufRenderer *pr, gint x, gint y, gint w, gint h, gboolean request);
+
+void pr_create_anaglyph(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h);
 #endif
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
--- a/src/renderer-tiles.c	Fri Jan 28 13:13:27 2011 +0100
+++ b/src/renderer-tiles.c	Fri Jan 28 14:34:57 2011 +0100
@@ -1263,7 +1263,7 @@
 	GtkWidget *box;
 	gboolean has_alpha;
 	gboolean draw = FALSE;
-	gint stereo_pixbuf_off;
+	gint stereo_right_pixbuf_off;
 
 	if (it->render_todo == TILE_RENDER_NONE && it->pixmap && !new_data) return;
 
@@ -1288,7 +1288,7 @@
 	rt_tile_prepare(rt, it);
 	has_alpha = (pr->pixbuf && gdk_pixbuf_get_has_alpha(pr->pixbuf));
 
-	stereo_pixbuf_off = (rt->stereo_mode & PR_STEREO_RIGHT) ? pr->stereo_pixbuf_off : 0;
+	stereo_right_pixbuf_off = (rt->stereo_mode & PR_STEREO_RIGHT) ? pr->stereo_pixbuf_off : 0;
 	box = GTK_WIDGET(pr);
 
 	/* FIXME checker colors for alpha should be configurable,
@@ -1308,17 +1308,18 @@
 	else if ((pr->zoom == 1.0 || pr->scale == 1.0) &&
 		 !has_alpha &&
 		 pr->orientation == EXIF_ORIENTATION_TOP_LEFT && 
-		 !(pr->func_post_process && !(pr->post_process_slow && fast)))
+		 !(pr->func_post_process && !(pr->post_process_slow && fast)) &&
+		 !(rt->stereo_mode & PR_STEREO_ANAGLYPH))
 		{
 		/* special case: faster, simple, scale 1.0, base orientation, no postprocessing */
-		gdk_draw_pixbuf(it->pixmap,
+		gdk_draw_pixbuf(it->pixmap, 
 #if GTK_CHECK_VERSION(2,20,0)
 				box->style->fg_gc[gtk_widget_get_state(box)],
 #else
 				box->style->fg_gc[GTK_WIDGET_STATE(box)],
 #endif
 				pr->pixbuf,
-				it->x + x + stereo_pixbuf_off, it->y + y,
+				it->x + x + stereo_right_pixbuf_off, it->y + y,
 				x, y,
 				w, h,
 				pr->dither_quality, it->x + x, it->y + y);
@@ -1360,7 +1361,6 @@
 				/* nothing to do */
 				break;
 			}
-		src_x += stereo_pixbuf_off * scale_x;
 		
 		/* HACK: The pixbuf scalers get kinda buggy(crash) with extremely
 		 * small sizes for anything but GDK_INTERP_NEAREST
@@ -1369,11 +1369,24 @@
 
 		rt_tile_get_region(has_alpha,
 				   pr->pixbuf, it->pixbuf, pb_x, pb_y, pb_w, pb_h,
-				   (gdouble) 0.0 - src_x,
+				   (gdouble) 0.0 - src_x - stereo_right_pixbuf_off * scale_x,
 				   (gdouble) 0.0 - src_y,
 				   scale_x, scale_y,
 				   (fast) ? GDK_INTERP_NEAREST : pr->zoom_quality,
 				   it->x + pb_x, it->y + pb_y);
+		if (rt->stereo_mode & PR_STEREO_ANAGLYPH && pr->stereo_pixbuf_off > 0)
+			{
+			GdkPixbuf *right_pb = rt_get_spare_tile(rt);
+			rt_tile_get_region(has_alpha,
+					   pr->pixbuf, right_pb, pb_x, pb_y, pb_w, pb_h,
+					   (gdouble) 0.0 - src_x - pr->stereo_pixbuf_off * scale_x,
+					   (gdouble) 0.0 - src_y,
+					   scale_x, scale_y,
+					   (fast) ? GDK_INTERP_NEAREST : pr->zoom_quality,
+					   it->x + pb_x, it->y + pb_y);
+			pr_create_anaglyph(it->pixbuf, right_pb, pb_x, pb_y, pb_w, pb_h);
+			/* do not care about freeing spare_tile, it will be reused */
+			}
 		rt_tile_apply_orientation(rt, &it->pixbuf, pb_x, pb_y, pb_w, pb_h);
 		draw = TRUE;
 		}