Abiword Image support

Hubert Figuière <hfiguiere@teaser.fr>

Status: DRAFT

Abstract

This document will describe how Abiword should handle images internally and how image import should be handled.

It will be divided in three parts:

file format internal support

file format conversion

rendering

File format internal support

Currently, Abiword supports PNG rendering internally. Rendering a PNG is done using the libpng that is provided is a peer library and linked against in the case it is not in the system. (Currently GNOME build has it dynamic).

We should also support SVG vector rendering, JPEG and raw bitmap. The latest will not be persistent and will always be stored as PNG on disk.

While SVG support seems obvious, JPEG is a little bit less since PNG is also a bitmap image format. The usefulness of JPEG comes from the fact that it compress well and that it is lossy. So the process of converting to PNG to be able to export it as JPEG later will generate information loss. This is not what we want. And a full color JPEG (say a 1024x768 screenshot) will eat up much less space than its PNG counterpart.

For raw bitmap, this is just a matter of avoiding multiple compression / decompression processes.

We will see later which format should be used in which case.

File format conversion

File format conversion is done in 3 cases:

when you import an image

when you preview an image during step 1

when you import a document that contain images

Step 1 and 2 are related and will be considered as one. Step 2 can be done as platform code (for example MacOS has support of image preview in open file dialogs with QuickTime that we will use anyway). In these case step 2 is void.

Anyway, whatever the cases, you have to convert the image to something that Abiword understand, ie raw bitmap, PNG, JPEG and SVG.

Image importers

Importing an image is done bye the importers, that are implement as a class. Base class is IE_ImpGraphic. Currently, only PNG and BMP are supported. Both take a buffer contain the file on entry and return a buffer containing a PNG on output. The PNG importer is simple as it is only a buffer copy.

While the PNG importer seems to be consistent I find that BMP import process is quite strange: decode a BMP then convert and compress it to PNG. If we want to display it again we have to decompress it again. That is inconsistent. I have written a JPEG importer that works almost the same way.

So the current design is weak on this point, even if it works.

So what should be done for bitmap format ?

Given the fact that we support PNG, JPEG and raw bitmap, and that raw bitmap remains the most easy format to display, everything that is not PNG or JPEG should be output as raw bitmap, that will be converted to PNG for persistence, if needed. Here is a summary:

Input format output format

PNG PNG

JPEG JPEG

other bitmap than the above raw bitmap

Image comversion can be implemented in several ways. As XP code using well know libraries. ImageMagick, libtiff and lot of others come to mind. libpng is currenly used by Abiword because of its internal PNG support. Platform support can also provide translation like QuickTime (on MacOS), Media Kit Translators (on BeOS), and al.

Vector formats

Vector formats are most problematic. Unlike bitmap images, that can be represented as a raw bitmap, there is no universal vector format for vector that can be drawn on any platform. While SVG is versatile and good for storage, I doubt that it does not bring overhead if used alone. So we have to come up with a good solution, mainly if the input format is native (ie the metafile format like WMF on windows or PICT on Macintosh). So what shall we do ? The best solution IMHO is to provide in memory a dual representation so that if the file is a metafile we have the SVG version along with the metafile version. For example, on Macintosh, you wish to import a PICT file. The importer will convert the PICT file to SVG and pass along the SVG a PICT representation of the file for immediate display. When stored, only the SVG, whose generation is supposed to not be lossy, is kept.

Input format output format

SVG SVG

Native Platform Metafile SVG + Metafile

other vector than the above SVG

Rendering

Rendering is the visible part of the stuff. This is also the biggest bottleneck of all of this.

Rendering should be performed by the platform code which is probably the most efficient (and which does not bloat Abiword). Rendering take 4 kind of streams on input: those that we support internally. The renderer is divided in 2 classes: the GR_Image and GR_Graphics. The first one encapsulate the picture will the second one performs graphic operations. It is up to the GR_Image class to cache the native display format to avoid conversion each time it as to actually display the image. Renderer also has to perform image scaling. The way it should perform this and the code is up to the implementor.

Example of implementation using native renderer is the gdk-pixbuf used by the current CVS version of Abiword for GNOME. It currently only receive a PNG, but it is likely that once we have JPEG and raw bitmap it will come for free. The cache is inside gdk-pixbuf.

For vector drawing it is almost the same with a little exception: it is more complex. If a metafile is passed along, then use it. If only SVG is received, then render SVG to the metafile and cache for later use. As an example, Microsoft Word 98 on MacOS that stores vector images, convert on the fly WMF picture to PICT (but insist on storing WMF). There reverse is true with Word 97 on Windows (but this time store it in WMF if I’m not wrong). Vector image is not a simply problem and has no simple solution.

What need to be changed ?

Image importer API need to be changed to no longer use an UT_ByteBuf buffer as output but a GR_Image that is created by the caller. This will allow passing structured data like the SVG and its metafile representation.