Thread overview
LoadTGA example
Aug 04, 2006
Emp
Aug 05, 2006
Emp
Aug 08, 2006
Bruno Medeiros
Aug 06, 2006
nobody
August 04, 2006
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...

struct Texture
{
 GLuint width;
 GLuint height;
 GLuint id;
}

bool LoadTGA(inout Texture tex, char[] filename)
{
 GLubyte[] TGAfile;
 GLubyte  temp;
 GLuint  mode=GL_RGBA;
 GLuint  bpp;
 int   imageSize;
 const GLubyte[]  TGAheader= [0,0,2,0,0,0,0,0,0,0,0,0];

 try{
  TGAfile=cast(GLubyte[])read(filename);
    }
    catch{
  return false;
    }

 if (TGAfile[].length<18) return false;
 if (TGAfile[0..12] != TGAheader) return false;

 tex.width  = TGAfile[12+1] * 256 + TGAfile[12+0];
 tex.height = TGAfile[12+3] * 256 + TGAfile[12+2];

  if( tex.width <=0 || tex.width&(tex.width-1)  !=0 ||tex.width >512||
  tex.height<=0 || tex.height&(tex.height-1)!=0 ||tex.height>512||
  (TGAfile[12+4]!=24 && TGAfile[12+4]!=32)){
  return false;
 }

 bpp = TGAfile[12+4]/8;
 if (bpp==3) mode=GL_RGB;

 imageSize = tex.width * tex.height * bpp;

 if (TGAfile[].length<(18+imageSize)) return false;

 for(int i=0; i<imageSize; i+=bpp){
  temp=TGAfile[(12+6)+i];
  TGAfile[(12+6)+i] = TGAfile[(12+6)+i+2];
  TGAfile[(12+6)+i+2] = temp;
 }

 //error handling!
 glGenTextures(1, &tex.id);
 //error handling!
 glBindTexture(GL_TEXTURE_2D, tex.id);
 //error handling!
 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 //error handling!
 glTexImage2D(GL_TEXTURE_2D, 0, mode, tex.width, tex.height, 0, mode,
GL_UNSIGNED_BYTE, TGAfile[(12+6)..(imageSize+12+6)]);

 return true;
}


August 05, 2006
Anybody knows a good place to send the code, or is it not really worth
sending?
(Don't worry, I won't be offended)


August 06, 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;
  }
}
August 08, 2006
Emp wrote:
> Anybody knows a good place to send the code, or is it not really worth sending?
> (Don't worry, I won't be offended) 
> 
> 

I use SDL_Image for purposes as this. If there was a D homologue of SDL_Image, your function could belong there.
(but it is very little code, and your function should have abstracted the openGL texture setup, from the TGA loading.)

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D