Hi!

I've been also affected by this bug. xzgv crashes when it tries to
render 32bit pixels (alpha+rgb, 8bits each) to 24bits visuals.

There's a common workaround against this bug:

   http://www.x.org/archive/X11R6.8.0/doc/RELNOTES5.html

So if you call

   $ XLIB_SKIP_ARGB_VISUALS=1 xzgv /some/path/

it should be working.

Nevertheless, I do not propose to do this, because xzgv could be
changed instead.

With the help of gdb, I've traced down the problem to main.c:2560:

In xvpic2pixmap, the call to gdk_draw_image() causes the error. This is
exactly the place where the 32bit-to-24bit rendering takes places.

According to

    
http://mail.gnome.org/archives/gtk-app-devel-list/2001-September/msg00089.html

it's not a good idea to use this function, as it involves handling every
special case like byte ordering, color depth and so on.

The link above refers to 

   http://developer.gnome.org/doc/GGAD/z132.html#SEC-GDKRGB

where the details of GdkRGB are described.

I'm not common with GTK/GDK programming, but with the help of the API
reference manual I've replaced the critical code by a GdkRGB buffer.


The the attached patch corrects the problem.


HTH

-- 
mail: [EMAIL PROTECTED]         http://adi.thur.de      PGP/GPG: key via 
keyserver

Eigentlich sieht dein ganzes Zimmer aus wie ein Tempverzeichnis.
                                                        (Mitbewohner Michael)
diff -u -r xzgv-0.9+svn34/src/main.c xzgv-new/src/main.c
--- xzgv-0.9+svn34/src/main.c   2007-12-18 13:55:59.000000000 +0100
+++ xzgv-new/src/main.c 2008-05-20 15:23:15.000000000 +0200
@@ -38,6 +38,7 @@
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
 #include <gdk/gdkx.h>          /* needed for iconify stuff */
+#include <gdk/gdkrgb.h>     /* http://bugs.debian.org/457252 */
 #include <X11/Xlib.h>          /* ditto */
 
 #include "backend.h"
@@ -105,7 +106,7 @@
 
 GtkWidget *mainwin;
 
-gint xvpic_pal[256];           /* palette for thumbnails */
+guint8 xvpic_pal[256][3];              /* palette for thumbnails */
 
 /* image & rendered pixmap for currently-loaded image */
 xzgv_image *theimage=NULL;
@@ -2514,77 +2515,92 @@
  */
 void find_xvpic_cols(void)
 {
-GdkColor col;
-int r,g,b;
-int n;
-
-for(n=0,r=0;r<8;r++)
-  for(g=0;g<8;g++)     /* colours are 3:3:2 */
-    for(b=0;b<4;b++,n++)
-      {
-      col.red=r*0xffff/7; col.green=g*0xffff/7; col.blue=b*0xffff/3;
-      backend_get_closest_colour(&col);
-      xvpic_pal[n]=col.pixel;
-      }
+    int r,g,b;
+    int n;
+
+    for(n=0,r=0;r<8;r++) {
+        for(g=0;g<8;g++) {/* colours are 3:3:2 */
+            for(b=0;b<4;b++,n++) {
+                xvpic_pal[n][0]=r*0xff/7; 
+                xvpic_pal[n][1]=g*0xff/7;
+                xvpic_pal[n][2]=b*0xff/3;
+            }
+        }
+    }
 }
 
 
 GdkPixmap *xvpic2pixmap(unsigned char *xvpic,int w,int h,GdkPixmap **smallp)
 {
 GdkPixmap *pixmap,*small_pixmap;
-GdkImage *image;
+guint8 *buffer;
 unsigned char *ptr=xvpic;
 int x,y;
 int small_w,small_h;
 
 if(w==0 || h==0) return(NULL);
 
-/* we allocate pixmap and image, draw into image, copy to pixmap,
- * and ditch the image.
- */
-
-if((image=gdk_image_new(GDK_IMAGE_FASTEST,backend_get_visual(),w,h))==NULL)
-  return(NULL);
-
-if((pixmap=gdk_pixmap_new(mainwin->window,w,h,
-                          gdk_visual_get_best_depth()))==NULL)
-  {
-  gdk_image_destroy(image);
-  return(NULL);
-  }
 
-for(y=0;y<h;y++)
-  for(x=0;x<w;x++)
-    gdk_image_put_pixel(image,x,y,xvpic_pal[*ptr++]);
-
-gdk_draw_image(pixmap,clist->style->white_gc,image,0,0,0,0,w,h);
-gdk_flush();
+if (NULL == (pixmap=gdk_pixmap_new(mainwin->window,w,h, -1))) { 
+    return(NULL);
+}
 
-/* reuse image to draw scaled-down version for thin rows */
 small_w=w/ROW_HEIGHT_DIV;
 small_h=h/ROW_HEIGHT_DIV;
 if(small_w==0) small_w=1;
 if(small_h==0) small_h=1;
 
-if((small_pixmap=gdk_pixmap_new(mainwin->window,small_w,small_h,
-                                gdk_visual_get_best_depth()))==NULL)
-  {
-  gdk_pixmap_unref(pixmap);
-  gdk_image_destroy(image);
-  return(NULL);
+if((small_pixmap=gdk_pixmap_new(mainwin->window,small_w,small_h,-1))==NULL)
+{
+    gdk_pixmap_unref(pixmap);
+    return(NULL);
+}
+
+buffer = malloc (w * h * sizeof (guint8) * 3);
+
+if (NULL == buffer) {
+    /* malloc failed */
+    gdk_pixmap_unref(pixmap);
+    gdk_pixmap_unref(small_pixmap);
+    return NULL;
+}
+
+
+for(y=0;y<h;y++) {
+  for(x=0;x<w;x++) {
+      buffer[3*(y*w + x)+0] = xvpic_pal[*ptr][0]; /* red */
+      buffer[3*(y*w + x)+1] = xvpic_pal[*ptr][1]; /* green */
+      buffer[3*(y*w + x)+2] = xvpic_pal[*ptr][2]; /* blue */
+      ptr++;
   }
+}
+
+gdk_draw_rgb_image(pixmap,clist->style->white_gc,0,0,w,h,
+        GDK_RGB_DITHER_NORMAL,
+        (guchar*)buffer, w * 3);
+gdk_flush();
+
+/* reuse image to draw scaled-down version for thin rows */
 
-for(y=0;y<small_h;y++)
-  for(x=0;x<small_w;x++)
-    gdk_image_put_pixel(image,x,y,
-                        xvpic_pal[xvpic[(y*w+x)*ROW_HEIGHT_DIV]]);
 
-gdk_draw_image(small_pixmap,clist->style->white_gc,image,
-               0,0,0,0,small_w,small_h);
+for(y=0;y<small_h;y++) {
+  for(x=0;x<small_w;x++) {
+      buffer[3*(y*w + x)+0] = xvpic_pal[xvpic[(y*w+x)*ROW_HEIGHT_DIV]][0];
+      buffer[3*(y*w + x)+1] = xvpic_pal[xvpic[(y*w+x)*ROW_HEIGHT_DIV]][1];
+      buffer[3*(y*w + x)+2] = xvpic_pal[xvpic[(y*w+x)*ROW_HEIGHT_DIV]][2];
+  }
+}
 
-gdk_image_destroy(image);
+gdk_draw_rgb_image(small_pixmap,clist->style->white_gc,0,0,small_w, small_h,
+        GDK_RGB_DITHER_NORMAL,
+        (guchar*)buffer, small_w * 3);
 
 *smallp=small_pixmap;
+
+if (NULL != buffer) {
+    free (buffer);
+}
+
 return(pixmap);
 }
 
@@ -3649,7 +3665,11 @@
   };
 
 
+gtk_widget_push_visual(gdk_rgb_get_visual());
+gtk_widget_push_colormap(gdk_rgb_get_cmap());
 mainwin=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+gtk_widget_pop_visual();
+gtk_widget_pop_colormap();
 GTK_WIDGET_UNSET_FLAGS(mainwin,GTK_CAN_FOCUS);
 gtk_signal_connect(GTK_OBJECT(mainwin),"destroy",
                    GTK_SIGNAL_FUNC(cb_quit),NULL);

Reply via email to