c++ texture class - Mine contribution to the community.

Started by
6 comments, last by _the_phantom_ 17 years, 5 months ago
Here comes mine contribution to the forum. Since I started to post threads here, I killed a bunch of doubts, and I'm very grateful. So, I remember a thing. We have allways people around searching for a loader of some type of image(file format), but allways get a library that do that. Well, not allways people want a library for some reason, so I get some ideas from internet and maked some adaptations to my needs. Conclusion: I writed a c++ class that load image from disk, and generate the openGL texture for you. The class supports .bmp, .png, .jpg, .tga, .pcx, anf tif. The only missing is .dds from directx. I think is support enough to the class :) The only requisites to the png, jpg, and tif, is that you will need the respective libraries to load that complex files. So you'll need libpng, libjpg, and libtiff to work with these. Ah! And if you use this class, you don't need to send me a e-mail, just post here that you are using this class. I want a feedback ;) If anyone want help to implement this source code, tell me. Some adjustments can be needed. The licence is GPL. And here comes the code: HEADER .hpp

/*
The Open Engine
Copyright (C) 2006 Johnny Birnfeld  https://sourceforge.net/projects/theopenengine

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

*/


#ifndef TOE_TEXTURE_H
#define TOE_TEXTURE_H

#include <string>
using namespace std;

class TOETexture{
	string _fileName;
	int _w;
	int _h;
	short int _bpp;
	unsigned int _id;
	unsigned char *_data;
	unsigned long _dataSize;
	
	float _OGLfilter;
	
	int readBMP( const char* );
	int readJPG( const char* );
	int readPNG( const char* );
	int readTIF( const char* );
	int readTGA( const char* );
	int readPCX( const char* );
	int readDDS( const char* );
	int generateTexture();
	void* combine( void*, size_t, void*, size_t );
	int tgaLoadRawData( unsigned char* );
	int tgaLoadRLEData( unsigned char* );
	void tgaBGRtoRGB();
	void flip();
	public:
		TOETexture();
		int load( string );
		int load( string, float );
		string fileName();
		unsigned int w();unsigned int h();
		unsigned int bpp();
		unsigned int id();
};

#endif


BODY .cpp

/*
The Open Engine
Copyright (C) 2006 Johnny Birnfeld  https://sourceforge.net/projects/theopenengine

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

*/


#include "TOETexture.hpp"
#include <iostream>
#include <fstream>
#include <GL/glu.h>

extern "C" {
	#include <jpeglib.h>
	#include <jerror.h>
}
#include <png.h>
#include <tiffio.h>


int TOETexture::readBMP( const char *filename ){
	unsigned short int bfType;
	long int bfOffBits;
	short int biPlanes;
	
	ifstream ifile(filename);
	if ( !ifile.good() )
		return 1; //File not found or corrupted.
	ifile.read( (char*)&bfType, sizeof(short int) );
	if (bfType != 19778){
		return 2; //Not a Bitmap-File
	}
	
	ifile.seekg(8, ios::cur); //skip file size and reserved fields of bitmap file header
	ifile.read( (char*)&bfOffBits, sizeof(long int) ); //get the position of the actual bitmap data
	ifile.seekg(4, ios::cur); //skip size of bitmap info header
	ifile.read( (char*)&this->_w, sizeof(int) ); //get the width of the bitmap
	ifile.read( (char*)&this->_h, sizeof(int) ); //get the heigth of the bitmap
	ifile.read( (char*)&biPlanes, sizeof(short int) ); //get the number of planes (must be set to 1)
	if (biPlanes != 1){
		return 3; //number of Planes not 1!
	}
	ifile.read( (char*)&this->_bpp, sizeof(short int) ); //get the number of bits per pixel
	if (this->_bpp != 24){
		return 4; //Bits per Pixel not 24!
	}
	
	_dataSize = this->_w * this->_h * 3; //calculate the size of the image in bytes
	_data = new unsigned char[_dataSize];
	
	ifile.seekg(bfOffBits, ios::beg); //seek to the actual data
	ifile.read( (char*)_data, _dataSize ); //read data
	
	//swap red and blue (bgr -> rgb)
	unsigned char temp;
	for ( unsigned int i = 0; i < _dataSize; i += 3 ){
		temp = _data;
		_data = _data;
		_data = temp;
	}
	
	ifile.close();
	
	<span class="cpp-keyword">this</span>-&gt;_fileName = filename;
	
	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;
}

<span class="cpp-keyword">int</span> TOETexture::readJPG( <span class="cpp-keyword">const</span> <span class="cpp-keyword">char</span>* filename ){
	
	FILE *file;
	<span class="cpp-keyword">struct</span> jpeg_decompress_struct cinfo;
	<span class="cpp-keyword">struct</span> jpeg_error_mgr jerr;
	<span class="cpp-keyword">volatile</span> JSAMPROW row = <span class="cpp-number">0</span>;
	JSAMPROW rowptr[<span class="cpp-number">1</span>];
	uint i,j,nrows;
	
	cinfo.err = jpeg_std_error(&amp;jerr);
	jpeg_create_decompress(&amp;cinfo);

	<span class="cpp-comment">/* make sure the file is there and open it read-only (binary) */</span>
	<span class="cpp-keyword">if</span> ((file = fopen(filename, <span class="cpp-literal">"rb"</span>)) == NULL){
		<span class="cpp-keyword">return</span> <span class="cpp-number">1</span>; <span class="cpp-comment">//File not found.</span>
	}
	jpeg_stdio_src(&amp;cinfo, file);
	jpeg_read_header(&amp;cinfo, <span class="cpp-keyword">true</span>);
	jpeg_start_decompress(&amp;cinfo);
	
	<span class="cpp-keyword">this</span>-&gt;_w = cinfo.output_width;
	<span class="cpp-keyword">this</span>-&gt;_h = cinfo.output_height;
	<span class="cpp-comment">//printf("Colorspace %d\n",cinfo.jpeg_color_space);</span>
	<span class="cpp-keyword">this</span>-&gt;_bpp = cinfo.jpeg_color_space*<span class="cpp-number">8</span>; <span class="cpp-comment">//JPEG images do not handle alpha channel.</span>
	
	row = (JSAMPROW)calloc(<span class="cpp-number">1</span>,cinfo.image_width * cinfo.output_components
			* <span class="cpp-keyword">sizeof</span>(JSAMPLE));
	
	_dataSize = cinfo.image_width * cinfo.image_height * cinfo.output_components * <span class="cpp-keyword">sizeof</span>(JSAMPLE);
	_data = (<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>*)malloc(_dataSize);
	rowptr[<span class="cpp-number">0</span>] = row;
	
	<span class="cpp-keyword">for</span> ( i = <span class="cpp-number">0</span>; i &lt; cinfo.output_height; i++ ) {
		nrows = jpeg_read_scanlines(&amp;cinfo, rowptr, <span class="cpp-number">1</span>);
		<span class="cpp-keyword">if</span> (nrows != <span class="cpp-number">1</span>) {
			fprintf(stderr, <span class="cpp-literal">"jpeg_read_scanlines"</span>
					<span class="cpp-literal">" returns %u, expected 1\n"</span>, nrows);
			<span class="cpp-keyword">return</span> <span class="cpp-number">5</span>;
		}
		
		<span class="cpp-keyword">for</span> ( j = <span class="cpp-number">0</span>; j &lt; cinfo.output_width*cinfo.output_components; j++ )
			_data[(cinfo.output_height-<span class="cpp-number">1</span>-i)*cinfo.output_width*cinfo.output_components+j] = row[j];
	
	}
	
	jpeg_finish_decompress(&amp;cinfo);
	jpeg_destroy_decompress(&amp;cinfo);
	free(row);
	
	<span class="cpp-keyword">this</span>-&gt;_fileName = filename;
	
	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;
}

<span class="cpp-keyword">int</span> TOETexture::readPNG( <span class="cpp-keyword">const</span> <span class="cpp-keyword">char</span>* filename ){
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">int</span> y;
	
	png_structp png_ptr;
	png_infop info_ptr;
	<span class="cpp-keyword">int</span> number_of_passes;
	png_bytep * row_pointers;
	
	<span class="cpp-keyword">char</span> header[<span class="cpp-number">8</span>];	<span class="cpp-comment">// 8 is the maximum size that can be checked</span>
	
	<span class="cpp-comment">/* open file and test for it being a png */</span>
	FILE *fp = fopen(filename, <span class="cpp-literal">"rb"</span>);
	<span class="cpp-keyword">if</span> (!fp)
		<span class="cpp-keyword">return</span> <span class="cpp-number">1</span>; <span class="cpp-comment">//File not found</span>
	fread(header, <span class="cpp-number">1</span>, <span class="cpp-number">8</span>, fp);
	<span class="cpp-keyword">if</span> (png_sig_cmp((png_byte*)header, <span class="cpp-number">0</span>, <span class="cpp-number">8</span>))
		<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>; <span class="cpp-comment">//Not a valid file</span>
	
	<span class="cpp-comment">/* initialize stuff */</span>
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	
	<span class="cpp-keyword">if</span> (!png_ptr)
		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>; <span class="cpp-comment">//png_create_read_struct failed</span>
	
	info_ptr = png_create_info_struct(png_ptr);
	<span class="cpp-keyword">if</span> (!info_ptr)
		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>; <span class="cpp-comment">//png_create_info_struct failed</span>
	
	<span class="cpp-keyword">if</span> (setjmp(png_jmpbuf(png_ptr)))
		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>; <span class="cpp-comment">//Error during init_io</span>
	
	png_init_io(png_ptr, fp);
	png_set_sig_bytes(png_ptr, <span class="cpp-number">8</span>);
	
	png_read_info(png_ptr, info_ptr);
	
	number_of_passes = png_set_interlace_handling(png_ptr);
	png_read_update_info(png_ptr, info_ptr);
	
	<span class="cpp-comment">/* read file */</span>
	<span class="cpp-keyword">if</span> (setjmp(png_jmpbuf(png_ptr)))
		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>; <span class="cpp-comment">//Error during read_image</span>
	
	row_pointers = (png_bytep*) malloc(<span class="cpp-keyword">sizeof</span>(png_bytep) * info_ptr-&gt;height);
	<span class="cpp-keyword">for</span> ( y=<span class="cpp-number">0</span>; y&lt;info_ptr-&gt;height; y++ )
		row_pointers[y] = (png_byte*) malloc(info_ptr-&gt;rowbytes);
	
	png_read_image(png_ptr, row_pointers);
	
	
	
	<span class="cpp-keyword">this</span>-&gt;_w = info_ptr-&gt;width;
	<span class="cpp-keyword">this</span>-&gt;_h = info_ptr-&gt;height;
	<span class="cpp-keyword">this</span>-&gt;_bpp = info_ptr-&gt;bit_depth;
	<span class="cpp-keyword">if</span> ( info_ptr-&gt;color_type == PNG_COLOR_TYPE_RGBA ){
		<span class="cpp-keyword">this</span>-&gt;_bpp *= <span class="cpp-number">4</span>;
	}<span class="cpp-keyword">else</span>{
		<span class="cpp-keyword">if</span> ( info_ptr-&gt;color_type == PNG_COLOR_TYPE_RGB ){
			<span class="cpp-keyword">this</span>-&gt;_bpp *= <span class="cpp-number">3</span>;
		}<span class="cpp-keyword">else</span>{
			std::cout &lt;&lt; <span class="cpp-literal">"Undefined color type for the png file."</span> &lt;&lt; std::endl;
		}
	}
	_dataSize = <span class="cpp-keyword">this</span>-&gt;_h * info_ptr-&gt;rowbytes;
	_data = <span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[_dataSize];
	
	<span class="cpp-keyword">int</span> tszdata=<span class="cpp-number">0</span>;
	<span class="cpp-keyword">for</span> ( <span class="cpp-keyword">int</span> c=<span class="cpp-number">0</span>; c&lt;<span class="cpp-keyword">this</span>-&gt;_h; c++ ){
		_data = (<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>*)combine( _data, tszdata, row_pointers[c], info_ptr-&gt;rowbytes );
		tszdata += info_ptr-&gt;rowbytes;
	}
	
	<span class="cpp-keyword">this</span>-&gt;_fileName = filename;
	
	
	
	
	<span class="cpp-comment">/* finish decompression and release memory */</span>
	png_read_end (png_ptr, NULL);
	png_destroy_read_struct (&amp;png_ptr, &amp;info_ptr, NULL);
	<span class="cpp-comment">/* we don't need row pointers anymore */</span>
	free (row_pointers);
	
	fclose(fp);
	<span class="cpp-comment">//Done reading .png file</span>
	
	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;
}

<span class="cpp-keyword">int</span> TOETexture::readTIF( <span class="cpp-keyword">const</span> <span class="cpp-keyword">char</span> *filename ){
	TIFFRGBAImage img;
	uint32 *raster;
	size_t npixels;
	
	TIFF *tif;
	<span class="cpp-keyword">char</span> emsg[<span class="cpp-number">1024</span>];
	tif = TIFFOpen(filename, <span class="cpp-literal">"r"</span>);
	<span class="cpp-keyword">if</span> (tif == NULL) {
		fprintf(stderr, <span class="cpp-literal">"Problem loading %s\n"</span>, filename);
		<span class="cpp-keyword">return</span> <span class="cpp-number">1</span>;
	}
	<span class="cpp-keyword">if</span> ( TIFFRGBAImageBegin( &amp;img, tif, <span class="cpp-number">0</span>, emsg ) ){
		npixels = img.width * img.height;
		raster = (uint32 *) _TIFFmalloc(npixels * <span class="cpp-comment">/*img.samplesperpixel*/</span><span class="cpp-keyword">sizeof</span>(uint32));
		<span class="cpp-keyword">if</span> (raster != NULL) {
			<span class="cpp-keyword">if</span> (TIFFRGBAImageGet(&amp;img, raster, img.width, img.height) == <span class="cpp-number">0</span>) {
				TIFFError(filename, emsg);
				<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;
			}
		}
		TIFFRGBAImageEnd(&amp;img);
	}<span class="cpp-keyword">else</span>{
		TIFFError(filename, emsg);
		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>;
	}
	
	<span class="cpp-keyword">this</span>-&gt;_w = img.width;
	<span class="cpp-keyword">this</span>-&gt;_h = img.height;
	<span class="cpp-keyword">this</span>-&gt;_bpp = <span class="cpp-number">32</span><span class="cpp-comment">/*img.bitspersample * img.samplesperpixel*/</span>;
	_dataSize = <span class="cpp-keyword">this</span>-&gt;_w * <span class="cpp-keyword">this</span>-&gt;_h * <span class="cpp-keyword">this</span>-&gt;_bpp/<span class="cpp-number">8</span>;
	_data = <span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[_dataSize];
	memcpy( _data, raster, _dataSize );
	<span class="cpp-keyword">this</span>-&gt;_fileName = filename;
	
	
	TIFFClose(tif);
	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;
}

<span class="cpp-keyword">int</span> TOETexture::readTGA( <span class="cpp-keyword">const</span> <span class="cpp-keyword">char</span> *filename ){
	
	ifstream ifile;
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">long</span> fileSize;
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *pData;
	<span class="cpp-keyword">char</span> bEnc;
	
	ifile.open( filename,ios::binary );
	<span class="cpp-keyword">if</span>(ifile==NULL)
		<span class="cpp-keyword">return</span> <span class="cpp-number">1</span>;
	
	<span class="cpp-comment">// Get file size</span>
	ifile.seekg(<span class="cpp-number">0</span>,ios_base::end);
	fileSize=ifile.tellg();
	ifile.seekg(<span class="cpp-number">0</span>,ios_base::beg);
	
	pData = <span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[fileSize];
	<span class="cpp-keyword">if</span>(pData==NULL){
		ifile.close();
		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>;
	}
	
	<span class="cpp-comment">// Read the file into memory</span>
	ifile.read((<span class="cpp-keyword">char</span>*)pData,fileSize);
	ifile.close();
	
	
	<span class="cpp-comment">//Read Header</span>
	<span class="cpp-keyword">short</span> ColMapStart,ColMapLen;
	<span class="cpp-keyword">short</span> x1,y1,x2,y2;
	
	<span class="cpp-keyword">if</span>( pData[<span class="cpp-number">1</span>] &gt; <span class="cpp-number">1</span> )    <span class="cpp-comment">// 0 (RGB) and 1 (Indexed) are the only types we know about</span>
		<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>; <span class="cpp-comment">//Not a TGA file, or not supported format.</span>
	
	bEnc = pData[<span class="cpp-number">2</span>];     <span class="cpp-comment">// Encoding flag  1 = Raw indexed image</span>
                      <span class="cpp-comment">//                2 = Raw RGB</span>
                      <span class="cpp-comment">//                3 = Raw greyscale</span>
                      <span class="cpp-comment">//                9 = RLE indexed</span>
                      <span class="cpp-comment">//               10 = RLE RGB</span>
                      <span class="cpp-comment">//               11 = RLE greyscale</span>
                      <span class="cpp-comment">//               32 &amp; 33 Other compression, indexed</span>
	
	<span class="cpp-keyword">if</span>( bEnc &gt; <span class="cpp-number">11</span> or bEnc == <span class="cpp-number">1</span> or bEnc == <span class="cpp-number">9</span> ) <span class="cpp-comment">// We don't want 32 or 33. And engine does not read indexed images too.</span>
		<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;
	
	
	<span class="cpp-comment">// Get palette info</span>
	memcpy(&amp;ColMapStart,&amp;pData[<span class="cpp-number">3</span>],<span class="cpp-number">2</span>);
	memcpy(&amp;ColMapLen,&amp;pData[<span class="cpp-number">5</span>],<span class="cpp-number">2</span>);
	
	<span class="cpp-comment">// Reject indexed images if not a VGA palette (256 entries with 24 bits per entry)</span>
	<span class="cpp-keyword">if</span>(pData[<span class="cpp-number">1</span>]==<span class="cpp-number">1</span>) <span class="cpp-comment">// Indexed</span>
	{
		<span class="cpp-keyword">if</span>(ColMapStart!=<span class="cpp-number">0</span> || ColMapLen!=<span class="cpp-number">256</span> || pData[<span class="cpp-number">7</span>]!=<span class="cpp-number">24</span>)
			<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;
	}
	
	<span class="cpp-comment">// Get image window and produce width &amp; height values</span>
	memcpy(&amp;x1,&amp;pData[<span class="cpp-number">8</span>],<span class="cpp-number">2</span>);
	memcpy(&amp;y1,&amp;pData[<span class="cpp-number">10</span>],<span class="cpp-number">2</span>);
	memcpy(&amp;x2,&amp;pData[<span class="cpp-number">12</span>],<span class="cpp-number">2</span>);
	memcpy(&amp;y2,&amp;pData[<span class="cpp-number">14</span>],<span class="cpp-number">2</span>);
	
	<span class="cpp-keyword">this</span>-&gt;_w = (x2-x1);
	<span class="cpp-keyword">this</span>-&gt;_h = (y2-y1);
	
	<span class="cpp-keyword">if</span>(<span class="cpp-keyword">this</span>-&gt;_w&lt;<span class="cpp-number">1</span> || <span class="cpp-keyword">this</span>-&gt;_h&lt;<span class="cpp-number">1</span>)
		<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;
	
	<span class="cpp-comment">// Bits per Pixel</span>
	<span class="cpp-keyword">this</span>-&gt;_bpp = pData[<span class="cpp-number">16</span>];
	
	<span class="cpp-comment">// Check flip / interleave byte</span>
	<span class="cpp-keyword">if</span>(pData[<span class="cpp-number">17</span>]&gt;<span class="cpp-number">32</span>) <span class="cpp-comment">// Interleaved data</span>
		<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;
	
	<span class="cpp-comment">// Calculate image size</span>
	<span class="cpp-keyword">this</span>-&gt;_dataSize=(<span class="cpp-keyword">this</span>-&gt;_w * <span class="cpp-keyword">this</span>-&gt;_h * (<span class="cpp-keyword">this</span>-&gt;_bpp/<span class="cpp-number">8</span>));
	<span class="cpp-comment">//Read Header</span>
	
	
	<span class="cpp-keyword">switch</span>(bEnc)
	{
		<span class="cpp-keyword">case</span> <span class="cpp-number">2</span>: <span class="cpp-comment">// Raw RGB</span>
		{
			<span class="cpp-comment">// Check filesize against header values</span>
			<span class="cpp-keyword">if</span>((<span class="cpp-keyword">this</span>-&gt;_dataSize+<span class="cpp-number">18</span>+pData[<span class="cpp-number">0</span>])&gt;fileSize)
				<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;
			
			<span class="cpp-comment">// Double check image type field</span>
			<span class="cpp-keyword">if</span>(pData[<span class="cpp-number">1</span>]!=<span class="cpp-number">0</span>)
				<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;
			
			<span class="cpp-comment">// Load image data</span>
			<span class="cpp-keyword">if</span>( tgaLoadRawData( pData )!=<span class="cpp-number">0</span> )
				<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>;
			
			tgaBGRtoRGB(); <span class="cpp-comment">// Convert to RGB</span>
			<span class="cpp-keyword">break</span>;
		}
		
		<span class="cpp-keyword">case</span> <span class="cpp-number">10</span>: <span class="cpp-comment">// RLE RGB</span>
		{
			<span class="cpp-comment">// Double check image type field</span>
			<span class="cpp-keyword">if</span>( pData[<span class="cpp-number">1</span>] != <span class="cpp-number">0</span> )
				<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;
			
			<span class="cpp-comment">// Load image data</span>
			<span class="cpp-keyword">if</span>( tgaLoadRLEData( pData ) != <span class="cpp-number">0</span> )
				<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>;
			
			tgaBGRtoRGB(); <span class="cpp-comment">// Convert to RGB</span>
			<span class="cpp-keyword">break</span>;
		}
		
		<span class="cpp-keyword">default</span>:
			<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;
	}
	
	<span class="cpp-comment">// Check flip bit</span>
	<span class="cpp-comment">//if((pData[17] &amp; 0x20)==0){</span>
	<span class="cpp-comment">//	flip();</span>
	<span class="cpp-comment">//}</span>
	
	<span class="cpp-comment">// Release file memory</span>
	<span class="cpp-keyword">delete</span> [] pData;
	pData = NULL;
	
	<span class="cpp-keyword">this</span>-&gt;_fileName = filename;
	
	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;
}

<span class="cpp-keyword">int</span> TOETexture::readPCX( <span class="cpp-keyword">const</span> <span class="cpp-keyword">char</span> *filename ){
	
	<span class="cpp-keyword">struct</span> PCXheader {
		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> Manufacturer;
		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> Version;
		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> Encoding;
		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> BitsPerPixel;
		<span class="cpp-keyword">short</span> <span class="cpp-keyword">int</span> Xmin, Ymin, Xmax, Ymax;
		<span class="cpp-keyword">short</span> <span class="cpp-keyword">int</span> HDpi, VDpi;
		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> Colormap[<span class="cpp-number">48</span>];
		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> Reserved;
		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> NPlanes;
		<span class="cpp-keyword">short</span> <span class="cpp-keyword">int</span> BytesPerLine;
		<span class="cpp-keyword">short</span> <span class="cpp-keyword">int</span> PaletteInfo;
		<span class="cpp-keyword">short</span> <span class="cpp-keyword">int</span> HscreenSize;
		<span class="cpp-keyword">short</span> <span class="cpp-keyword">int</span> VscreenSize;
		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> Filler[<span class="cpp-number">54</span>];
	};
	
	<span class="cpp-keyword">struct</span> PCXheader pcxh;
	<span class="cpp-keyword">int</span> bpl;
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *row, *buf = NULL;
	
	ifstream ifile(filename);
	<span class="cpp-keyword">if</span> ( !ifile.good() ){
		<span class="cpp-keyword">return</span> <span class="cpp-number">1</span>;
	}
	
	ifile.read( (<span class="cpp-keyword">char</span>*)&amp;pcxh, <span class="cpp-keyword">sizeof</span>(pcxh) );
	
	<span class="cpp-keyword">this</span>-&gt;_w = (pcxh.Xmax - pcxh.Xmin) + <span class="cpp-number">1</span>;
	<span class="cpp-keyword">this</span>-&gt;_h = (pcxh.Ymax - pcxh.Ymin) + <span class="cpp-number">1</span>;
	<span class="cpp-keyword">this</span>-&gt;_bpp = pcxh.BitsPerPixel * pcxh.NPlanes;
	<span class="cpp-keyword">if</span> ( <span class="cpp-keyword">this</span>-&gt;_bpp != <span class="cpp-number">24</span> ){
		ifile.close();
		<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;
	}
	
	<span class="cpp-keyword">this</span>-&gt;_dataSize = <span class="cpp-keyword">this</span>-&gt;_w*<span class="cpp-keyword">this</span>-&gt;_h*(<span class="cpp-keyword">this</span>-&gt;_bpp/<span class="cpp-number">8</span>);
	<span class="cpp-keyword">this</span>-&gt;_data = <span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[<span class="cpp-keyword">this</span>-&gt;_dataSize];
	
	
	bpl = pcxh.NPlanes * pcxh.BytesPerLine;
	buf = <span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[bpl];
	row = <span class="cpp-keyword">this</span>-&gt;_data;
	<span class="cpp-keyword">for</span> ( <span class="cpp-keyword">int</span> y=<span class="cpp-number">0</span>; y&lt;<span class="cpp-keyword">this</span>-&gt;_h; ++y ) {
		<span class="cpp-comment">/* decode a scan line to a temporary buffer first */</span>
		<span class="cpp-keyword">int</span> i, count = <span class="cpp-number">0</span>;
		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> ch;
		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *dst = buf;
		<span class="cpp-keyword">for</span>(i = <span class="cpp-number">0</span>; i &lt; bpl; i++) {
			<span class="cpp-keyword">if</span>(!count) {
				ifile.read( (<span class="cpp-keyword">char</span>*)&amp;ch, <span class="cpp-number">1</span> );
				<span class="cpp-keyword">if</span>( (ch &amp; 0xc0) == 0xc0) {
					count = ch &amp; 0x3f;
					ifile.read( (<span class="cpp-keyword">char</span>*)&amp;ch, <span class="cpp-number">1</span> );
				} <span class="cpp-keyword">else</span>
					count = <span class="cpp-number">1</span>;
			}
			dst<span style="font-weight:bold;"> = ch;
			count–;
		}
		
		<span class="cpp-comment">/* de-interlace planes */</span>
		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *src = buf;
		<span class="cpp-keyword">int</span> plane;
		<span class="cpp-keyword">for</span>(plane = <span class="cpp-number">0</span>; plane &lt; pcxh.NPlanes; plane++){
			<span class="cpp-keyword">int</span> x;
			dst = row + plane;
			<span class="cpp-keyword">for</span>(x = <span class="cpp-number">0</span>; x &lt; <span class="cpp-keyword">this</span>-&gt;_w; x++) {
				*dst = *src++;
				dst += pcxh.NPlanes;
			}
		}
		row += <span class="cpp-keyword">this</span>-&gt;_dataSize/<span class="cpp-keyword">this</span>-&gt;_h;
	}
	<span class="cpp-keyword">delete</span>[] buf;
	ifile.close();
	
	flip();
	
	<span class="cpp-keyword">this</span>-&gt;_fileName = filename;
	
	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;
}

<span class="cpp-keyword">int</span> TOETexture::readDDS( <span class="cpp-keyword">const</span> <span class="cpp-keyword">char</span> *filename ){
	<span class="cpp-keyword">return</span> <span class="cpp-number">1</span>;
}

<span class="cpp-keyword">int</span> TOETexture::generateTexture(){
	
	glGenTextures( <span class="cpp-number">1</span>, &amp;<span class="cpp-keyword">this</span>-&gt;_id );
	glBindTexture( GL_TEXTURE_2D, <span class="cpp-keyword">this</span>-&gt;_id );
	
	<span class="cpp-keyword">if</span> ( <span class="cpp-keyword">this</span>-&gt;_OGLfilter == GL_NEAREST ){ <span class="cpp-comment">//NORMAL</span>
		<span class="cpp-keyword">if</span> ( <span class="cpp-keyword">this</span>-&gt;_bpp != <span class="cpp-number">32</span> ){ <span class="cpp-comment">//imagem não tem canal alfa</span>
			glTexImage2D( GL_TEXTURE_2D, <span class="cpp-number">0</span>, <span class="cpp-number">3</span>,
					<span class="cpp-keyword">this</span>-&gt;_w, <span class="cpp-keyword">this</span>-&gt;_h,
					<span class="cpp-number">0</span>, GL_RGB, GL_UNSIGNED_BYTE,
					_data );
		}<span class="cpp-keyword">else</span>{
			glTexImage2D( GL_TEXTURE_2D, <span class="cpp-number">0</span>, <span class="cpp-number">4</span>,
					<span class="cpp-keyword">this</span>-&gt;_w, <span class="cpp-keyword">this</span>-&gt;_h,
					<span class="cpp-number">0</span>, GL_RGBA, GL_UNSIGNED_BYTE,
					_data );
		}
	}<span class="cpp-keyword">else</span>{ <span class="cpp-comment">//MIPMAP</span>
		<span class="cpp-keyword">if</span> ( <span class="cpp-keyword">this</span>-&gt;_bpp != <span class="cpp-number">32</span> ){ <span class="cpp-comment">//imagem não tem canal alfa</span>
			gluBuild2DMipmaps(GL_TEXTURE_2D, <span class="cpp-number">3</span>,
					<span class="cpp-keyword">this</span>-&gt;_w, <span class="cpp-keyword">this</span>-&gt;_h,
					GL_RGB, GL_UNSIGNED_BYTE,
					_data);
		}<span class="cpp-keyword">else</span>{
			gluBuild2DMipmaps(GL_TEXTURE_2D, <span class="cpp-number">4</span>,
					<span class="cpp-keyword">this</span>-&gt;_w, <span class="cpp-keyword">this</span>-&gt;_h,
					GL_RGBA, GL_UNSIGNED_BYTE,
					_data);
		}
		
	}
	
	<span class="cpp-keyword">if</span> ( <span class="cpp-keyword">this</span>-&gt;_OGLfilter == GL_NEAREST ){
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	}<span class="cpp-keyword">else</span>{
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	}
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, <span class="cpp-keyword">this</span>-&gt;_OGLfilter);
	
	
	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;
}

<span class="cpp-keyword">void</span>* TOETexture::combine (<span class="cpp-keyword">void</span> *o1, size_t s1, <span class="cpp-keyword">void</span> *o2, size_t s2){
	<span class="cpp-keyword">void</span> *result = malloc(s1 + s2);
	<span class="cpp-keyword">if</span> (result != NULL)
		mempcpy(mempcpy(result, o2, s2), o1, s1);
	<span class="cpp-keyword">return</span> result;
}

<span class="cpp-keyword">int</span> TOETexture::tgaLoadRawData( <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>* ppData ) <span class="cpp-comment">// Load uncompressed image data</span>
{
	<span class="cpp-keyword">short</span> iOffset;
	
	<span class="cpp-keyword">this</span>-&gt;_data=<span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[<span class="cpp-keyword">this</span>-&gt;_dataSize];
	
	<span class="cpp-keyword">if</span>(<span class="cpp-keyword">this</span>-&gt;_data==NULL)
		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>;
	
	iOffset = ppData[<span class="cpp-number">0</span>]+<span class="cpp-number">18</span>; <span class="cpp-comment">// Add header to ident field size</span>
	
	<span class="cpp-keyword">if</span>(ppData[<span class="cpp-number">1</span>]==<span class="cpp-number">1</span>) <span class="cpp-comment">// Indexed images</span>
		iOffset+=<span class="cpp-number">768</span>;  <span class="cpp-comment">// Add palette offset</span>
	
	memcpy(<span class="cpp-keyword">this</span>-&gt;_data,&amp;ppData[iOffset],<span class="cpp-keyword">this</span>-&gt;_dataSize);
	
	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;
}

<span class="cpp-keyword">int</span> TOETexture::tgaLoadRLEData( <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>* ppData ) <span class="cpp-comment">// Load RLE compressed image data</span>
{
	<span class="cpp-keyword">short</span> iOffset,iPixelSize;
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *pCur;
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">long</span> Index=<span class="cpp-number">0</span>;
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> bLength,bLoop;
	
	<span class="cpp-comment">// Calculate offset to image data</span>
	iOffset=ppData[<span class="cpp-number">0</span>]+<span class="cpp-number">18</span>;
	
	<span class="cpp-comment">// Add palette offset for indexed images</span>
	<span class="cpp-keyword">if</span>(ppData[<span class="cpp-number">1</span>]==<span class="cpp-number">1</span>)
		iOffset+=<span class="cpp-number">768</span>; 
	
	<span class="cpp-comment">// Get pixel size in bytes</span>
	iPixelSize=<span class="cpp-keyword">this</span>-&gt;_bpp/<span class="cpp-number">8</span>;
	
	<span class="cpp-comment">// Set our pointer to the beginning of the image data</span>
	pCur=&amp;ppData[iOffset];
 
	<span class="cpp-comment">// Allocate space for the image data</span>
	<span class="cpp-keyword">this</span>-&gt;_data=<span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[<span class="cpp-keyword">this</span>-&gt;_dataSize];
 
	<span class="cpp-keyword">if</span>(<span class="cpp-keyword">this</span>-&gt;_data==NULL)
		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>;
 
	<span class="cpp-comment">// Decode</span>
	<span class="cpp-keyword">while</span>(Index&lt;<span class="cpp-keyword">this</span>-&gt;_dataSize) 
	{
		<span class="cpp-keyword">if</span>(*pCur &amp; 0x80) <span class="cpp-comment">// Run length chunk (High bit = 1)</span>
		{
			bLength=*pCur-<span class="cpp-number">127</span>; <span class="cpp-comment">// Get run length</span>
			pCur++;            <span class="cpp-comment">// Move to pixel data  </span>
			
			<span class="cpp-comment">// Repeat the next pixel bLength times</span>
			<span class="cpp-keyword">for</span>(bLoop=<span class="cpp-number">0</span>;bLoop!=bLength;++bLoop,Index+=iPixelSize)
				memcpy(&amp;<span class="cpp-keyword">this</span>-&gt;_data[Index],pCur,iPixelSize);
			
			pCur+=iPixelSize; <span class="cpp-comment">// Move to the next descriptor chunk</span>
		}
		<span class="cpp-keyword">else</span> <span class="cpp-comment">// Raw chunk</span>
		{
			bLength=*pCur+<span class="cpp-number">1</span>; <span class="cpp-comment">// Get run length</span>
			pCur++;          <span class="cpp-comment">// Move to pixel data</span>
			
			<span class="cpp-comment">// Write the next bLength pixels directly</span>
			<span class="cpp-keyword">for</span>(bLoop=<span class="cpp-number">0</span>;bLoop!=bLength;++bLoop,Index+=iPixelSize,pCur+=iPixelSize)
				memcpy(&amp;<span class="cpp-keyword">this</span>-&gt;_data[Index],pCur,iPixelSize);
		}
	}
 
	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;
}

<span class="cpp-keyword">void</span> TOETexture::tgaBGRtoRGB() <span class="cpp-comment">// Convert BGR to RGB (or back again)</span>
{
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">long</span> Index,nPixels;
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *bCur;
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> bTemp;
	<span class="cpp-keyword">short</span> iPixelSize;
	
	<span class="cpp-comment">// Set ptr to start of image</span>
	bCur = <span class="cpp-keyword">this</span>-&gt;_data;
	
	<span class="cpp-comment">// Calc number of pixels</span>
	nPixels = <span class="cpp-keyword">this</span>-&gt;_w*<span class="cpp-keyword">this</span>-&gt;_h;
	
	<span class="cpp-comment">// Get pixel size in bytes</span>
	iPixelSize = <span class="cpp-keyword">this</span>-&gt;_bpp/<span class="cpp-number">8</span>;
	
	<span class="cpp-keyword">for</span>(Index=<span class="cpp-number">0</span>;Index!=nPixels;Index++)  <span class="cpp-comment">// For each pixel</span>
	{
		bTemp=*bCur;      <span class="cpp-comment">// Get Blue value</span>
		*bCur=*(bCur+<span class="cpp-number">2</span>);  <span class="cpp-comment">// Swap red value into first position</span>
		*(bCur+<span class="cpp-number">2</span>)=bTemp;  <span class="cpp-comment">// Write back blue to last position</span>
		
		bCur+=iPixelSize; <span class="cpp-comment">// Jump to next pixel</span>
	}
	
}

<span class="cpp-keyword">void</span> TOETexture::flip( ) <span class="cpp-comment">// Flips the image vertically (Why store images upside down?)</span>
{
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> bTemp;
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *pLine1, *pLine2;
	<span class="cpp-keyword">int</span> iLineLen,iIndex;
 
	iLineLen=<span class="cpp-keyword">this</span>-&gt;_w*(<span class="cpp-keyword">this</span>-&gt;_bpp/<span class="cpp-number">8</span>);
	pLine1=<span class="cpp-keyword">this</span>-&gt;_data;
	pLine2=&amp;<span class="cpp-keyword">this</span>-&gt;_data[iLineLen * (<span class="cpp-keyword">this</span>-&gt;_h - <span class="cpp-number">1</span>)];
 
	<span class="cpp-keyword">for</span>( ;pLine1&lt;pLine2;pLine2-=(iLineLen*<span class="cpp-number">2</span>))
	{
		<span class="cpp-keyword">for</span>(iIndex=<span class="cpp-number">0</span>;iIndex!=iLineLen;pLine1++,pLine2++,iIndex++)
		{
			bTemp=*pLine1;
			*pLine1=*pLine2;
			*pLine2=bTemp;
		}
	}
 
}







<span class="cpp-comment">///public methods</span>
TOETexture::TOETexture(){
	<span class="cpp-keyword">this</span>-&gt;_OGLfilter = GL_LINEAR_MIPMAP_LINEAR; <span class="cpp-comment">//Default value to the texture filter(Trilinear).</span>
}

<span class="cpp-keyword">int</span> TOETexture::load( string filename ){
	<span class="cpp-keyword">return</span> <span class="cpp-keyword">this</span>-&gt;load( filename, <span class="cpp-keyword">this</span>-&gt;_OGLfilter );
}

<span class="cpp-keyword">int</span> TOETexture::load( string filename, <span class="cpp-keyword">float</span> filterToUse ){
	<span class="cpp-keyword">this</span>-&gt;_OGLfilter = filterToUse;
	<span class="cpp-keyword">int</span> returnValue = <span class="cpp-number">0</span>;
	string ext = filename.substr( filename.length()-<span class="cpp-number">3</span>, filename.length()-<span class="cpp-number">1</span> );
	string extl = filename.substr( filename.length()-<span class="cpp-number">4</span>, filename.length()-<span class="cpp-number">1</span> );
	
	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"bmp"</span> ){
		returnValue = readBMP( filename.c_str() );
		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){
			returnValue = generateTexture();
		}
	}
	
	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"jpg"</span> or extl == <span class="cpp-literal">"jpeg"</span> ){
		returnValue = readJPG( filename.c_str() );
		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){
			returnValue = generateTexture();
		}
	}
	
	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"png"</span> ){
		returnValue = readPNG( filename.c_str() );
		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){
			returnValue = generateTexture();
		}
	}
	
	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"tif"</span> or extl == <span class="cpp-literal">"tiff"</span> ){
		returnValue = readTIF( filename.c_str() );
		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){
			returnValue = generateTexture();
		}
	}
	
	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"tga"</span> ){
		returnValue = readTGA( filename.c_str() );
		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){
			returnValue = generateTexture();
		}
	}
	
	
	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"pcx"</span> ){
		returnValue = readPCX( filename.c_str() );
		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){
			returnValue = generateTexture();
		}
	}
	
	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"dds"</span> ){
		returnValue = readDDS( filename.c_str() );
		cout &lt;&lt; <span class="cpp-literal">"INFO: "</span> &lt;&lt; <span class="cpp-keyword">this</span>-&gt;_w &lt;&lt; endl;
		cout &lt;&lt; <span class="cpp-literal">"INFO: "</span> &lt;&lt; <span class="cpp-keyword">this</span>-&gt;_h &lt;&lt; endl;
		cout &lt;&lt; <span class="cpp-literal">"INFO: "</span> &lt;&lt; <span class="cpp-keyword">this</span>-&gt;_bpp &lt;&lt; endl;
		cout &lt;&lt; <span class="cpp-literal">"INFO: "</span> &lt;&lt; <span class="cpp-keyword">this</span>-&gt;_fileName &lt;&lt; endl;
		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){
			returnValue = generateTexture();
		}
	}
	
	<span class="cpp-keyword">switch</span>( returnValue ){
		<span class="cpp-keyword">case</span> -<span class="cpp-number">1</span>:
			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Internal error reading image."</span> &lt;&lt; endl;
			<span class="cpp-keyword">break</span>;
		<span class="cpp-keyword">case</span> <span class="cpp-number">1</span>:
			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". File not found."</span> &lt;&lt; endl;
			<span class="cpp-keyword">break</span>;
		<span class="cpp-keyword">case</span> <span class="cpp-number">2</span>:
			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Unexpected file format. Wrong extension?"</span> &lt;&lt; endl;
			<span class="cpp-keyword">break</span>;
		<span class="cpp-keyword">case</span> <span class="cpp-number">3</span>:
			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Number of Planes not 1."</span> &lt;&lt; endl;
			<span class="cpp-keyword">break</span>;
		<span class="cpp-keyword">case</span> <span class="cpp-number">4</span>:
			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Unexpected bits per pixel."</span> &lt;&lt; endl;
			<span class="cpp-keyword">break</span>;
		<span class="cpp-keyword">case</span> <span class="cpp-number">5</span>:
			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Unexpected number of rows."</span> &lt;&lt; endl;
			<span class="cpp-keyword">break</span>;
		<span class="cpp-keyword">case</span> <span class="cpp-number">50</span>:
			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Could not generate texture."</span> &lt;&lt; endl;
			<span class="cpp-keyword">break</span>;
	}
	
	<span class="cpp-keyword">return</span> returnValue;
}

string TOETexture::fileName(){
	<span class="cpp-keyword">return</span> <span class="cpp-keyword">this</span>-&gt;_fileName;
}

<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">int</span> TOETexture::w(){
	<span class="cpp-keyword">return</span> <span class="cpp-keyword">this</span>-&gt;_w;
}

<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">int</span> TOETexture::h(){
	<span class="cpp-keyword">return</span> <span class="cpp-keyword">this</span>-&gt;_h;
}

<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">int</span> TOETexture::bpp(){
	<span class="cpp-keyword">return</span> <span class="cpp-keyword">this</span>-&gt;_bpp;
}

<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">int</span> TOETexture::id(){
	<span class="cpp-keyword">return</span> <span class="cpp-keyword">this</span>-&gt;_id;
}



</pre></div><!–ENDSCRIPT–>

Advertisement
Quote:
The licence is GPL.

:(

But anyway, here are my comments.


  • How about some documentation?

  • Don't put "using namespace std;" in header files! You've polluted the global namespace and defeated the entire purpose of namespaces.

  • What's with TOETexture? Just call it Texture and place it in a namespace. Prefixing class names is generally sort of useless; namespaces do a much better job.

  • You #include <string> but you use C strings for all your function parameters. Why?

  • Your public interface has very poor naming conventions. "w()" and "h()" and "bpp()" are terrible names.

  • You don't have a way of selectively disabling the loads I don't want to use. For example, lets say I only want to use the PNG functionality. You should have preprocessor switches I can set to skip the TIFF, et cetera, functionality so I don't have to link with all these extra libraries that I will never use.

  • Why is _OGLfilter a float?

  • You handle errors by returning magic numbers. You should really throw exceptions in many of these cases, or at the very least return enumeration values. When I recieve a return code of 4 from readBMP(), I have no idea what it means. This is not useful at all.

  • Your bitmap handling is pretty restrictive, isn't it? You only support certain bitmap color formats and such. Other types, like TGA, seem equally artificially restricted.

  • You mix C style IO (the JPEG loader) and C++ style IO (the bitmap loader). This has rather negative implications... the overall lack of consistency in the style of the code and the comments suggests this code is based primarily on tutorials or sample code, which implies that its probably not particularly robust.

  • Similarly, you inconsitantly print to stderr, stdout and sometimes not at all. Again, it's probably better just to throw an exception. Printing from a low-level interface like a texture is undesirable.

  • You don't have any way to bind the texture to make it current so it can be used. This essentially renders every texture you load except for the last one useless.

  • load() has a very poor method of extracting the extension that can result in naughty behavior if the string isn't well formed (for example, if the string is less than three characters). This is unstable.

  • From a high level perspective, I don't think binding together the texture itself, and the loading of that texture, is good design. Among other issues, it makes for some obnoxious rentrancy issues. For example, right now if I call load() twice, memory is leaked.

  • In fact, since you don't have a destructor, you leak memory anyway.



Overall, it's a respectable first attempt but needs a lot of work before it can compete with other available texture loading utility code for OpenGL (such as the OpenIL library). Keep at it!
Yes, the GPL thing was something I was going to comment on as well [sad]

and as I'm here <pimp>GameTexture Loader pimpage!</pimp> [wink]
Quote:
* How about some documentation?

Maybe in the future? Is just a class!
Quote:
* Don't put "using namespace std;" in header files! You've polluted the global namespace and defeated the entire purpose of namespaces.

My mistake. Now on .cpp.
Quote:
* What's with TOETexture? Just call it Texture and place it in a namespace. Prefixing class names is generally sort of useless; namespaces do a much better job.

I name all my classes in that way(of this project). I see no problem with that.
Quote:
* You #include <string> but you use C strings for all your function parameters. Why?

I use std::string just for the load method and _fileName attribute. Pass const char* for the other methods because they need to. ifstream just accept const char* as a parameter to open() or constructor. And fopen too. So...
Quote:
* Your public interface has very poor naming conventions. "w()" and "h()" and "bpp()" are terrible names.

This is a texture class. So a texture.w() is a little obvious you don't think? But I can change this. No problem.
( I wrote in that way because I saw in platically all library loaders, they implement member of a struct or method of a class named w or w(), to call image width. )
Quote:
* You don't have a way of selectively disabling the loads I don't want to use. For example, lets say I only want to use the PNG functionality. You should have preprocessor switches I can set to skip the TIFF, et cetera, functionality so I don't have to link with all these extra libraries that I will never use.

I'll fix this.
Quote:
* Why is _OGLfilter a float?

Because void glTexParameterf( GLenum target, GLenum pname, GLfloat param ).
Sure, I can call glTexParameteri(). Humm, ok, changed this. But I do not saw problem.
Quote:
* You handle errors by returning magic numbers. You should really throw exceptions in many of these cases, or at the very least return enumeration values. When I recieve a return code of 4 from readBMP(), I have no idea what it means. This is not useful at all.

Yeah, was thinking in a good way to do that... try - catch()?
Quote:
* Your bitmap handling is pretty restrictive, isn't it? You only support certain bitmap color formats and such. Other types, like TGA, seem equally artificially restricted.

You mean only to support 24/32 bits RGB/BGR compressed or uncompressed formats? I think is enought. I'll not put support here for indexed images. Anybody still use that?
I was thinking in support Greyscale images, but I'm not sure.
Quote:
* You mix C style IO (the JPEG loader) and C++ style IO (the bitmap loader). This has rather negative implications... the overall lack of consistency in the style of the code and the comments suggests this code is based primarily on tutorials or sample code, which implies that its probably not particularly robust.

Because void jpeg_stdio_src(j_decompress_ptr cinfo, FILE * infile); I cannot use fstream here(I thinked in that problem yes, but I have no choice), or can I?
Quote:
* Similarly, you inconsitantly print to stderr, stdout and sometimes not at all. Again, it's probably better just to throw an exception. Printing from a low-level interface like a texture is undesirable.

Forget to throw out these things. Now is clean.
Quote:
* You don't have any way to bind the texture to make it current so it can be used. This essentially renders every texture you load except for the last one useless.

No, was thinking on that functionality too.
Quote:
* load() has a very poor method of extracting the extension that can result in naughty behavior if the string isn't well formed (for example, if the string is less than three characters). This is unstable.

Don't thinked on that. Man, this is why open source is do great! Thanks for that!
The name now must have at least 5 characters.
Quote:
* From a high level perspective, I don't think binding together the texture itself, and the loading of that texture, is good design. Among other issues, it makes for some obnoxious rentrancy issues. For example, right now if I call load() twice, memory is leaked.

Quote:
* In fact, since you don't have a destructor, you leak memory anyway.

I made a fix. Look and tell me what you think.


Thank you man! This was of great help! hummmm your name in credits? :)

HEADER .hpp
/*The Open EngineCopyright (C) 2006 Johnny Birnfeld  https://sourceforge.net/projects/theopenengineThis program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public License version 2as published by the Free Software Foundation.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.*/#ifndef TOE_TEXTURE_H#define TOE_TEXTURE_H#include <string>class TOETexture{	std::string _fileName;	int _w;	int _h;	short int _bpp;	unsigned int _id;	unsigned char *_data;	unsigned long _dataSize;		int _OGLfilter;		int readBMP( const char* );	int readJPG( const char* );	int readPNG( const char* );	int readTIF( const char* );	int readTGA( const char* );	int readPCX( const char* );	int readDDS( const char* );	int generateTexture();	void* combine( void*, size_t, void*, size_t );	int tgaLoadRawData( unsigned char* );	int tgaLoadRLEData( unsigned char* );	void tgaBGRtoRGB();	void flip();	public:		TOETexture();		~TOETexture();		int load( std::string );		int load( std::string, int );		std::string fileName();		unsigned int width();unsigned int height();		unsigned int bpp();		unsigned int id();				void createInMemoryTexture( void* );};#endif


BODY .cpp
/*The Open EngineCopyright (C) 2006 Johnny Birnfeld  https://sourceforge.net/projects/theopenengineThis program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public License version 2as published by the Free Software Foundation.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.*/#include "TOETexture.hpp"#include <iostream>#include <fstream>#include <GL/glu.h>extern "C" {	#include <jpeglib.h>	#include <jerror.h>}#include <png.h>#include <tiffio.h>using namespace std;int TOETexture::readBMP( const char *filename ){	unsigned short int bfType;	long int bfOffBits;	short int biPlanes;		ifstream ifile(filename);	if ( !ifile.good() )		return 1; //File not found or corrupted.	ifile.read( (char*)&bfType, sizeof(short int) );	if (bfType != 19778){		return 2; //Not a Bitmap-File	}		ifile.seekg(8, ios::cur); //skip file size and reserved fields of bitmap file header	ifile.read( (char*)&bfOffBits, sizeof(long int) ); //get the position of the actual bitmap data	ifile.seekg(4, ios::cur); //skip size of bitmap info header	ifile.read( (char*)&this->_w, sizeof(int) ); //get the width of the bitmap	ifile.read( (char*)&this->_h, sizeof(int) ); //get the heigth of the bitmap	ifile.read( (char*)&biPlanes, sizeof(short int) ); //get the number of planes (must be set to 1)	if (biPlanes != 1){		return 3; //number of Planes not 1!	}	ifile.read( (char*)&this->_bpp, sizeof(short int) ); //get the number of bits per pixel	if (this->_bpp != 24){		return 4; //Bits per Pixel not 24!	}		_dataSize = this->_w * this->_h * 3; //calculate the size of the image in bytes	_data = new unsigned char[_dataSize];		ifile.seekg(bfOffBits, ios::beg); //seek to the actual data	ifile.read( (char*)_data, _dataSize ); //read data		//swap red and blue (bgr -> rgb)	unsigned char temp;	for ( unsigned int i = 0; i < _dataSize; i += 3 ){		temp = _data;		_data = _data;<br>		_data = temp;<br>	}<br>	<br>	ifile.close();<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_fileName = filename;<br>	<br>	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;<br>}<br><br><span class="cpp-keyword">int</span> TOETexture::readJPG( <span class="cpp-keyword">const</span> <span class="cpp-keyword">char</span>* filename ){<br>	<br>	FILE *file;<br>	<span class="cpp-keyword">struct</span> jpeg_decompress_struct cinfo;<br>	<span class="cpp-keyword">struct</span> jpeg_error_mgr jerr;<br>	<span class="cpp-keyword">volatile</span> JSAMPROW row = <span class="cpp-number">0</span>;<br>	JSAMPROW rowptr[<span class="cpp-number">1</span>];<br>	uint i,j,nrows;<br>	<br>	cinfo.err = jpeg_std_error(&amp;jerr);<br>	jpeg_create_decompress(&amp;cinfo);<br><br>	<span class="cpp-comment">/* make sure the file is there and open it read-only (binary) */</span><br>	<span class="cpp-keyword">if</span> ((file = fopen(filename, <span class="cpp-literal">"rb"</span>)) == NULL){<br>		<span class="cpp-keyword">return</span> <span class="cpp-number">1</span>; <span class="cpp-comment">//File not found.</span><br>	}<br>	jpeg_stdio_src(&amp;cinfo, file);<br>	jpeg_read_header(&amp;cinfo, <span class="cpp-keyword">true</span>);<br>	jpeg_start_decompress(&amp;cinfo);<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_w = cinfo.output_width;<br>	<span class="cpp-keyword">this</span>-&gt;_h = cinfo.output_height;<br>	<span class="cpp-keyword">this</span>-&gt;_bpp = cinfo.jpeg_color_space*<span class="cpp-number">8</span>; <span class="cpp-comment">//JPEG images do not handle alpha channel.</span><br>	<br>	row = (JSAMPROW)calloc(<span class="cpp-number">1</span>,cinfo.image_width * cinfo.output_components<br>			* <span class="cpp-keyword">sizeof</span>(JSAMPLE));<br>	<br>	_dataSize = cinfo.image_width * cinfo.image_height * cinfo.output_components * <span class="cpp-keyword">sizeof</span>(JSAMPLE);<br>	_data = (<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>*)malloc(_dataSize);<br>	rowptr[<span class="cpp-number">0</span>] = row;<br>	<br>	<span class="cpp-keyword">for</span> ( i = <span class="cpp-number">0</span>; i &lt; cinfo.output_height; i++ ) {<br>		nrows = jpeg_read_scanlines(&amp;cinfo, rowptr, <span class="cpp-number">1</span>);<br>		<span class="cpp-keyword">if</span> (nrows != <span class="cpp-number">1</span>) {<br>			<span class="cpp-keyword">return</span> <span class="cpp-number">5</span>;<br>		}<br>		<br>		<span class="cpp-keyword">for</span> ( j = <span class="cpp-number">0</span>; j &lt; cinfo.output_width*cinfo.output_components; j++ )<br>			_data[(cinfo.output_height-<span class="cpp-number">1</span>-i)*cinfo.output_width*cinfo.output_components+j] = row[j];<br>	<br>	}<br>	<br>	jpeg_finish_decompress(&amp;cinfo);<br>	jpeg_destroy_decompress(&amp;cinfo);<br>	free(row);<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_fileName = filename;<br>	<br>	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;<br>}<br><br><span class="cpp-keyword">int</span> TOETexture::readPNG( <span class="cpp-keyword">const</span> <span class="cpp-keyword">char</span>* filename ){<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">int</span> y;<br>	<br>	png_structp png_ptr;<br>	png_infop info_ptr;<br>	<span class="cpp-keyword">int</span> number_of_passes;<br>	png_bytep * row_pointers;<br>	<br>	<span class="cpp-keyword">char</span> header[<span class="cpp-number">8</span>];	<span class="cpp-comment">// 8 is the maximum size that can be checked</span><br>	<br>	<span class="cpp-comment">/* open file and test for it being a png */</span><br>	FILE *fp = fopen(filename, <span class="cpp-literal">"rb"</span>);<br>	<span class="cpp-keyword">if</span> (!fp)<br>		<span class="cpp-keyword">return</span> <span class="cpp-number">1</span>; <span class="cpp-comment">//File not found</span><br>	fread(header, <span class="cpp-number">1</span>, <span class="cpp-number">8</span>, fp);<br>	<span class="cpp-keyword">if</span> (png_sig_cmp((png_byte*)header, <span class="cpp-number">0</span>, <span class="cpp-number">8</span>))<br>		<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>; <span class="cpp-comment">//Not a valid file</span><br>	<br>	<span class="cpp-comment">/* initialize stuff */</span><br>	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);<br>	<br>	<span class="cpp-keyword">if</span> (!png_ptr)<br>		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>; <span class="cpp-comment">//png_create_read_struct failed</span><br>	<br>	info_ptr = png_create_info_struct(png_ptr);<br>	<span class="cpp-keyword">if</span> (!info_ptr)<br>		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>; <span class="cpp-comment">//png_create_info_struct failed</span><br>	<br>	<span class="cpp-keyword">if</span> (setjmp(png_jmpbuf(png_ptr)))<br>		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>; <span class="cpp-comment">//Error during init_io</span><br>	<br>	png_init_io(png_ptr, fp);<br>	png_set_sig_bytes(png_ptr, <span class="cpp-number">8</span>);<br>	<br>	png_read_info(png_ptr, info_ptr);<br>	<br>	number_of_passes = png_set_interlace_handling(png_ptr);<br>	png_read_update_info(png_ptr, info_ptr);<br>	<br>	<span class="cpp-comment">/* read file */</span><br>	<span class="cpp-keyword">if</span> (setjmp(png_jmpbuf(png_ptr)))<br>		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>; <span class="cpp-comment">//Error during read_image</span><br>	<br>	row_pointers = (png_bytep*) malloc(<span class="cpp-keyword">sizeof</span>(png_bytep) * info_ptr-&gt;height);<br>	<span class="cpp-keyword">for</span> ( y=<span class="cpp-number">0</span>; y&lt;info_ptr-&gt;height; y++ )<br>		row_pointers[y] = (png_byte*) malloc(info_ptr-&gt;rowbytes);<br>	<br>	png_read_image(png_ptr, row_pointers);<br>	<br>	<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_w = info_ptr-&gt;width;<br>	<span class="cpp-keyword">this</span>-&gt;_h = info_ptr-&gt;height;<br>	<span class="cpp-keyword">this</span>-&gt;_bpp = info_ptr-&gt;bit_depth;<br>	<span class="cpp-keyword">if</span> ( info_ptr-&gt;color_type == PNG_COLOR_TYPE_RGBA ){<br>		<span class="cpp-keyword">this</span>-&gt;_bpp *= <span class="cpp-number">4</span>;<br>	}<span class="cpp-keyword">else</span>{<br>		<span class="cpp-keyword">if</span> ( info_ptr-&gt;color_type == PNG_COLOR_TYPE_RGB ){<br>			<span class="cpp-keyword">this</span>-&gt;_bpp *= <span class="cpp-number">3</span>;<br>		}<span class="cpp-keyword">else</span>{<br>			<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;<br>		}<br>	}<br>	_dataSize = <span class="cpp-keyword">this</span>-&gt;_h * info_ptr-&gt;rowbytes;<br>	_data = <span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[_dataSize];<br>	<br>	<span class="cpp-keyword">int</span> tszdata=<span class="cpp-number">0</span>;<br>	<span class="cpp-keyword">for</span> ( <span class="cpp-keyword">int</span> c=<span class="cpp-number">0</span>; c&lt;<span class="cpp-keyword">this</span>-&gt;_h; c++ ){<br>		_data = (<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>*)combine( _data, tszdata, row_pointers[c], info_ptr-&gt;rowbytes );<br>		tszdata += info_ptr-&gt;rowbytes;<br>	}<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_fileName = filename;<br>	<br>	<br>	<br>	<br>	<span class="cpp-comment">/* finish decompression and release memory */</span><br>	png_read_end (png_ptr, NULL);<br>	png_destroy_read_struct (&amp;png_ptr, &amp;info_ptr, NULL);<br>	<span class="cpp-comment">/* we don't need row pointers anymore */</span><br>	free (row_pointers);<br>	<br>	fclose(fp);<br>	<span class="cpp-comment">//Done reading .png file</span><br>	<br>	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;<br>}<br><br><span class="cpp-keyword">int</span> TOETexture::readTIF( <span class="cpp-keyword">const</span> <span class="cpp-keyword">char</span> *filename ){<br>	TIFFRGBAImage img;<br>	uint32 *raster;<br>	size_t npixels;<br>	<br>	TIFF *tif;<br>	<span class="cpp-keyword">char</span> emsg[<span class="cpp-number">1024</span>];<br>	tif = TIFFOpen(filename, <span class="cpp-literal">"r"</span>);<br>	<span class="cpp-keyword">if</span> (tif == NULL) {<br>		<span class="cpp-keyword">return</span> <span class="cpp-number">1</span>;<br>	}<br>	<span class="cpp-keyword">if</span> ( TIFFRGBAImageBegin( &amp;img, tif, <span class="cpp-number">0</span>, emsg ) ){<br>		npixels = img.width * img.height;<br>		raster = (uint32 *) _TIFFmalloc(npixels * <span class="cpp-comment">/*img.samplesperpixel*/</span><span class="cpp-keyword">sizeof</span>(uint32));<br>		<span class="cpp-keyword">if</span> (raster != NULL) {<br>			<span class="cpp-keyword">if</span> (TIFFRGBAImageGet(&amp;img, raster, img.width, img.height) == <span class="cpp-number">0</span>) {<br>				TIFFError(filename, emsg);<br>				<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;<br>			}<br>		}<br>		TIFFRGBAImageEnd(&amp;img);<br>	}<span class="cpp-keyword">else</span>{<br>		TIFFError(filename, emsg);<br>		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>;<br>	}<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_w = img.width;<br>	<span class="cpp-keyword">this</span>-&gt;_h = img.height;<br>	<span class="cpp-keyword">this</span>-&gt;_bpp = <span class="cpp-number">32</span><span class="cpp-comment">/*img.bitspersample * img.samplesperpixel*/</span>;<br>	_dataSize = <span class="cpp-keyword">this</span>-&gt;_w * <span class="cpp-keyword">this</span>-&gt;_h * <span class="cpp-keyword">this</span>-&gt;_bpp/<span class="cpp-number">8</span>;<br>	_data = <span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[_dataSize];<br>	memcpy( _data, raster, _dataSize );<br>	<span class="cpp-keyword">this</span>-&gt;_fileName = filename;<br>	<br>	<br>	TIFFClose(tif);<br>	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;<br>}<br><br><span class="cpp-keyword">int</span> TOETexture::readTGA( <span class="cpp-keyword">const</span> <span class="cpp-keyword">char</span> *filename ){<br>	<br>	ifstream ifile;<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">long</span> fileSize;<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *pData;<br>	<span class="cpp-keyword">char</span> bEnc;<br>	<br>	ifile.open( filename,ios::binary );<br>	<span class="cpp-keyword">if</span>(ifile==NULL)<br>		<span class="cpp-keyword">return</span> <span class="cpp-number">1</span>;<br>	<br>	<span class="cpp-comment">// Get file size</span><br>	ifile.seekg(<span class="cpp-number">0</span>,ios_base::end);<br>	fileSize=ifile.tellg();<br>	ifile.seekg(<span class="cpp-number">0</span>,ios_base::beg);<br>	<br>	pData = <span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[fileSize];<br>	<span class="cpp-keyword">if</span>(pData==NULL){<br>		ifile.close();<br>		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>;<br>	}<br>	<br>	<span class="cpp-comment">// Read the file into memory</span><br>	ifile.read((<span class="cpp-keyword">char</span>*)pData,fileSize);<br>	ifile.close();<br>	<br>	<br>	<span class="cpp-comment">//Read Header</span><br>	<span class="cpp-keyword">short</span> ColMapStart,ColMapLen;<br>	<span class="cpp-keyword">short</span> x1,y1,x2,y2;<br>	<br>	<span class="cpp-keyword">if</span>( pData[<span class="cpp-number">1</span>] &gt; <span class="cpp-number">1</span> )    <span class="cpp-comment">// 0 (RGB) and 1 (Indexed) are the only types we know about</span><br>		<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>; <span class="cpp-comment">//Not a TGA file, or not supported format.</span><br>	<br>	bEnc = pData[<span class="cpp-number">2</span>];     <span class="cpp-comment">// Encoding flag  1 = Raw indexed image</span><br>                      <span class="cpp-comment">//                2 = Raw RGB</span><br>                      <span class="cpp-comment">//                3 = Raw greyscale</span><br>                      <span class="cpp-comment">//                9 = RLE indexed</span><br>                      <span class="cpp-comment">//               10 = RLE RGB</span><br>                      <span class="cpp-comment">//               11 = RLE greyscale</span><br>                      <span class="cpp-comment">//               32 &amp; 33 Other compression, indexed</span><br>	<br>	<span class="cpp-keyword">if</span>( bEnc &gt; <span class="cpp-number">11</span> or bEnc == <span class="cpp-number">1</span> or bEnc == <span class="cpp-number">9</span> ) <span class="cpp-comment">// We don't want 32 or 33. And engine does not read indexed images too.</span><br>		<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;<br>	<br>	<br>	<span class="cpp-comment">// Get palette info</span><br>	memcpy(&amp;ColMapStart,&amp;pData[<span class="cpp-number">3</span>],<span class="cpp-number">2</span>);<br>	memcpy(&amp;ColMapLen,&amp;pData[<span class="cpp-number">5</span>],<span class="cpp-number">2</span>);<br>	<br>	<span class="cpp-comment">// Reject indexed images if not a VGA palette (256 entries with 24 bits per entry)</span><br>	<span class="cpp-keyword">if</span>(pData[<span class="cpp-number">1</span>]==<span class="cpp-number">1</span>) <span class="cpp-comment">// Indexed</span><br>	{<br>		<span class="cpp-keyword">if</span>(ColMapStart!=<span class="cpp-number">0</span> || ColMapLen!=<span class="cpp-number">256</span> || pData[<span class="cpp-number">7</span>]!=<span class="cpp-number">24</span>)<br>			<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;<br>	}<br>	<br>	<span class="cpp-comment">// Get image window and produce width &amp; height values</span><br>	memcpy(&amp;x1,&amp;pData[<span class="cpp-number">8</span>],<span class="cpp-number">2</span>);<br>	memcpy(&amp;y1,&amp;pData[<span class="cpp-number">10</span>],<span class="cpp-number">2</span>);<br>	memcpy(&amp;x2,&amp;pData[<span class="cpp-number">12</span>],<span class="cpp-number">2</span>);<br>	memcpy(&amp;y2,&amp;pData[<span class="cpp-number">14</span>],<span class="cpp-number">2</span>);<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_w = (x2-x1);<br>	<span class="cpp-keyword">this</span>-&gt;_h = (y2-y1);<br>	<br>	<span class="cpp-keyword">if</span>(<span class="cpp-keyword">this</span>-&gt;_w&lt;<span class="cpp-number">1</span> || <span class="cpp-keyword">this</span>-&gt;_h&lt;<span class="cpp-number">1</span>)<br>		<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;<br>	<br>	<span class="cpp-comment">// Bits per Pixel</span><br>	<span class="cpp-keyword">this</span>-&gt;_bpp = pData[<span class="cpp-number">16</span>];<br>	<br>	<span class="cpp-comment">// Check flip / interleave byte</span><br>	<span class="cpp-keyword">if</span>(pData[<span class="cpp-number">17</span>]&gt;<span class="cpp-number">32</span>) <span class="cpp-comment">// Interleaved data</span><br>		<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;<br>	<br>	<span class="cpp-comment">// Calculate image size</span><br>	<span class="cpp-keyword">this</span>-&gt;_dataSize=(<span class="cpp-keyword">this</span>-&gt;_w * <span class="cpp-keyword">this</span>-&gt;_h * (<span class="cpp-keyword">this</span>-&gt;_bpp/<span class="cpp-number">8</span>));<br>	<span class="cpp-comment">//Read Header</span><br>	<br>	<br>	<span class="cpp-keyword">switch</span>(bEnc)<br>	{<br>		<span class="cpp-keyword">case</span> <span class="cpp-number">2</span>: <span class="cpp-comment">// Raw RGB</span><br>		{<br>			<span class="cpp-comment">// Check filesize against header values</span><br>			<span class="cpp-keyword">if</span>((<span class="cpp-keyword">this</span>-&gt;_dataSize+<span class="cpp-number">18</span>+pData[<span class="cpp-number">0</span>])&gt;fileSize)<br>				<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;<br>			<br>			<span class="cpp-comment">// Double check image type field</span><br>			<span class="cpp-keyword">if</span>(pData[<span class="cpp-number">1</span>]!=<span class="cpp-number">0</span>)<br>				<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;<br>			<br>			<span class="cpp-comment">// Load image data</span><br>			<span class="cpp-keyword">if</span>( tgaLoadRawData( pData )!=<span class="cpp-number">0</span> )<br>				<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>;<br>			<br>			tgaBGRtoRGB(); <span class="cpp-comment">// Convert to RGB</span><br>			<span class="cpp-keyword">break</span>;<br>		}<br>		<br>		<span class="cpp-keyword">case</span> <span class="cpp-number">10</span>: <span class="cpp-comment">// RLE RGB</span><br>		{<br>			<span class="cpp-comment">// Double check image type field</span><br>			<span class="cpp-keyword">if</span>( pData[<span class="cpp-number">1</span>] != <span class="cpp-number">0</span> )<br>				<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;<br>			<br>			<span class="cpp-comment">// Load image data</span><br>			<span class="cpp-keyword">if</span>( tgaLoadRLEData( pData ) != <span class="cpp-number">0</span> )<br>				<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>;<br>			<br>			tgaBGRtoRGB(); <span class="cpp-comment">// Convert to RGB</span><br>			<span class="cpp-keyword">break</span>;<br>		}<br>		<br>		<span class="cpp-keyword">default</span>:<br>			<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;<br>	}<br>	<br>	<span class="cpp-comment">// Check flip bit</span><br>	<span class="cpp-comment">//if((pData[17] &amp; 0x20)==0){</span><br>	<span class="cpp-comment">//	flip();</span><br>	<span class="cpp-comment">//}</span><br>	<br>	<span class="cpp-comment">// Release file memory</span><br>	<span class="cpp-keyword">delete</span> [] pData;<br>	pData = NULL;<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_fileName = filename;<br>	<br>	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;<br>}<br><br><span class="cpp-keyword">int</span> TOETexture::readPCX( <span class="cpp-keyword">const</span> <span class="cpp-keyword">char</span> *filename ){<br>	<br>	<span class="cpp-keyword">struct</span> PCXheader {<br>		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> Manufacturer;<br>		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> Version;<br>		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> Encoding;<br>		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> BitsPerPixel;<br>		<span class="cpp-keyword">short</span> <span class="cpp-keyword">int</span> Xmin, Ymin, Xmax, Ymax;<br>		<span class="cpp-keyword">short</span> <span class="cpp-keyword">int</span> HDpi, VDpi;<br>		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> Colormap[<span class="cpp-number">48</span>];<br>		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> Reserved;<br>		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> NPlanes;<br>		<span class="cpp-keyword">short</span> <span class="cpp-keyword">int</span> BytesPerLine;<br>		<span class="cpp-keyword">short</span> <span class="cpp-keyword">int</span> PaletteInfo;<br>		<span class="cpp-keyword">short</span> <span class="cpp-keyword">int</span> HscreenSize;<br>		<span class="cpp-keyword">short</span> <span class="cpp-keyword">int</span> VscreenSize;<br>		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> Filler[<span class="cpp-number">54</span>];<br>	};<br>	<br>	<span class="cpp-keyword">struct</span> PCXheader pcxh;<br>	<span class="cpp-keyword">int</span> bpl;<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *row, *buf = NULL;<br>	<br>	ifstream ifile(filename);<br>	<span class="cpp-keyword">if</span> ( !ifile.good() ){<br>		<span class="cpp-keyword">return</span> <span class="cpp-number">1</span>;<br>	}<br>	<br>	ifile.read( (<span class="cpp-keyword">char</span>*)&amp;pcxh, <span class="cpp-keyword">sizeof</span>(pcxh) );<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_w = (pcxh.Xmax - pcxh.Xmin) + <span class="cpp-number">1</span>;<br>	<span class="cpp-keyword">this</span>-&gt;_h = (pcxh.Ymax - pcxh.Ymin) + <span class="cpp-number">1</span>;<br>	<span class="cpp-keyword">this</span>-&gt;_bpp = pcxh.BitsPerPixel * pcxh.NPlanes;<br>	<span class="cpp-keyword">if</span> ( <span class="cpp-keyword">this</span>-&gt;_bpp != <span class="cpp-number">24</span> ){<br>		ifile.close();<br>		<span class="cpp-keyword">return</span> <span class="cpp-number">2</span>;<br>	}<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_dataSize = <span class="cpp-keyword">this</span>-&gt;_w*<span class="cpp-keyword">this</span>-&gt;_h*(<span class="cpp-keyword">this</span>-&gt;_bpp/<span class="cpp-number">8</span>);<br>	<span class="cpp-keyword">this</span>-&gt;_data = <span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[<span class="cpp-keyword">this</span>-&gt;_dataSize];<br>	<br>	<br>	bpl = pcxh.NPlanes * pcxh.BytesPerLine;<br>	buf = <span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[bpl];<br>	row = <span class="cpp-keyword">this</span>-&gt;_data;<br>	<span class="cpp-keyword">for</span> ( <span class="cpp-keyword">int</span> y=<span class="cpp-number">0</span>; y&lt;<span class="cpp-keyword">this</span>-&gt;_h; ++y ) {<br>		<span class="cpp-comment">/* decode a scan line to a temporary buffer first */</span><br>		<span class="cpp-keyword">int</span> i, count = <span class="cpp-number">0</span>;<br>		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> ch;<br>		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *dst = buf;<br>		<span class="cpp-keyword">for</span>(i = <span class="cpp-number">0</span>; i &lt; bpl; i++) {<br>			<span class="cpp-keyword">if</span>(!count) {<br>				ifile.read( (<span class="cpp-keyword">char</span>*)&amp;ch, <span class="cpp-number">1</span> );<br>				<span class="cpp-keyword">if</span>( (ch &amp; 0xc0) == 0xc0) {<br>					count = ch &amp; 0x3f;<br>					ifile.read( (<span class="cpp-keyword">char</span>*)&amp;ch, <span class="cpp-number">1</span> );<br>				} <span class="cpp-keyword">else</span><br>					count = <span class="cpp-number">1</span>;<br>			}<br>			dst<span style="font-weight:bold;"> = ch;<br>			count–;<br>		}<br>		<br>		<span class="cpp-comment">/* de-interlace planes */</span><br>		<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *src = buf;<br>		<span class="cpp-keyword">int</span> plane;<br>		<span class="cpp-keyword">for</span>(plane = <span class="cpp-number">0</span>; plane &lt; pcxh.NPlanes; plane++){<br>			<span class="cpp-keyword">int</span> x;<br>			dst = row + plane;<br>			<span class="cpp-keyword">for</span>(x = <span class="cpp-number">0</span>; x &lt; <span class="cpp-keyword">this</span>-&gt;_w; x++) {<br>				*dst = *src++;<br>				dst += pcxh.NPlanes;<br>			}<br>		}<br>		row += <span class="cpp-keyword">this</span>-&gt;_dataSize/<span class="cpp-keyword">this</span>-&gt;_h;<br>	}<br>	<span class="cpp-keyword">delete</span>[] buf;<br>	ifile.close();<br>	<br>	flip();<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_fileName = filename;<br>	<br>	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;<br>}<br><br><span class="cpp-keyword">int</span> TOETexture::readDDS( <span class="cpp-keyword">const</span> <span class="cpp-keyword">char</span> *filename ){<br>	<span class="cpp-keyword">return</span> <span class="cpp-number">1</span>;<br>}<br><br><span class="cpp-keyword">int</span> TOETexture::generateTexture(){<br>	<br>	glGenTextures( <span class="cpp-number">1</span>, &amp;<span class="cpp-keyword">this</span>-&gt;_id );<br>	glBindTexture( GL_TEXTURE_2D, <span class="cpp-keyword">this</span>-&gt;_id );<br>	<br>	<span class="cpp-keyword">if</span> ( <span class="cpp-keyword">this</span>-&gt;_OGLfilter == GL_NEAREST ){ <span class="cpp-comment">//NORMAL</span><br>		<span class="cpp-keyword">if</span> ( <span class="cpp-keyword">this</span>-&gt;_bpp != <span class="cpp-number">32</span> ){ <span class="cpp-comment">//image does not have alpha channel</span><br>			glTexImage2D( GL_TEXTURE_2D, <span class="cpp-number">0</span>, <span class="cpp-number">3</span>,<br>					<span class="cpp-keyword">this</span>-&gt;_w, <span class="cpp-keyword">this</span>-&gt;_h,<br>					<span class="cpp-number">0</span>, GL_RGB, GL_UNSIGNED_BYTE,<br>					_data );<br>		}<span class="cpp-keyword">else</span>{<br>			glTexImage2D( GL_TEXTURE_2D, <span class="cpp-number">0</span>, <span class="cpp-number">4</span>,<br>					<span class="cpp-keyword">this</span>-&gt;_w, <span class="cpp-keyword">this</span>-&gt;_h,<br>					<span class="cpp-number">0</span>, GL_RGBA, GL_UNSIGNED_BYTE,<br>					_data );<br>		}<br>	}<span class="cpp-keyword">else</span>{ <span class="cpp-comment">//MIPMAP</span><br>		<span class="cpp-keyword">if</span> ( <span class="cpp-keyword">this</span>-&gt;_bpp != <span class="cpp-number">32</span> ){ <span class="cpp-comment">//image does not have alpha channel</span><br>			gluBuild2DMipmaps(GL_TEXTURE_2D, <span class="cpp-number">3</span>,<br>					<span class="cpp-keyword">this</span>-&gt;_w, <span class="cpp-keyword">this</span>-&gt;_h,<br>					GL_RGB, GL_UNSIGNED_BYTE,<br>					_data);<br>		}<span class="cpp-keyword">else</span>{<br>			gluBuild2DMipmaps(GL_TEXTURE_2D, <span class="cpp-number">4</span>,<br>					<span class="cpp-keyword">this</span>-&gt;_w, <span class="cpp-keyword">this</span>-&gt;_h,<br>					GL_RGBA, GL_UNSIGNED_BYTE,<br>					_data);<br>		}<br>		<br>	}<br>	<br>	<span class="cpp-keyword">if</span> ( <span class="cpp-keyword">this</span>-&gt;_OGLfilter == GL_NEAREST ){<br>		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);<br>	}<span class="cpp-keyword">else</span>{<br>		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);<br>	}<br>	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, <span class="cpp-keyword">this</span>-&gt;_OGLfilter);<br>	<br>	glBindTexture( GL_TEXTURE_2D, <span class="cpp-number">0</span> ); <span class="cpp-comment">//Unbind current texture.</span><br>	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;<br>}<br><br><span class="cpp-keyword">void</span>* TOETexture::combine (<span class="cpp-keyword">void</span> *o1, size_t s1, <span class="cpp-keyword">void</span> *o2, size_t s2){<br>	<span class="cpp-keyword">void</span> *result = malloc(s1 + s2);<br>	<span class="cpp-keyword">if</span> (result != NULL)<br>		mempcpy(mempcpy(result, o2, s2), o1, s1);<br>	<span class="cpp-keyword">return</span> result;<br>}<br><br><span class="cpp-keyword">int</span> TOETexture::tgaLoadRawData( <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>* ppData ) <span class="cpp-comment">// Load uncompressed image data</span><br>{<br>	<span class="cpp-keyword">short</span> iOffset;<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_data=<span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[<span class="cpp-keyword">this</span>-&gt;_dataSize];<br>	<br>	<span class="cpp-keyword">if</span>(<span class="cpp-keyword">this</span>-&gt;_data==NULL)<br>		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>;<br>	<br>	iOffset = ppData[<span class="cpp-number">0</span>]+<span class="cpp-number">18</span>; <span class="cpp-comment">// Add header to ident field size</span><br>	<br>	<span class="cpp-keyword">if</span>(ppData[<span class="cpp-number">1</span>]==<span class="cpp-number">1</span>) <span class="cpp-comment">// Indexed images</span><br>		iOffset+=<span class="cpp-number">768</span>;  <span class="cpp-comment">// Add palette offset</span><br>	<br>	memcpy(<span class="cpp-keyword">this</span>-&gt;_data,&amp;ppData[iOffset],<span class="cpp-keyword">this</span>-&gt;_dataSize);<br>	<br>	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;<br>}<br><br><span class="cpp-keyword">int</span> TOETexture::tgaLoadRLEData( <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>* ppData ) <span class="cpp-comment">// Load RLE compressed image data</span><br>{<br>	<span class="cpp-keyword">short</span> iOffset,iPixelSize;<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *pCur;<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">long</span> Index=<span class="cpp-number">0</span>;<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> bLength,bLoop;<br>	<br>	<span class="cpp-comment">// Calculate offset to image data</span><br>	iOffset=ppData[<span class="cpp-number">0</span>]+<span class="cpp-number">18</span>;<br>	<br>	<span class="cpp-comment">// Add palette offset for indexed images</span><br>	<span class="cpp-keyword">if</span>(ppData[<span class="cpp-number">1</span>]==<span class="cpp-number">1</span>)<br>		iOffset+=<span class="cpp-number">768</span>; <br>	<br>	<span class="cpp-comment">// Get pixel size in bytes</span><br>	iPixelSize=<span class="cpp-keyword">this</span>-&gt;_bpp/<span class="cpp-number">8</span>;<br>	<br>	<span class="cpp-comment">// Set our pointer to the beginning of the image data</span><br>	pCur=&amp;ppData[iOffset];<br> <br>	<span class="cpp-comment">// Allocate space for the image data</span><br>	<span class="cpp-keyword">this</span>-&gt;_data=<span class="cpp-keyword">new</span> <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span>[<span class="cpp-keyword">this</span>-&gt;_dataSize];<br> <br>	<span class="cpp-keyword">if</span>(<span class="cpp-keyword">this</span>-&gt;_data==NULL)<br>		<span class="cpp-keyword">return</span> -<span class="cpp-number">1</span>;<br> <br>	<span class="cpp-comment">// Decode</span><br>	<span class="cpp-keyword">while</span>(Index&lt;<span class="cpp-keyword">this</span>-&gt;_dataSize) <br>	{<br>		<span class="cpp-keyword">if</span>(*pCur &amp; 0x80) <span class="cpp-comment">// Run length chunk (High bit = 1)</span><br>		{<br>			bLength=*pCur-<span class="cpp-number">127</span>; <span class="cpp-comment">// Get run length</span><br>			pCur++;            <span class="cpp-comment">// Move to pixel data  </span><br>			<br>			<span class="cpp-comment">// Repeat the next pixel bLength times</span><br>			<span class="cpp-keyword">for</span>(bLoop=<span class="cpp-number">0</span>;bLoop!=bLength;++bLoop,Index+=iPixelSize)<br>				memcpy(&amp;<span class="cpp-keyword">this</span>-&gt;_data[Index],pCur,iPixelSize);<br>			<br>			pCur+=iPixelSize; <span class="cpp-comment">// Move to the next descriptor chunk</span><br>		}<br>		<span class="cpp-keyword">else</span> <span class="cpp-comment">// Raw chunk</span><br>		{<br>			bLength=*pCur+<span class="cpp-number">1</span>; <span class="cpp-comment">// Get run length</span><br>			pCur++;          <span class="cpp-comment">// Move to pixel data</span><br>			<br>			<span class="cpp-comment">// Write the next bLength pixels directly</span><br>			<span class="cpp-keyword">for</span>(bLoop=<span class="cpp-number">0</span>;bLoop!=bLength;++bLoop,Index+=iPixelSize,pCur+=iPixelSize)<br>				memcpy(&amp;<span class="cpp-keyword">this</span>-&gt;_data[Index],pCur,iPixelSize);<br>		}<br>	}<br> <br>	<span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;<br>}<br><br><span class="cpp-keyword">void</span> TOETexture::tgaBGRtoRGB() <span class="cpp-comment">// Convert BGR to RGB (or back again)</span><br>{<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">long</span> Index,nPixels;<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *bCur;<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> bTemp;<br>	<span class="cpp-keyword">short</span> iPixelSize;<br>	<br>	<span class="cpp-comment">// Set ptr to start of image</span><br>	bCur = <span class="cpp-keyword">this</span>-&gt;_data;<br>	<br>	<span class="cpp-comment">// Calc number of pixels</span><br>	nPixels = <span class="cpp-keyword">this</span>-&gt;_w*<span class="cpp-keyword">this</span>-&gt;_h;<br>	<br>	<span class="cpp-comment">// Get pixel size in bytes</span><br>	iPixelSize = <span class="cpp-keyword">this</span>-&gt;_bpp/<span class="cpp-number">8</span>;<br>	<br>	<span class="cpp-keyword">for</span>(Index=<span class="cpp-number">0</span>;Index!=nPixels;Index++)  <span class="cpp-comment">// For each pixel</span><br>	{<br>		bTemp=*bCur;      <span class="cpp-comment">// Get Blue value</span><br>		*bCur=*(bCur+<span class="cpp-number">2</span>);  <span class="cpp-comment">// Swap red value into first position</span><br>		*(bCur+<span class="cpp-number">2</span>)=bTemp;  <span class="cpp-comment">// Write back blue to last position</span><br>		<br>		bCur+=iPixelSize; <span class="cpp-comment">// Jump to next pixel</span><br>	}<br>	<br>}<br><br><span class="cpp-keyword">void</span> TOETexture::flip( ) <span class="cpp-comment">// Flips the image vertically (Why store images upside down?)</span><br>{<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> bTemp;<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *pLine1, *pLine2;<br>	<span class="cpp-keyword">int</span> iLineLen,iIndex;<br> <br>	iLineLen=<span class="cpp-keyword">this</span>-&gt;_w*(<span class="cpp-keyword">this</span>-&gt;_bpp/<span class="cpp-number">8</span>);<br>	pLine1=<span class="cpp-keyword">this</span>-&gt;_data;<br>	pLine2=&amp;<span class="cpp-keyword">this</span>-&gt;_data[iLineLen * (<span class="cpp-keyword">this</span>-&gt;_h - <span class="cpp-number">1</span>)];<br> <br>	<span class="cpp-keyword">for</span>( ;pLine1&lt;pLine2;pLine2-=(iLineLen*<span class="cpp-number">2</span>))<br>	{<br>		<span class="cpp-keyword">for</span>(iIndex=<span class="cpp-number">0</span>;iIndex!=iLineLen;pLine1++,pLine2++,iIndex++)<br>		{<br>			bTemp=*pLine1;<br>			*pLine1=*pLine2;<br>			*pLine2=bTemp;<br>		}<br>	}<br> <br>}<br><br><br><br><br><br><br><br><span class="cpp-comment">///public methods</span><br>TOETexture::TOETexture(){<br>	<span class="cpp-keyword">this</span>-&gt;_fileName = <span class="cpp-literal">""</span>;<br>	<span class="cpp-keyword">this</span>-&gt;_w = <span class="cpp-number">0</span>;<br>	<span class="cpp-keyword">this</span>-&gt;_h = <span class="cpp-number">0</span>;<br>	<span class="cpp-keyword">this</span>-&gt;_bpp = <span class="cpp-number">0</span>;<br>	<span class="cpp-keyword">this</span>-&gt;_id = <span class="cpp-number">0</span>;<br>	<span class="cpp-keyword">this</span>-&gt;_data = NULL;<br>	<span class="cpp-keyword">this</span>-&gt;_dataSize = <span class="cpp-number">0</span>;<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_OGLfilter = GL_LINEAR_MIPMAP_LINEAR; <span class="cpp-comment">//Default value to the texture filter(Trilinear).</span><br>}<br><br>TOETexture::~TOETexture(){<br>	<span class="cpp-keyword">delete</span>[] <span class="cpp-keyword">this</span>-&gt;_data;<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_fileName = <span class="cpp-literal">""</span>;<br>	<span class="cpp-keyword">this</span>-&gt;_w = <span class="cpp-number">0</span>;<br>	<span class="cpp-keyword">this</span>-&gt;_h = <span class="cpp-number">0</span>;<br>	<span class="cpp-keyword">this</span>-&gt;_bpp = <span class="cpp-number">0</span>;<br>	<span class="cpp-keyword">this</span>-&gt;_id = <span class="cpp-number">0</span>;<br>	<span class="cpp-keyword">this</span>-&gt;_data = NULL;<br>	<span class="cpp-keyword">this</span>-&gt;_dataSize = <span class="cpp-number">0</span>;<br>}<br><br><span class="cpp-keyword">int</span> TOETexture::load( string filename ){<br>	<span class="cpp-keyword">return</span> <span class="cpp-keyword">this</span>-&gt;load( filename, <span class="cpp-keyword">this</span>-&gt;_OGLfilter );<br>}<br><br><span class="cpp-keyword">int</span> TOETexture::load( string filename, <span class="cpp-keyword">int</span> filterToUse ){<br>	<span class="cpp-keyword">if</span> ( filename.length() &lt; <span class="cpp-number">5</span> ){<br>		cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Filename is too short!"</span> &lt;&lt; endl;<br>		<span class="cpp-keyword">return</span> -<span class="cpp-number">2</span>;<br>	}<br>	<span class="cpp-keyword">if</span> ( <span class="cpp-keyword">this</span>-&gt;_data ){<br>		cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". File is already loaded! Will not load twice."</span> &lt;&lt; endl;<br>		<span class="cpp-keyword">return</span> -<span class="cpp-number">3</span>;<br>	}<br>	<br>	<span class="cpp-keyword">this</span>-&gt;_OGLfilter = filterToUse;<br>	<span class="cpp-keyword">int</span> returnValue = <span class="cpp-number">0</span>;<br>	string ext = filename.substr( filename.length()-<span class="cpp-number">3</span>, filename.length()-<span class="cpp-number">1</span> );<br>	string extl = filename.substr( filename.length()-<span class="cpp-number">4</span>, filename.length()-<span class="cpp-number">1</span> );<br>	<br>	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"bmp"</span> ){<br>		returnValue = readBMP( filename.c_str() );<br>		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){<br>			returnValue = generateTexture();<br>		}<br>	}<br>	<br>	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"jpg"</span> or extl == <span class="cpp-literal">"jpeg"</span> ){<br>		returnValue = readJPG( filename.c_str() );<br>		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){<br>			returnValue = generateTexture();<br>		}<br>	}<br>	<br>	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"png"</span> ){<br>		returnValue = readPNG( filename.c_str() );<br>		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){<br>			returnValue = generateTexture();<br>		}<br>	}<br>	<br>	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"tif"</span> or extl == <span class="cpp-literal">"tiff"</span> ){<br>		returnValue = readTIF( filename.c_str() );<br>		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){<br>			returnValue = generateTexture();<br>		}<br>	}<br>	<br>	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"tga"</span> ){<br>		returnValue = readTGA( filename.c_str() );<br>		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){<br>			returnValue = generateTexture();<br>		}<br>	}<br>	<br>	<br>	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"pcx"</span> ){<br>		returnValue = readPCX( filename.c_str() );<br>		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){<br>			returnValue = generateTexture();<br>		}<br>	}<br>	<br>	<span class="cpp-keyword">if</span> ( ext == <span class="cpp-literal">"dds"</span> ){<br>		returnValue = readDDS( filename.c_str() );<br>		cout &lt;&lt; <span class="cpp-literal">"INFO: "</span> &lt;&lt; <span class="cpp-keyword">this</span>-&gt;_w &lt;&lt; endl;<br>		cout &lt;&lt; <span class="cpp-literal">"INFO: "</span> &lt;&lt; <span class="cpp-keyword">this</span>-&gt;_h &lt;&lt; endl;<br>		cout &lt;&lt; <span class="cpp-literal">"INFO: "</span> &lt;&lt; <span class="cpp-keyword">this</span>-&gt;_bpp &lt;&lt; endl;<br>		cout &lt;&lt; <span class="cpp-literal">"INFO: "</span> &lt;&lt; <span class="cpp-keyword">this</span>-&gt;_fileName &lt;&lt; endl;<br>		<span class="cpp-keyword">if</span> ( returnValue == <span class="cpp-number">0</span> ){<br>			returnValue = generateTexture();<br>		}<br>	}<br>	<br>	<span class="cpp-keyword">switch</span>( returnValue ){<br>		<span class="cpp-keyword">case</span> -<span class="cpp-number">1</span>:<br>			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Internal error reading image."</span> &lt;&lt; endl;<br>			<span class="cpp-keyword">break</span>;<br>		<span class="cpp-keyword">case</span> <span class="cpp-number">1</span>:<br>			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". File not found."</span> &lt;&lt; endl;<br>			<span class="cpp-keyword">break</span>;<br>		<span class="cpp-keyword">case</span> <span class="cpp-number">2</span>:<br>			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Unexpected file format. Wrong extension?"</span> &lt;&lt; endl;<br>			<span class="cpp-keyword">break</span>;<br>		<span class="cpp-keyword">case</span> <span class="cpp-number">3</span>:<br>			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Number of Planes not 1."</span> &lt;&lt; endl;<br>			<span class="cpp-keyword">break</span>;<br>		<span class="cpp-keyword">case</span> <span class="cpp-number">4</span>:<br>			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Unexpected bits per pixel."</span> &lt;&lt; endl;<br>			<span class="cpp-keyword">break</span>;<br>		<span class="cpp-keyword">case</span> <span class="cpp-number">5</span>:<br>			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Unexpected number of rows."</span> &lt;&lt; endl;<br>			<span class="cpp-keyword">break</span>;<br>		<span class="cpp-keyword">case</span> <span class="cpp-number">50</span>:<br>			cout &lt;&lt; <span class="cpp-literal">"Error loading "</span> &lt;&lt; filename &lt;&lt; <span class="cpp-literal">". Could not generate texture."</span> &lt;&lt; endl;<br>			<span class="cpp-keyword">break</span>;<br>	}<br>	<br>	<span class="cpp-keyword">return</span> returnValue;<br>}<br><br>string TOETexture::fileName(){<br>	<span class="cpp-keyword">return</span> <span class="cpp-keyword">this</span>-&gt;_fileName;<br>}<br><br><span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">int</span> TOETexture::width(){<br>	<span class="cpp-keyword">return</span> <span class="cpp-keyword">this</span>-&gt;_w;<br>}<br><br><span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">int</span> TOETexture::height(){<br>	<span class="cpp-keyword">return</span> <span class="cpp-keyword">this</span>-&gt;_h;<br>}<br><br><span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">int</span> TOETexture::bpp(){<br>	<span class="cpp-keyword">return</span> <span class="cpp-keyword">this</span>-&gt;_bpp;<br>}<br><br><span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">int</span> TOETexture::id(){<br>	<span class="cpp-keyword">return</span> <span class="cpp-keyword">this</span>-&gt;_id;<br>}<br><br><span class="cpp-keyword">void</span> TOETexture::createInMemoryTexture( <span class="cpp-keyword">void</span>* ){<br>	<br>}<br><br><br></pre></div><!–ENDSCRIPT–><br><br><br>phantom, I'm just want to write a texture class, not a complete library :) Is a different approach.<br>Ah, I wanted to make you a question: Your project just runs &#111;n win32?
Quote:
Maybe in the future? Is just a class!

Irrelevant. It should be documented. Especially since your public interface is next to incomprehensible. Especially since you are providing it for others to use.

Quote:
I name all my classes in that way(of this project). I see no problem with that.

It adds no useful information. The functionality can be duplicated (in a better fashion) by namespaces. It hinders readability. Depending the layout of your project files and their names, it can make project navigation a chore.

Quote:
I use std::string just for the load method and _fileName attribute. Pass const char* for the other methods because they need to. ifstream just accept const char* as a parameter to open() or constructor. And fopen too. So...

std::string has a method called c_str() that will return a const char* representation of the string. So in the case of fopen(), you can use:
FILE *fp = fopen(some_std_string.c_str(),"rb"); 

or something similar. Using const char* for strings is a chore.

Quote:
This is a texture class. So a texture.w() is a little obvious you don't think? But I can change this. No problem.
( I wrote in that way because I saw in platically all library loaders, they implement member of a struct or method of a class named w or w(), to call image width. )

No, I don't think it's obvious. It's bad practice, and it's not self-documenting. The fact that you've seen other code use it doesn't mean it's okay, it means that other code is poor.

w() and h() might be intuitable. But consider, for example, bpp()?

What on earth does that mean? Bits per pixel or bytes per pixel? both are perfectly useful numbers (neither is neccessarily more or less useful than the other). So which is it? The user won't know unless he digs through your source code.

Quote:
Sure, I can call glTexParameteri(). Humm, ok, changed this. But I do not saw problem.

Because it's silly to use a float to store values that are integers. You never need that value to be a float, so why make it a float?

Quote:
Yeah, was thinking in a good way to do that... try - catch()?

It is unlikely that you will need to catch any exceptions in this code, since it is very low level and would not know what to do about the failure (the only exception would be if you wanted to translate the exceptions and rethrow). Therefore you won't need to use try/catch blocks.

However, I may have misspoke. Writing exception-safe code is hard and might be something you want to postpone until you have more programming experience.

You should at least convert your returned magic numbers to values that are part of some kind of error code enumeration, however.

Quote:
You mean only to support 24/32 bits RGB/BGR compressed or uncompressed formats? I think is enought. I'll not put support here for indexed images. Anybody still use that?
I was thinking in support Greyscale images, but I'm not sure.

Yes, people still use indexed formats. They use grayscale formats, too. The key to writing code suitable for others to use is to realize that you generally can't expect your users to need to use the code in exactly the way you'd use it.

Quote:
Because void jpeg_stdio_src(j_decompress_ptr cinfo, FILE * infile); I cannot use fstream here(I thinked in that problem yes, but I have no choice), or can I?

Hmm, fair enough. I don't know enough about libjpeg, so perhaps that does mean FILE* are you only options here.

Quote:
Thank you man!

No problem.
Quote:Original post by Tsumuji
phantom, I'm just want to write a texture class, not a complete library :) Is a different approach.
Ah, I wanted to make you a question: Your project just runs on win32?


The only difference is that I split up what you do in one class over a number of logical units; the benfit of more software engineering experiance I guess [smile]

GTL has successfully been compiled and tested for Win32, Win64 (x64) and ARM9 for the GP2x handheld console (which runs linux).
In theory, because it uses C++ and crossplatorm libs it should work on any system which uses the same Endian as Intel/AMD CPUs, the BMP and DDS code might have some 'issues' with systems which don't use it (PPC for example...), I should fix that.
You covered pretty much every point above, except one, which I would like to focus on a bit.
Quote:Original post by Tsumuji
Quote:
* You mix C style IO (the JPEG loader) and C++ style IO (the bitmap loader). This has rather negative implications... the overall lack of consistency in the style of the code and the comments suggests this code is based primarily on tutorials or sample code, which implies that its probably not particularly robust.

Because void jpeg_stdio_src(j_decompress_ptr cinfo, FILE * infile); I cannot use fstream here(I thinked in that problem yes, but I have no choice), or can I?

Any library worth it's name that requires I/O of some kind should have a way to abstract the I/O. Never used the JPEG library you use, so can't say whether it have it or not, but look for some user I/O callbacks.

Common ways are to register read/write callbacks, which the library use for reading/writing/whatever. For example, the read callback prototype can be something like:
int read(int n, void *p, void *user)

The user pointer being some user defined value, so you can pass the address of a istream object, letting you read from any stream derived from the standard C++ input stream.
Libjpg does indeed work that way, and with a clever bit of casting about you can pass any data you want down to it;
the jpg loader from GTL has an example of this hackery in action [grin]

This topic is closed to new replies.

Advertisement