home contents changes options help

by Robin Rowe 8/17/04

img_img is a new core architecture for CinePaint to replace the legacy GIMP tiled architecture. It will support not only CinePaint but other applications that wish to manipulate raw RGB buffers in memory.

img_img is a new architecture and still being created. The architecture is based upon a dll that accesses the img_img process and shared memory.

Client C code will look approximately like this:

    enum {width=640,height=480,depth=8};
    unsigned image_id=imgCreateImage(width,height,depth,"RGB");// calls to img_img
    // note, if img_img not already a running process it is launched implicitly
    byte* rgb=imgGetImage(image_id);// rgb points into shared memory of img_img
    memset(rgb,0,3*width*height); // set image all black, for example

   ... do whatever else you want to do with a raw rgb buffer ...

    bool ok=imgWriteImage(image_num,"test1.jpg");// save image as JPEG, for example
    imgClose(image_id);// Memory released, image_id and rgb no longer valid
    image_id=imgOpenImage("test1.jpg");// image_id here is different from before
    imgInfo info; /* struct imgInfo { unsigned width; unsigned height; ...}; */
    imgGetInfo(image_id,&info); // get some image stats

Omitted here, error checking code should check for 0.

Multiple layers can be created:

    unsigned layer2_id=imgCreateLayer(image_id,width,height,depth,"RGB");

Numbers for layer_id are assigned sequentially in order of creation, temporary but unique as long as img_img is running. The image_id is also the layer_id of the first layer of the image.

This is the first level protocol for img_img, just rgb layers in shared memory and file io. In the second generation protocol an application will be able to operate img_img filters:

    bool ok=imgCommand(image_id,"blur","image");

Note that img_img never uses variargs. Where parameters have unknown type or quantity they are passed as a string:

   bool ok=imgCommand(image_id,"blur","channel|1");

Multiple parameters can be in the same string, separated by the pipe character.

The first generation will be lock-less, have no callbacks. There will be async stuff later. There will also be a way to poll for % completed so client apps can update a progress bar:

    float progress=imgGetProgress(image_id);// 100.0% is default, 0.0 is error

An image being processed would report progress greater than 0.0. Zero means the processing failed. An image doing nothing reports 100.0%.

Shooting for September availability for first version of this code.


Robin's update -- Tue, 21 Sep 2004 11:17:25 -0700 reply
Have built the img_img command-line utility (sort of like ImageMagick convert) and am starting on the img_ppm plug-in. Next will create the img_server to support the external img_img API for Blender.

Robin responds to Emil's questions -- Wed, 22 Sep 2004 09:19:48 -0700 reply
From verse-dev@projects.blender.org list:


Looks cool, although I'm certainly not familiar with the design goals you have in mind here.

A versatile image file io engine so that every app in the world (including CinePaint) doesn't need to know how to read/write a zillion different image file formats. What this will mean for Blender is being able to write RGB renders easily in formats such as Cineon or OpenEXR that are standard in the motion picture industry. Another feature of img_img is it knows how to covert framebuffers to different bit-depths.

1. It looks like it replaces the tile-based architecture from GIMP with straight, sequential, memory buffers.

God, yes. It's a framebuffer.

I guess GIMP uses tiles so that an image can be partially in RAM; is this not a goal for img_img?

No. Tiles were an accomodation to the high cost of RAM in 1995 when they were implemented in GIMP. In 2004 users want entire images in RAM. Tiles create performance problems in typical scenarios and are a pain in the neck for plug-in developers to code for.

2. Is there some rationale for when a call contains the word "Image" and when it does not? Is imgClose() used to destroy e.g. layers too? Can imgInfo() get info on objects other than images? 3. Create() and Close() are not obvious opposites to me, but perhaps it makes more sense in a larger context.

It's only the preliminary spec, to give a feel for what the API will look like. Expect some changes.

Every call is prepended with "img" to make it easy to search on and to prevent name clashes. It's just a convention, instead of using C++ namespaces.

4. Why the decision to avoid varargs and use strings?

Legacy GIMP variargs code has made the present CinePaint extremely hard to maintain. Stack corruption and void pointers are almost impossible to debug.

... -- Tue, 28 Dec 2004 01:39:49 -0800 reply

... -- Sun, 12 Jun 2005 15:51:16 -0700 reply

Looking up plug-ins -- Sun, 12 Jun 2005 15:56:50 -0700 reply
The current public code for img_img requires a client app to know which library it wants to open.

Is there any spec on how plug-ins will be registered?


Using iterators -- Sat, 23 Jul 2005 14:05:11 -0700 reply
Have you considered hiding tiles behind iterators -- as we currently do in Krita (yay! we've got 16 bit/channel images, too!), or in vigra? We find it doesn't degrade performance all that much, given that nothing in Krita is optimized yet, and that it makes plugin development extremely simple.

Boudewijn Rempt (http://koffice.kde.org/krita)