GNOME Bugzilla – Bug 121884
gdk_pixbuf_loader_write gives error on TIFF files
Last modified: 2010-07-10 04:08:34 UTC
I can't make gdk_pixbuf_loader load tiff files. The code is (w/o error checking to simplify): GdkPixbufLoader *pbl=gdk_pixbuf_loader_new(); // tested new_with_type("tiff", NULL) too ! FILE *f=fopen(file, "rb"); if(f) { char buff[512]; gint siz; do { siz=fread(buff, 512, 1, f); gdk_pixbuf_loader_write(pbl, buff, siz, NULL); pb=gdk_pixbuf_loader_get_pixbuf(pbl); } while(siz && !pb); if(pb) { x=gdk_pixbuf_get_width(pb); y=gdk_pixbuf_get_height(pb); c=gdk_pixbuf_get_bits_per_sample(pb)*gdk_pixbuf_get_n_channels(pb); } gdk_pixbuf_loader_close(pbl, NULL); fclose(f); } When trying to load a tiff file, the first write returns "unrecognized image file format", but gdk_pixbuf_new_from_file works ok... Tested even with a buffer large enough to contain the whole file: same error.
gdk-pixbuf can only write jpeg and png, the tiff module doesn't have write support. If anything, the error message could be improved. You would of course be welcome to provide an implementation for tiff save support, but I don't think this is a high priority for us.
Take a look at what you're getting back from fread and then passing to gdk_pixbuf_loader_write. fread returns the number of *elements* read, of the size you give it, so siz == 1 since it read one 512 byte element. loader_write then only looks at one byte. You should also call gdk_pixbuf_loader_close before trying to get the pixbuf. This has nothing to do with saving files, the reporter is trying to load a file using the GdkPixbufLoader interface directly.
I must have been asleep when I wrote that comment...
Nope. It's just a typo in the pasted code (being desperate, I retrieved the last try... when the logic can't help, be illogic and try anything!).. Try RUNNING it. The code (after swapping 512 and 1) works for anything BUT tif files. :-( And according to the docs, get_pixbuf can be called anytime -- if there isn't enough data it simply returns NULL. The new (complete - just add gnome_init(...) just before pbl= ) snippet is : #define FILNAM "test.tif" GdkPixbufLoader *pbl; GdkPixbuf *pb; FILE *f; pbl=gdk_pixbuf_loader_new(); f=fopen(FILNAM, "rb"); if(f) { char buff[512]; gint siz, x, y, c; GError *e=NULL; do { siz=fread(buff, 1, 512, f); printf("siz=%d\n", siz); gdk_pixbuf_loader_write(pbl, buff, siz, &e); pb=gdk_pixbuf_loader_get_pixbuf(pbl); } while(!e && siz && !pb); if(e) { printf("ERROR: %s\n", e->message); } else if(!pb) { printf("Creating new from file"); pb=gdk_pixbuf_new_from_file(FILNAM, NULL); } if(pb) { x=gdk_pixbuf_get_width(pb); y=gdk_pixbuf_get_height(pb); c=gdk_pixbuf_get_bits_per_sample(pb)*gdk_pixbuf_get_n_channels(pb); printf("%dx%dx%d\n", x, y, c); } else { printf("Nope... all failed"); } gdk_pixbuf_loader_close(pbl, NULL); fclose(f); }
It helps to have a completely compilable test case, with a main() function and everything. From the gdk-pixbuf docs on gdk_pixbuf_loader_get_pixbuf: Queries the GdkPixbuf that a pixbuf loader is currently creating. In general it only makes sense to call this function after the "area_prepared" signal has been emitted by the loader; this means that enough data has been read to know the size of the image that will be allocated. "area_prepared" isn't emitted for tiff loading until after close is called. The Images sample in gtk-demo shows the right way of handling incremental loader logic. If you believe the the tiff loader should be able to get the info to emit the area_prepared signal earlier, file a separate bug on that. I'm not sure that can be done in all cases, so some research into libtiff is in order.
I was just about to quote the same thing. Incremental loading for tiff is just a fake, because libtiff is a pain to work with.