Creating Image Files

dave "who can do? ratmandu!" ratcliffe dave at sgi.com
Fri Oct 5 00:36:09 AEST 1990


In article <4671 at tahoe.unr.edu> dahl at tahoe.unr.edu (Michael Dahl) writes:
>
>I want to produce, from within my application, image files of the format
>produced by snapshot(1).  Can anyone tell me the file format?

hi Michael-

  a boatload o' worms you sail in w/here with but i'll try to give it a go:

so snapshot uses the ubiquitous gl_readscreen (see the post i just sent out
before this one responding to a query about wanting more info on this un-
documented GL call) to go read, scanline by scanline, whatever area of the
screen is specified and, returns RGB triples for each pixel into the three 
red green and blue arrays gl_readscreen gets called with.  unfortunately
the request for information on the format of the equally ubiquitous
"SGI imagelib image" -type files betrays the dangling embarrassment that 
this information has never been adequately documented...

without being able to give you a blow-blow, technically inclusive 
specification of this format, here are some of the most salient points.  
(please know that i am, at this moment engaged in trying to work with 
those in the know, to once and for all create the ultimate document on 
the iris image libraries which *will* contain the details about the
creation and manipulation of "SGI imagelib image" files.  regretably, 
i am unable at this time to tell you when this will be completed.)

    refer to the IMAGE structure in /usr/include/gl/image.h
    this is the meat of what you are asking about.   the IMAGE structure
    *is* the header for every file created by snapshot/icut/scrsave which
    calls gl_readscreen.  

    if you haven't already found it, see /usr/people/4Dgifts/iristools.
    this subtree under the 4Dgifts sample source code user account contains
    all the source you are wondering about (~4Dgifts/iristools/libimage/*
    contains all the source that builds the library /usr/lib/libimage.a,
    ~4Dgifts/iristools/libgutil contains all the source that builds the
    library /usr/lib/libgutil.a).  this subtree is still in a process of 
    "evolvement" and its lack of documentation is an area we in support 
    engineering are painfully aware of and are trying to correct.  (if 
    you can't find /usr/people/4Dgifts on yer machine it's because no one
    has ever gone into manual mode while running the installation tool
    and explicitly tagged "dev.sw.giftssrc" for loading.  see the 
    description in the Release and Installation Notes document for how to 
    do this from the DEVelopment tape.)

    in essence you want to fold the guts of 

                 ~4Dgifts/iristools/imgtools/writeimg.c

    into yer own code.  this standalone "lobotomized" example program creates
    the SGI imagelib image file format you are seeking.  lets briefly examine 
    writeimg.c:
-----------------------------------------------------
/*
 *    writeimg -
 *          Write out an RGB image file.  This example uses three functions
 *    from the image library: 
 *
 *              iopen, putrow, and iclose.        
 *
 *    The function iopen is called to describe the xsize and ysize of the 
 *    RGB image to be written out.  
 *
 *    The function putrow writes a row of image data to the image file. It is
 *    called with an array of shorts with values in the range [0..255].
 *        
 *    The function iclose is called to close the image file.
 *
 *    Why not modify this program to be a filter that converts from your own
 *    image file format to IRIS images? 
 *
 *                                Paul Haeberli - 1987
 *
 */
#include "image.h"

unsigned short rbuf[4096];
unsigned short gbuf[4096];
unsigned short bbuf[4096];

main(argc,argv)
int argc;
char **argv;
{
    int y;
    int xsize, ysize;
    IMAGE *image;

    if(argc<4) {
        fprintf(stderr,"usage writeimg name xsize ysize\n");
        exit(1);
    }
    xsize = atoi(argv[2]);
    ysize = atoi(argv[3]);
    image = iopen(argv[1],"w",RLE(1),3,xsize,ysize,3);
    for(y=0; y<ysize; y++) {
        /*
                fill rbuf, gbuf, and bbuf with pixel values 
        */
        putrow(image,rbuf,y,0);                /* red row */
        putrow(image,gbuf,y,1);                /* green row */
        putrow(image,bbuf,y,2);                /* blue row */
    }
    iclose(image);
}
-----------------------------------------------------
so you will obviously been assigning yer own "xsize/ysize" values.
the iopen call is half of the core functionality (its source can be 
found in ~4Dgifts/iristools/open.c):

       IMAGE *iopen(file, mode [, type, dim, xsize, ysize, zsize])
       char *file;
       register char *mode;
       unsigned int type, dim, xsize, ysize, zsize;

             To open an image file for writing, iopen should be
        called with 7 arguments:  the name of the image file to open,
        and a mode of "w", followed by the type, the number of
        dimensions and the xsize, ysize and zsize of the image.  The 
	type indicates how many bytes are stored per pixel value, 
	and whether the image file should be run-length encoded.  Type 
	may be given as RLE(1), RLE(2), VERBATIM(1), or VERBATIM(2).  
	The recommended default is RLE(1).

             zsize should be 3 [bytes]--for the number of channels (Red, 
	Green, and Blue, 1 byte each)--if you want to generate RGB/SGI 
	imagelib image -type files.

             dim--the dimension--indicates whether the image is just a
        single row (one dimensional) or is an an array of rows (two
        dimensional) or is an array of 2 dimensional images (three
        dimensional).  A color image that consists of 3 layers (one
        for each read green and blue) is represented as a three
	dimensional image that is xsize by ysize by 3.  A black 
	and white image has one layer and is represented as a two 
	dimensional image that is xsize by ysize.

                iclose(image)
                register IMAGE  *image;

             Closes an image file that was open for reading or writing.  
	All output is flushed to the output file, and the output file 
	is closed.


The other thing you'll need to use is putrow (its source can be found in
~4Dgifts/iristools/libimage/row.c):

                putrow(image,buffer,y,z)
                register IMAGE  *image;
                unsigned short  *buffer;
                unsigned        y, z;

             Writes a row of pixels to the specified image file. The
        buffer should be an array of shorts that contain the pixel
        values.  If the image file maintains only one byte per
        pixel, then only the values passed in the buffer should be
        in the range 0..255.  The row of the image to be written is
        given by y, while z indicates which layer of the image to
        write to. The first layer of the image is layer 0.  The y
        argument should be greater than or equal to zero and less
        than the ysize of the image. You can write the rows to the
        image in any order.

what obviously has been left out of the above example ("the problem
is left to the reader as an exercise...") is the step where you need
to get the red channel's 8-bits of color intensity--as well as the
green and blue--from the the image data you are currently dealing
with, and load these channels, row by row into the 3 short arrays,
that you then call putrow with.  when compiling you'll want to include
"-limage" to specify libimage.a, and you may find you need/want
"-lgutil" (for libgutil.a) as well.  check out the Makefile in 
~4Dgifts/iristools/imgtools.

feel free to post more queries if yer still stuck.

--
                                             daveus rattus   

                                   yer friendly neighborhood ratman

                              KOYAANISQATSI

   ko.yan.nis.qatsi (from the Hopi Language)  n.  1. crazy life.  2. life
       in turmoil.  3. life out of balance.  4. life disintegrating.  
         5. a state of life that calls for another way of living.



More information about the Comp.sys.sgi mailing list