SGI: Development

gimp image format plugin, help :-P

this is probably trivial but for some reason i just can't see the right way. i tried a couple of ways but no luck :P

i want to make a gimp plugin that can read (writing would be the next stage) wavefront images. rla and rlb which are almost the same. of course i had a closer look at the other gimp plugins for file formats but different formats are, well, different so i didn't see enough similarities to apply it to this case.
i have a sample here from wavefront (full demo attached):

Code: Select all

for (scan = rlb_head.window.bottom; scan <= rlb_head.window.top; scan++) {
/* check for black regions outside active window */
if ((scan < rlb_head.active_window.bottom) || (scan > rlb_head.active_window.top)) {

/* write out a blank scanline */
fwrite(blank, 4, width, out);
} else {
/* seek to file location */
if (fseek(fp, (long) offset[scan - bottom], 0)) {
printf("rlb file incomplete!\n");
exit(-7);
}
/* read red scanline */
fread(&len, sizeof(short), 1, fp);
fread(buf, sizeof(U_CHAR), (int) len, fp);
decode(buf, red, (int) len);

/* read green scanline */
fread(&len, sizeof(short), 1, fp);
fread(buf, sizeof(U_CHAR), (int) len, fp);
decode(buf, green, (int) len);

/* read blue scanline */
fread(&len, sizeof(short), 1, fp);
fread(buf, sizeof(U_CHAR), (int) len, fp);
decode(buf, blue, (int) len);

/* read matte scanline */
fread(&len, sizeof(short), 1, fp);
fread(buf, sizeof(U_CHAR), (int) len, fp);
decode(buf, matte, (int) len);

/* write out RGBM for each pixel */
for (x = rlb_head.window.left; x <= rlb_head.window.right; x++) {

if ((x < rlb_head.active_window.left) || (x > rlb_head.active_window.right)) {
fwrite(blank, 4, 1, out);
} else {
fwrite(&red[x - left], 1, 1, out);
fwrite(&green[x - left], 1, 1, out);
fwrite(&blue[x - left], 1, 1, out);
fwrite(&matte[x - left], 1, 1, out);
}
}
}
}

all fine and cozy. i do of course not want to write to a dump file but hand it over to gimp. the gimp stuff is as follows:

Code: Select all

image_ID = gimp_image_new(width, height, imgtype);
gimp_image_set_filename(image_ID, filename);
layer_ID = gimp_layer_new(image_ID, _("Background"), width, height, gdtype, 100, GIMP_NORMAL_MODE);
gimp_image_add_layer(image_ID, layer_ID, 0);
drawable = gimp_drawable_get(layer_ID);
gimp_pixel_rgn_init(&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE);
tile_height = gimp_tile_height();

...

gimp_pixel_rgn_set_rect(&pixel_rgn, data, 0, 0, width, height);

the important part here is the last one which actually puts the data into gimp. data is guchar i.e. glib's unsigned char. as a pointer.

the thing that made me struggle now is to change the fwrites into something else that i can use for writing to some dummy variable i allocated in advance or whatever else does the job.
also i wanna emphasize that this is not a commercial project in any way. in fact i'd like to share the finished product here in case i get it done somehow :P

any ideas or help in whichever way would be welcome :-)
r-a-c.de
Have you tried using gimp_pixel_rgn_init() to write the Wavefront image data directly into a GIMP image region, and then you can save that as a new image?
Project:
Temporarily lost at sea...
Plan:
World domination! Or something...

:Tezro: :Octane2:
rgn_init() doesn't take any actual image data afaik but just, well, inits the region :P
but yeah the idea of using some of the region_set functions inside the decode function could be an option. however the decode function is meant to read one full row per color (and alpha) only so i'd need a new one or change the current one because gimp wants rgba, rgba, rgba ... per row.

my general idea was to replace the fwrites at the bottom so that i store whatever the colors like red[x - left] have in a buffer. once the row is done i give that to gimp, update the progress bar and go for the next row.
the rather basic problem i have there is making a "copy" of whatever red[x - left] and the others have to a buffer. i tried a simple = and bcopy and a few others but nothing worked.
r-a-c.de
I'm assuming the matte is alpha channel? wtf else would it be really used for? Do all your gimp image init before hand, and then maybe something like this?

Code: Select all

/* write out RGBM for each pixel */
guchar rowdata[width * 4];
for (x = rlb_head.window.left; x <= rlb_head.window.right; x++) {

if ((x < rlb_head.active_window.left) || (x > rlb_head.active_window.right)) {
fwrite(blank, 4, 1, out);
} else {
guint pos = 4 * (x - left);
rowdata[pos] = &red[x - left];
rowdata[pos+1] = &green[x - left];
rowdata[pos+2] = &blue[x - left];
rowdata[pos+3] = &matte[x - left];
}
}

/* write row to GIMP */
gimp_pixel_rgn_set_row(&pixel_rgn, &rowdata, 0, scan, width);
:Fuel: nitro
much thanks for that. unfortunately it doesn't work.

Code: Select all

A value of type "guchar *" cannot be assigned to an entity of type "guchar"


in case you didn't grab the full file, the colors are declared as (guchar *). another example of how they're assigned

Code: Select all

guchar *red, *green, *blue, *matte;
size_t suc = sizeof(guchar);
...
red = (guchar *)malloc(suc * width * 4);
...
green = &red[width];
blue = &green[width];
matte = &blue[width];


pointer-party :P
r-a-c.de
Ahh, ok, then change the lines to be:

Code: Select all

rowdata[pos] = *red[x - left];
rowdata[pos+1] = *green[x - left];
rowdata[pos+2] = *blue[x - left];
rowdata[pos+3] = *matte[x - left];
:Fuel: nitro
sorry, still no dice

Code: Select all

The operand of the indirection operator ("*") must be a pointer
r-a-c.de
i had another look at this and this time i took a closer look at the alias pix plugin hoping to find some clues in there. but instead i discovered something that confusesd me even more :P

the plugin does support writing the alias files with and without rle. the curious part now is that the function for loading files just reads them as they come. no special rle detection or support otherwise but it does work nevertheless :shock:
i can't shake the feeling that i'm missing something fundamental about image files ...

EDIT: i hope no seasoned gfx programmer will read this. feels like it's getting a little embarassing :P
r-a-c.de