Tuesday, March 10, 2009

A gift to the competition

For once, I didn't spend my weekends hacking time on patches for F-Spot. Instead, in my journey addressing an old and vocal request, I ended up writing xcf files support for eog, gthumb, gqview, F-Spot obviously and maybe some more.

The code for this is a GdkPixbuf loader, based on this specification (moved there since) and some xcf hexdumps, meaning it's suitable to be released under the LGPL for gdk-pixbuf inclusion. (Googling around, I found some mail archives stating that the GPL(The Gimp)/LGPL (gdk-pixbuf) issue was preventing the inclusion of a loader based on The Gimp's code in gdk).

Features:
  • read xcf files up to v002,
  • compressed and rle-encoded,
  • grayscale and rgb color modes,
  • supports all kinds of layer blending,
  • supports layer masks
TODO:
  • .xcf.gz and .xcf.bz2 support (for jimmac),
  • indexed mode


Clone this piece of awesomeness from git://gitorious.org/xcf-pixbuf-loader/mainline.git and report bugs by e-mail. Build it, copy the .so next to the others loaders on your system and run gdk-pixbuf-query-loaders[-64].

(Get the sample file I used for those screenshots from there)

22 comments:

Wouter said...

What a coincidence: only yesterday I was annoyed by the fact nautilus could show me XCF thumbnails, but eog couldn't. And today I see this blog post. Seriously cool.

Wouter said...

I tried it, and it seems to work okay for basic files. Great, many thanks for your work!

However, I have a (quite big) file here that doesn't show up correctly, though. Please let me know if you want me to send you that file, so that you can investigate the issue. If so, mail me at wbolster, gnome, org — I won't be reading new reactions to this blog post.

Tobi said...

That is very cool!
This was on my wish-list for a very long time, thank you for the work.

OpenRaster said...

XCF is still a rubbish format for document exchange - PSD is unfortunately still the defacto standard - but thank you for making the whole process a little less unpleasant.

Stephane said...

@Wouter: fixed

@OpenRaster: I'm aware of some plans to replace the xcf format. But I'm not really expecting anything in the coming 2 years. For the time being, this small loader could help loading your own (Gimp) files in a picture management application.

Bart said...

This is a very nice addition to the PSD pixbuf loader (http://code.google.com/p/gdk-pixbuf-psd/). Now i can view files from the indutry and open standrd of imageing :) Great work!!!

Dave Neary said...

Great stuff Stephane!

This reminds me of the time a few years back when there was a bit of a ruckus over the XCF format and Henning wrote the spec: http://blogs.gnome.org/bolsh/2006/06/19/the-gimps-xcf-file-format/ and http://blogs.gnome.org/bolsh/2006/07/12/xcf-update/ has the story.

From the first blog entry, I said: "For the record, I disagree (and have always done so) with the policy of discouraging other applications from using XCF. When something better comes along, we can abstract file load & save to a library, and everyone can use it. Until then, if someone wants to write a libxcf, why not? I’m all for interoperability where practical." It's a pity that didn't get done, but I'm really happy that you took on the job.

Dave.

Bart said...

@Stephane
How to built a binary? I'm using Ubuntu 8.04.
I tried a simple "make" and getting the message a no targets message. The ./autogen.sh ends with:

configure.ac:8: error: possibly undefined macro: AC_PROG_LIBTOOL

and

configure: error: cannot find install-sh or install.sh

Please can you help me.
Thanks.

Stephane said...

@Dave: Thanks for your support :) I kind of agree with The Gimp devs when they say that xcf is not the greatest interchange format, and would be happy if they switch to anything gegl/xml/openraster/whatever based. But in the meantime, The Gimp produces images that needs to be viewable by _image_ viewers.

@Bart: you're probably missing some pieces to build it. Make sure you get recent autoconf and automake

Andreas said...

Great work! But unfortunately make fails for me:

/bin/bash ./libtool --mode=compile gcc -DPACKAGE_NAME=\"io-xcf\" -DPACKAGE_TARNAME=\"io-xcf\" -DPACKAGE_VERSION=\"0.0.1\" -DPACKAGE_STRING=\"io-xcf\ 0.0.1\" -DPACKAGE_BUGREPORT=\"stephane@delcroix.org\" -DPACKAGE=\"\" -DVERSION=\"\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DHAVE_LIBBZ2=1 -I. -I. -g -c io-xcf.c
libtool: compile: gcc -DPACKAGE_NAME=\"io-xcf\" -DPACKAGE_TARNAME=\"io-xcf\" -DPACKAGE_VERSION=\"0.0.1\" "-DPACKAGE_STRING=\"io-xcf 0.0.1\"" -DPACKAGE_BUGREPORT=\"stephane@delcroix.org\" -DPACKAGE=\"\" -DVERSION=\"\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DHAVE_LIBBZ2=1 -I. -I. -g -Wp,-MD,.deps/io-xcf.pp -c io-xcf.c -fPIC -DPIC -o .libs/io-xcf.o
io-xcf.c:41:21: error: gmodule.h: No such file or directory
io-xcf.c:42:35: error: gdk-pixbuf/gdk-pixbuf.h: No such file or directory
io-xcf.c:43:38: error: gdk-pixbuf/gdk-pixbuf-io.h: No such file or directory
io-xcf.c:117: Fehler: expected specifier-qualifier-list before »GdkPixbufModuleSizeFunc«
io-xcf.c:130: Fehler: expected specifier-qualifier-list before »guint32«
io-xcf.c:139: Fehler: expected specifier-qualifier-list before »guint32«
io-xcf.c:153: Fehler: expected declaration specifiers or »...« before »gchar«
io-xcf.c: In Funktion »rle_decode«:
io-xcf.c:165: Fehler: »guchar« nicht deklariert (erste Benutzung in dieser Funktion)
io-xcf.c:165: Fehler: (Jeder nicht deklarierte Bezeichner wird nur einmal aufgeführt
io-xcf.c:165: Fehler: für jede Funktion in der er auftritt.)
io-xcf.c:165: Fehler: expected »;« before »opcode«
io-xcf.c:166: Fehler: expected »;« before »buffer«
io-xcf.c:167: Fehler: expected »;« before »ch«
io-xcf.c:174: Fehler: »opcode« nicht deklariert (erste Benutzung in dieser Funktion)
io-xcf.c:176: Fehler: »buffer« nicht deklariert (erste Benutzung in dieser Funktion)
io-xcf.c:179: Fehler: »ch« nicht deklariert (erste Benutzung in dieser Funktion)
io-xcf.c:204: Fehler: »ptr« nicht deklariert (erste Benutzung in dieser Funktion)
io-xcf.c: Auf höchster Ebene:
io-xcf.c:208: Fehler: expected »)« before »*« token
io-xcf.c:238: Fehler: expected »)« before »*« token
io-xcf.c:246: Fehler: expected declaration specifiers or »...« before »gchar«
io-xcf.c:246: Fehler: expected declaration specifiers or »...« before »guchar«
io-xcf.c: In Funktion »apply_mask«:
io-xcf.c:251: Fehler: »guint32« nicht deklariert (erste Benutzung in dieser Funktion)
io-xcf.c:251: Fehler: expected »;« before »tptr«
io-xcf.c:252: Fehler: »tptr« nicht deklariert (erste Benutzung in dieser Funktion)
io-xcf.c:256: Fehler: »gchar« nicht deklariert (erste Benutzung in dieser Funktion)
io-xcf.c:256: Fehler: expected »;« before »pixels«
io-xcf.c:257: Fehler: »compression« nicht deklariert (erste Benutzung in dieser Funktion)
io-xcf.c:258: Fehler: »pixels« nicht deklariert (erste Benutzung in dieser Funktion)
io-xcf.c:258: Fehler: zu viele Argumente für Funktion »rle_decode«
io-xcf.c:264: Fehler: »ptr« nicht deklariert (erste Benutzung in dieser Funktion)
io-xcf.c: Auf höchster Ebene:
io-xcf.c:272: Fehler: expected »)« before »*« token
io-xcf.c:298: Fehler: expected »)« before »*« token
io-xcf.c:306: Fehler: expected »)« before »*« token
io-xcf.c:309: Fehler: expected »)« before »*« token
io-xcf.c:317: Fehler: expected »)« before »*« token
io-xcf.c:325: Fehler: expected »)« before »*« token
io-xcf.c:335: Fehler: expected »)« before »*« token
io-xcf.c:343: Fehler: expected »)« before »*« token
io-xcf.c:353: Fehler: expected »)« before »*« token
io-xcf.c:361: Fehler: expected »)« before »*« token
io-xcf.c:369: Fehler: expected »)« before »*« token
io-xcf.c:377: Fehler: expected »)« before »*« token
io-xcf.c:385: Fehler: expected »)« before »*« token
io-xcf.c:393: Fehler: expected »)« before »*« token
io-xcf.c:401: Fehler: expected »)« before »*« token
io-xcf.c:409: Fehler: expected »)« before »*« token
io-xcf.c:417: Fehler: expected »)« before »*« token
io-xcf.c:427: Fehler: expected »)« before »*« token
io-xcf.c:454: Fehler: expected »)« before »*« token
io-xcf.c:482: Fehler: expected »)« before »*« token
io-xcf.c:510: Fehler: expected »)« before »*« token
io-xcf.c:527: Fehler: expected »)« before »*« token
io-xcf.c:773: Fehler: expected »=«, »,«, »;«, »asm« or »__attribute__« before »*« token
io-xcf.c:1168: Fehler: expected »=«, »,«, »;«, »asm« or »__attribute__« before »*« token
io-xcf.c:1267: Fehler: expected »=«, »,«, »;«, »asm« or »__attribute__« before »xcf_image_begin_load«
io-xcf.c:1303: Fehler: expected »=«, »,«, »;«, »asm« or »__attribute__« before »xcf_image_stop_load«
io-xcf.c:1327: Fehler: expected »=«, »,«, »;«, »asm« or »__attribute__« before »xcf_image_load_increment«
io-xcf.c:1418: Fehler: expected »=«, »,«, »;«, »asm« or »__attribute__« before »void«
io-xcf.c:1426: Fehler: expected »=«, »,«, »;«, »asm« or »__attribute__« before »void«
make: *** [io-xcf.lo] Fehler 1

Stephane said...

@Andreas: I added a check for gmodule in configure script, but your issue is there:
io-xcf.c:41:21: error: gmodule.h: No such file or directory
io-xcf.c:42:35: error: gdk-pixbuf/gdk-pixbuf.h: No such file or directory
io-xcf.c:43:38: error: gdk-pixbuf/gdk-pixbuf-io.h: No such file or directory

Bart said...

Hello Stephane,
i get it compiled yet, thanks for your help! But where to copy the binaries on Ubuntu 8.04? I tried to copy it to "/usr/lib/gtk-2.0/2.10.0/loaders" (like the PSD pixbuf loader) but without luck. It didn't work :(
Do you have any idea?

Stephane said...

@Bart: run gdk-pixbuf-query-loaders ...

Bart said...

Hello Stephan,

thanks again but i'm getting this error:

g_module_open() failed for /usr/lib/gtk-2.0/2.10.0/loaders/libpixbufloader-xcf.so: /usr/lib/gtk-2.0/2.10.0/loaders/libpixbufloader-xcf.so: undefined symbol: g_set_error_literal
g_module_open() failed for /usr/lib/gtk-2.0/2.10.0/loaders/libioxcf.so: /usr/lib/gtk-2.0/2.10.0/loaders/libioxcf.so: undefined symbol: g_set_error_literal

:(

Jon Senior said...

Just stumbled across this. I've build and installed it. gdk-pixbuf-query-loaders-32 (Fedora 10) shows it as present:

"/usr/lib/gtk-2.0/2.10.0/loaders/libioxcf.so"
"xcf" 0 "gtk20" "The XCF (The Gimp) image format" "LGPL"
"image/x-xcf" "image/x-compressed-xcf" ""
"xcf" "xcf.bz2" ""
"gimp xcf" "" 100
"BZh" "" 80

But it doesn't seem to change anything. Geeqie (and GQView), and EOG all display a broken thumbnail or throw errors.

Any ideas?

Stephane said...

@Jon: drop me a mail with the error log

Jon Senior said...

@Stephane: Resolved: I needed to run update-gdk-pixbuf-loaders. It now works perfectly...

Thanks. You are a genius!

maniac8k said...

This did not work in ubuntu 7.10 until I ran this command:

sudo gdk-pixbuf-query-loaders > /etc/gtk-2.0/gdk-pixbuf.loaders

Now it seems to be working. I'm not sure if newer version of Ubuntu need this or not.

Thanks Stephane!!!!!!

Stephane said...

guys, read the blog post up to the end, so you'll know you have to run gdk-pixbuf-loader[-64]

maniac8k said...

@Stephane

The blog post has "gdk-pixbuf-query-loaders[-64]" instead of "update-gdk-pixbuf-loaders". I tried both of these commands and neither of them worked. After some searching, I found the command I posted and it worked.

It looks like the update-gdk-pixbuf-loaders script should do the exact same thing as the command I posted, but it doesn't. Must be a bug in Ubuntu 7.10 or a problem with my environment.

I think the blog post should have the update command instead of the query command but I could be wrong.

Thanks again. I like being able to see my gimp images in gnome apps.

richard18925 said...

Thanks Stephane! Others might find it useful to see exactly what I did to get it working on Ubuntu 9.04:

> sudo apt-get install git-core autoconf libtool
> sudo apt-get install libgtk2.0-dev libbz2-dev
> cd ~
> git clone git://gitorious.org/xcf-pixbuf-loader/mainline.git pixbuf
> cd pixbuf
> ./autogen.sh
> make
> cd .libs
> sudo cp libioxcf.so /usr/lib/gtk-2.0/2.10.0/loaders
> sudo gdk-pixbuf-query-loaders libioxcf.so
> sudo gdk-pixbuf-query-loaders > /etc/gtk-2.0/gdk-pixbuf.loaders

The only problem I had was that grayscale xcf images were somewhat garbled, but I'll take that over what I had before (which was nothing). :)

Rolf said...

Thank you!

But this solves only half of my problem How do I get the xcf file into the database of f-spot?

Post a Comment