LoadTGA example

nobody at mailinator.com nobody at mailinator.com
Sun Aug 6 11:04:07 PDT 2006


Emp wrote:
 > I've written some code to load tga files for openGl use and 
wanted to donate
 > it (somewhere?)
 >
 > Could you people check whether it is not totally faulty (not 
to my knowledge
 > though).
 > I've written it so that it will even take a textfile as long 
as it is big
 > enough and the first 18 or so bytes are correct :)
 >
 > Any comments/improvements are more than welcome.
 > Also if anyone knows how to do good openGL error handling...

I noticed your post yesterday. For sharing your code you might 
want to check dsource.org. I don't use OpenGL so I can't help 
with your error handling question. I did want to suggest a way 
to use names to refer to the array offsets you used in your code.

The following code should suggest a strategy I think will work 
for using meaningful names. I did not test the code so it might 
work but certainly won't be very robust. I mostly wanted to 
illustrate how a combination of structs and unions might help.


import std.file;
alias std.file.read read;


align(1)
struct TGAHeader
{
     // raster stores BGRA
     // size of ID field that follows 18 byte header (0 usually)
     ubyte identsize;
     // type of colour map 0=none, 1=has palette
     ubyte colourmap;
     // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
     ubyte type;

     // first colour map entry in palette
     ushort cmStart;
     // number of colours in palette
     ushort cmLength;
      // number of bits per palette entry 15,16,24,32
      ubyte cmBits;

     // image x origin
     ushort xStart;
     // image y origin
     ushort yStart;
     // image width in pixels
     ushort width;
     // image height in pixels
     ushort height;
     // image bits per pixel 8,16,24,32
     ubyte bits;
     // image descriptor bits (vh flip bits)
     ubyte descriptor;

     enum
     {
         // greyscale image
         typeGREY = 3,
         // rgb image type (same as rgba)
         typeRGB  = 2,
         // rgba image type (same as rgb)
         typeRGBA = 2,

         // no palette
         colourmapRAW = 0,
         // palette present
         colourmapPAL = 1,

         // grey
         bitsGREY =  8,
         // rgb
         bitsRGB  = 24,
         // rgb w alpha
         bitsRGBA = 32,

         // alpha value bit mask
         descriptorAM = 15,
         // origin bit mask
         descriptorOM = 48,
         // ? img.pix[0] is at bottom left of scree
         descriptorBL = 0,
         // ? img.pix[0] is at bottom right of screen
         descriptorBR = 16,
         // ? img.pix[0] is at top left of screen
         descriptorTL = 32,
         // ? img.pix[0] is at top right of screen
         descriptorTR = 48
      };
}


align(1)
struct PixBGR
{
   ubyte b;
   ubyte g;
   ubyte r;

   alias r red;
   alias g green;
   alias b blue;
}


align(1)
struct PixRGB
{
   ubyte r;
   ubyte g;
   ubyte b;

   alias r red;
   alias g green;
   alias b blue;

   PixRGB opAssign(PixBGR bgr) {

     return *this;
   }
}


struct PixArrayMeta
{
   uint len;
   void* ptr;
}


union PixArray
{
   ubyte[] grey;
   PixBGR[] bgr;
   PixRGB[] rgb;
   PixArrayMeta meta;
}


struct TGAImage
{
   void[] buf;
   PixArray raster;
   TGAHeader* header;

   bool loadTGA(char[] filename)
   {
     // dump file contents in buf
     buf = read(filename);

     // make header point to start of buffer
     header = cast(TGAHeader*) &buf[0];

     // make sure the TGA has 24 bpp
     if( header.bits != header.bitsRGB ) return false;

     /*
      *  more type checking & etc here
      */

     // no colormap means raster follows header?
     raster.meta.ptr = &buf[header.sizeof];

     // raster.whatever.length; whatever is rgb, bgr, grey, ...
     raster.meta.len = header.width * header.height;

     // now swap BGR to RGB for OpenGL
     ubyte tempR, tempG, tempB;
     for(uint i = 0; i < raster.bgr.length; i++)
     {
       // using aliased names
       tempR = raster.bgr[i].red;
       tempG = raster.bgr[i].green;
       tempB = raster.bgr[i].blue;

       // using non-aliased names
       raster.rgb[i].r = tempR;
       raster.rgb[i].g = tempG;
       raster.rgb[i].b = tempB;
     }

     // raster has now swapped from BGR to RGB

     return true;
   }
}



More information about the Digitalmars-d-learn mailing list