www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - LoadTGA example

reply "Emp" <empty nomail.com> writes:
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;
} 
Aug 03 2006
next sibling parent reply "Emp" <empty nomail.com> writes:
Anybody knows a good place to send the code, or is it not really worth 
sending?
(Don't worry, I won't be offended) 
Aug 05 2006
parent Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
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
Aug 08 2006
prev sibling parent nobody mailinator.com writes:
Emp wrote:
 I've written some code to load tga files for openGl use and 

 it (somewhere?)

 Could you people check whether it is not totally faulty (not 

 though).
 I've written it so that it will even take a textfile as long 

 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; } }
Aug 06 2006