lansd@dgp.toronto.edu (Robert Lansdale) (03/19/90)
Several months ago I added Iris 'IMG' file output capabilities to my 3d renderer, but everytime I outputed an image and 'ipaste'd it to the screen, the image was always displayed black. After spending too much time trying to narrow the problem down (including examining the file directly), I gave up and placed it at the bottom of my list of things to eventually fix. Well, here we are several months later, but now I must convert an Iris IMG file created with Alias's Quickpaint program to our native RLE file format. To make a long story short, the converter did its job but the resulting colour image was displayed in grey-scale. To see who was at fault, I converted the 'max5.rgb' image and it displayed just fine. I then tried the 'toalias' converter in 4Dgifts/iristools/imgtools on the Quickpaint output, then used a (known-to-be-working) Alias image display program to paste the Alias pic to the Iris display - same 'greyscale' effect. So, the question is: why does both my renderer and the converter programs have problems with the Image file library? I made sure I recompiled the libraries in 4Dgifts/iristools before I made the toalias program and before I linked libimage.a into my renderer. Also, does the "image->zsize" variable really reflect the depth of the IMG file? From what I recall, most of the IMG related files in 4Dgifts don't bother looking at the image depth. --> Rob Lansdale
paul@manray.sgi.com (Paul Haeberli) (03/20/90)
The reason you had problems converting a file from Alias QuickPaint is that QuickPaint saves its images as colo(u)r index pixels. To use a QuickPaint image with the image processing tools or the image library it is best to convert it into an RGB image. The following script does just that by first saving the current colo(u)r-map, and then mapping the color indexed pixels into rgb space. The programs "savemap" and "mapimg" can be found in /usr/people/4Dgifts/iristools/imgtools if they aren't found in /usr/sbin. This is fromqp: #! /bin/sh if [ $# != 2 ] then echo "usage: fromqp in.qp out.rgb" exit 1 fi savemap /tmp/qp.map mapimg $1 $2 /tmp/qp.map rm /tmp/qp.map To write out an rgb IRIS image from a renderer use a sequence of image library calls like this: #include "gl/image.h" /* * writeiris - * This function takes three arrays of unsigned characters and * writes these as pixel data to an IRIS image file that can be ipasted * to the screen. * */ writeiris(rbuf,gbuf,bbuf,xsize,ysize) unsigned char *rbuf, *gbuf, *bbuf; int xsize, ysize; { IMAGE *oimage; unsigned short *rs, *gs, *bs; int x, y; rs = (unsigned short *)malloc(xsize*sizeof(unsigned short)); gs = (unsigned short *)malloc(xsize*sizeof(unsigned short)); bs = (unsigned short *)malloc(xsize*sizeof(unsigned short)); oimage = iopen("render.rgb","w",RLE(1),3,xsize,ysize,3); for(y=0; y<ysize; y++) { for(x=0; x<xsize; x++) { rs[x] = *rbuf++; gs[x] = *gbuf++; bs[x] = *bbuf++; } putrow(oimage,rs,y,0); putrow(oimage,gs,y,1); putrow(oimage,bs,y,2); } iclose(oimage); free(rs); free(gs); free(bs); } Please let me know if you still have problems . . . . . paul haeberli paul@sgi.com
pbreslin@dragon.tmc.edu (Paul Breslin) (03/20/90)
>... > Well, here we are several months later, but now I must convert >an Iris IMG file created with Alias's Quickpaint program to our native >RLE file format. ... The Iris image library is capable of storing four "types" of image files. These are (from image.h): CM_NORMAL, CM_DITHERED, CM_SCREEN, CM_COLORMAP. Some of the image tools in 4Dgifts prefer and/or assume CM_NORMAL type, which is the most common type (pixel values are channel intensities). Since QuickPaint operates in colormap mode, it stores images using type CM_SCREEN. Since QuickPaint also allows you to modify the colormap, it saves a secondary file (.M) containing the colormap used to create the image. This .M file is of type CM_COLORMAP. If one of these doesn't exist you usually assume the default NeWS colormap should be used. So, say you wanted to convert a QuickPaint image to RGB format. You should first read in the colormap file. It should be 4 by 256. The X dimension contains the colormap index, R, G, and B. Then to read the image itself, you read in the CM_SCREEN type image whose pixel values represent colormap indices and map them to RGB values using the colormap from above. Here's a program I just created to read in a quickpaint file, convert it to RGB and blast it into a window using lrectwrite. It was created with 4 space tabs and compiled with the command: cc -O qp.c -lgutil -limage -lgl_s -lm -lc_s It's rather sparse on diagnostics. If you turn this into a real tool then please add more of these. It was also whipped together somewhat quickly so I apologize in advance for any errors. I've only tested it on the images in /usr/demos/quickpaint. Also note that the SGI image library has a nasty habit of calling exit. A hack was added to it to trap errors by calling "i_seterror" with an error handling function pointer. I would suggest using this. Locally we've modified the library to be slightly improved in this area. cheers, Paul Breslin Alias Research Inc. -------------------------------------------------------------------- #include <stdio.h> #include <gl.h> #include <device.h> #include <gl/image.h> typedef struct { unsigned char a, b, g, r; } RGBA; static RGBA *ColorMap; static RGBA *Image; static int Xres, Yres; static char ErrorMsg[256]; extern unsigned char red_map[256]; extern unsigned char green_map[256]; extern unsigned char blue_map[256]; static int LoadColorMap(char *filename) { register IMAGE *cmap; register RGBA *rgbp; register int y; register int index; short rowbuf[4]; char cmapname[512]; sprintf(cmapname, "%s.M", filename); if( !(cmap = iopen(cmapname, "r")) ) return 0; if( cmap->xsize != 4 ) { iclose(cmap); return 0; } rgbp = ColorMap = (RGBA *)malloc(cmap->ysize * sizeof(RGBA)); for( y = 0; y < cmap->ysize; y++ ) if( getrow(cmap, rowbuf, y, 0) >= 0 ) { index = rowbuf[0]; rgbp->r = rowbuf[1]; rgbp->g = rowbuf[2]; rgbp->b = rowbuf[3]; ++rgbp; } iclose(cmap); return 1; } static int LoadImage(char *filename) { register Colorindex *scanline; register RGBA *rgbp; register IMAGE *image; register int y; register int x; register int index; register int file_zsize; if( !(image = iopen(filename,"r")) ) return 0; file_zsize = image->zsize; Xres = image->xsize; Yres = image->ysize; if( file_zsize != 1 ) { sprintf(ErrorMsg, "\"%s\" is not a normal QP file", filename); iclose(image); return 0; } scanline = (Colorindex *)malloc(Xres * sizeof(Colorindex)); rgbp = Image = (RGBA *)malloc(Xres * Yres * sizeof(RGBA)); for( y = 0; y < Yres; ++y ) { if( getrow(image, scanline, y, 0) < 0 ) break; for( x = 0; x < Xres; ++x, ++rgbp ) { index = scanline[x]; if( !ColorMap ) { if( index < 256 ) { rgbp->r = red_map[index]; rgbp->g = green_map[index]; rgbp->b = blue_map[index]; } else { rgbp->r = 0; rgbp->g = 0; rgbp->b = 0; } } else *rgbp = ColorMap[index]; } } iclose(image); free((char *)scanline); return y == Yres; } int main(int argc, char **argv) { Device event; short value; long window; if( argc != 2 ) { fprintf(stderr, "Usage: %s <quickpaint_file>\n", argv[0]); return 1; } LoadColorMap(argv[1]); if( LoadImage(argv[1]) ) { prefposition(0, Xres - 1, 0, Yres - 1); noborder(); foreground(); if( (window = winopen("Hi")) <= 0 ) return 1; RGBmode(); gconfig(); qdevice(WINQUIT); qdevice(WINSHUT); qenter(REDRAW, window); while( event = qread(&value) ) { switch( event ) { case WINQUIT: case WINSHUT: break; case REDRAW: lrectwrite(0, 0, Xres - 1, Yres - 1, Image); continue; default: continue; } break; } } return 0; }