Reading .png files to pixmaps




I've been playing with using imlib to load .png files to a GdkPixmap. It
seems, well, slow and rather bloated - I have no need for saving files,
or for filetypes other than png, or scaling, etc. Also, I'd rather users
didn't have to have numerous esoteric libraries installed.

Would anyone have any code to load .png files using only libpng calls?
Re-inventing the wheel isn't fun.


Alistair Cunningham.




As an aside: Here's what I've been working with. It doesn't work - it
won't handle assigning colours correctly. It's horribly inefficient
anyway, so I'd rather bin it. However, it should give an idea what I'm
after:



#include "tc.h"
extern widget *mainwin;

GdkPixmap *create_gdkpixmap_from_png(char *path, GdkWindow *window, int *w, int *h, gint depth) {
  png_structp png_ptr;
  png_infop info_ptr;
  unsigned char **lines,*ptr2,r,g,b,a;
  int i,x,y,bit_depth,color_type,interlace_type;
  png_uint_32 *ww,*hh;
  FILE *f;
  GdkPixmap *map;
  GdkGC *gc;
  GdkColor colour;

  f = fopen(path,"rb");
  if (!f) {
    return NULL;
  }

  png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
  if (!png_ptr) return NULL;
  info_ptr=png_create_info_struct(png_ptr);
  if (!info_ptr)
    {
      png_destroy_read_struct(&png_ptr,NULL,NULL);
      return NULL;
    }
  if (setjmp(png_ptr->jmpbuf))
    {
      png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
      return NULL;
    }
  if (info_ptr->color_type==PNG_COLOR_TYPE_RGB_ALPHA)
    {
      png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
      return NULL;
    }
  png_init_io(png_ptr,f);

  png_read_info(png_ptr,info_ptr);
  ww=(png_uint_32 *)w;hh=(png_uint_32 *)h;
  png_get_IHDR(png_ptr,info_ptr,ww,hh,&bit_depth,&color_type,&interlace_type,
               NULL, NULL);

  if (color_type==PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr);
  png_set_strip_16(png_ptr);
  png_set_packing(png_ptr);
  if (png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS))
    png_set_expand(png_ptr);
  png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
  *w=info_ptr->width;
  *h=info_ptr->height;

  lines = (unsigned char **)malloc( *h * sizeof( unsigned char *) );
  for (i=0;i<*h;i++) lines[i] = malloc(*w * ( sizeof( unsigned char )*4 ) );
  png_read_image(png_ptr,lines);
  png_destroy_read_struct(&png_ptr,&info_ptr,NULL);

  map = gdk_pixmap_new( window, *w, *h, depth );
  if (!map) return NULL;
  gc = gdk_gc_new( window );

  if (color_type==PNG_COLOR_TYPE_GRAY)
    {
      fprintf(stderr,"\n\n\nBlack and white\n\n\n\n");
      for(y=0;y<*h;y++)
        {
          ptr2=lines[y];
          for(x=0;x<*w;x++)
            {
              r=*ptr2++;
              colour.red = colour.green = colour.blue = r * (65535/255);
              colour.pixel = (gulong)(r*65536 + r*256 + r);
              gdk_color_alloc( gtk_widget_get_colormap(mainwin), &colour );
              gdk_gc_set_foreground( gc, &colour );
              gdk_draw_point( map, gc, x, y );
            }
          }
    }
   else
     {

	/* This is the horribly broken bit. The gdk_color_alloc below
works, but takes about 30 minutes to load a 256x256 bitmap on a Pentium
180. */

gdk_colors_alloc( gtk_widget_get_colormap(mainwin), FALSE, (gulong *)info_ptr->palette, info_ptr->num_palette, (gulong *)lines, *w**h );
       for(y=0;y<*h;y++)
         {
           printf("Row %d\n",y);
            ptr2=lines[y];
           for(x=0;x<*w;x++)
               {
                 r=*ptr2++;g=*ptr2++;b=*ptr2++;a=*ptr2++;
                 colour.red = r * 65535/255;
                 colour.green = g * 65535/255;
                 colour.blue = b * 65535/255;
                 colour.pixel = (gulong)(r*65536 + g*256 + b);
                 // gdk_color_alloc( gtk_widget_get_colormap(mainwin),&colour );
                 gdk_gc_set_foreground( gc, &colour );
                 gdk_draw_point( map, gc, x, y );
               }
         }
     }
  for (i=0;i<*h;i++) free(lines[i]);
  free(lines);
  gdk_gc_destroy( gc );

  return map;
}



--------------------------------------------------------------------------
 Alistair Cunningham   Selwyn College, Cambridge   Email: ac212@cam.ac.uk



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