wglgears: add srgb-mode to usage
[mesa-demos.git] / src / wgl / rtotex / image.cpp
blobc6561d390421847ca5bebcbc383ceda93e021757
1 //////////////////////////////////////////////////////////////////////////////////////////
2 // image.cpp
3 // functions for image for a texture
4 // Downloaded from: www.paulsprojects.net
5 // Created: 20th July 2002
6 //
7 // Copyright (c) 2006, Paul Baker
8 // Distributed under the New BSD Licence. (See accompanying file License.txt or copy at
9 // http://www.paulsprojects.net/NewBSDLicense.txt)
10 //////////////////////////////////////////////////////////////////////////////////////////
11 #include <windows.h>
12 #include <GL/gl.h>
13 #include "log.h"
14 #include "image.h"
16 extern LOG errorLog;
18 //Load - load a texture from a file
19 bool IMAGE::Load(const char * filename)
21 //Clear the data if already used
22 if(data)
23 delete [] data;
24 data=NULL;
25 bpp=0;
26 width=0;
27 height=0;
28 format=0;
30 int filenameLength=strlen(filename);
32 if( strncmp((filename+filenameLength-3), "BMP", 3)==0 ||
33 strncmp((filename+filenameLength-3), "bmp", 3)==0)
34 return LoadBMP(filename);
36 if( strncmp((filename+filenameLength-3), "PCX", 3)==0 ||
37 strncmp((filename+filenameLength-3), "pcx", 3)==0)
38 return LoadPCX(filename);
40 if( strncmp((filename+filenameLength-3), "TGA", 3)==0 ||
41 strncmp((filename+filenameLength-3), "tga", 3)==0)
42 return LoadTGA(filename);
44 errorLog.OutputError("%s does not end in \".tga\", \".bmp\" or \"pcx\"", filename);
45 return false;
50 bool IMAGE::LoadBMP(const char * filename)
52 FILE * file; //the texture file
53 BITMAPFILEHEADER fileHeader; //bitmap file header
54 BITMAPINFOHEADER infoHeader; //bitmap info header
56 //open file for reading
57 file=fopen(filename, "rb");
58 if(file==NULL)
60 errorLog.OutputError("Unable to open %s", filename);
61 return false;
64 //read the file header
65 fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file);
67 //check it's a bitmap
68 if(fileHeader.bfType != BITMAP_ID)
70 fclose(file);
71 errorLog.OutputError("%s is not a legal .BMP", filename);
72 return false;
75 //read in the information header
76 fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file);
78 //close the file
79 fclose(file);
81 //discover the bpp
82 if(infoHeader.biBitCount==24)
83 return Load24BitBMP(filename);
84 if(infoHeader.biBitCount==8)
85 return Load8BitBMP(filename);
87 errorLog.OutputError("%s has an unknown bpp", filename);
88 return false;
92 //Load24BitBMP - load a 24 bit bitmap file
93 bool IMAGE::Load24BitBMP(const char * filename)
95 errorLog.OutputSuccess("Loading %s in Load24bitBMP()", filename);
97 //set bpp and format
98 bpp=24;
99 format=GL_RGB;
101 FILE * file; //the texture file
102 BITMAPFILEHEADER fileHeader; //bitmap file header
103 BITMAPINFOHEADER infoHeader; //bitmap info header
105 //open file for reading
106 file=fopen(filename, "rb");
107 if(file==NULL)
109 errorLog.OutputError("Unable to open %s", filename);
110 return false;
113 //read the file header
114 fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file);
116 //check it's a bitmap
117 if(fileHeader.bfType != BITMAP_ID)
119 fclose(file);
120 errorLog.OutputError("%s is not a legal .BMP", filename);
121 return false;
124 //read in the information header
125 fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file);
127 //set size
128 width=infoHeader.biWidth;
129 height=infoHeader.biHeight;
131 //calculate the stride in bytes: width*bpp/8 plus padding bytes at the end of each row
132 unsigned int stride=width*bpp/8;
133 if(width%4==1)
134 stride+=1;
135 if(width%4==2)
136 stride+=2;
137 if(width%4==3)
138 stride+=3;
140 //point file to the beginning of the data
141 fseek(file, fileHeader.bfOffBits, SEEK_SET);
143 //allocate space for the image data
144 data=new unsigned char[stride*height];
145 if(!data)
147 fclose(file);
148 errorLog.OutputError("Unable to allocate memory for %s", filename);
149 return false;
152 //read in the data
153 fread(data, 1, stride*height, file);
155 //close the file
156 fclose(file);
158 //data is in BGR format
159 //swap b and r
160 for(unsigned int row=0; row<height; row++)
162 for(unsigned int i=0; i<width*3; i+=bpp/8)
164 //repeated XOR to swap bytes 0 and 2
165 data[(row*stride)+i] ^= data[(row*stride)+i+2] ^=
166 data[(row*stride)+i] ^= data[(row*stride)+i+2];
170 errorLog.OutputSuccess("Loaded %s correctly.", filename);
171 return true;
174 //Load8BitBMP - load an 8 bit paletted bitmap file
175 bool IMAGE::Load8BitBMP(const char * filename)
177 errorLog.OutputSuccess("Loading %s in Load8bitBMP()", filename);
179 //set bpp and format
180 bpp=24; //after conversion
181 format=GL_RGB;
183 FILE * file; //the texture file
184 BITMAPFILEHEADER fileHeader; //bitmap file header
185 BITMAPINFOHEADER infoHeader; //bitmap info header
187 //open file for reading
188 file=fopen(filename, "rb");
189 if(file==NULL)
191 errorLog.OutputError("Unable to open %s", filename);
192 return false;
195 //read the file header
196 fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file);
198 //check it's a bitmap
199 if(fileHeader.bfType != BITMAP_ID)
201 fclose(file);
202 errorLog.OutputError("%s is not a legal .BMP", filename);
203 return false;
206 //read in the information header
207 fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file);
209 //set size
210 width=infoHeader.biWidth;
211 height=infoHeader.biHeight;
213 //make space for palette
214 unsigned char * palette=new unsigned char[256*4];
215 if(!palette)
217 errorLog.OutputError("Unable to alllocate memory for palette");
218 return false;
221 //load the palette
222 fread(palette, 256*4, 1, file);
224 //point file to the beginning of the data
225 fseek(file, fileHeader.bfOffBits, SEEK_SET);
227 //calculate the stride in bytes between one row and the next
228 unsigned int stride=width;
229 if(width%4 != 0)
230 stride+=4-width%4;
232 //allocate space for color indices
233 unsigned char * indices=new unsigned char[stride*height];
234 if(!indices)
236 errorLog.OutputError("Unable to allocate memory for indices");
237 return false;
240 //load indices
241 fread(indices, 1, stride*height, file);
243 //close the file
244 fclose(file);
246 //allocate space for the image data
247 data=new unsigned char[stride*height*bpp/8];
248 if(!data)
250 fclose(file);
251 errorLog.OutputError("Unable to allocate memory for %s", filename);
252 return false;
255 //calculate the color values - keeping the padding colors
256 for(unsigned int currentRow=0; currentRow<height; currentRow++)
258 for(unsigned int i=0; i<stride; i++)
260 data[(currentRow*stride+i)*3+0]=palette[indices[currentRow*stride+i]*4+2];
261 data[(currentRow*stride+i)*3+1]=palette[indices[currentRow*stride+i]*4+1];
262 data[(currentRow*stride+i)*3+2]=palette[indices[currentRow*stride+i]*4+0];//BGR
266 errorLog.OutputSuccess("Loaded %s correctly.", filename);
267 return true;
276 //LoadPCX - load a .pcx texture - 256 color, paletted
277 bool IMAGE::LoadPCX(const char * filename)
279 errorLog.OutputSuccess("Loading %s in LoadPCX()", filename);
281 //set bpp and format
282 bpp=24;
283 format=GL_RGB;
285 FILE * file;
287 file=fopen(filename, "rb");
288 if(!file)
290 errorLog.OutputError("Unable to open %s", filename);
291 return false;
294 //retrieve header, first 4 bytes, first 2 should be 0x0A0C
295 unsigned short header[2];
296 fread(header, 4, 1, file);
298 if(header[0]!=0x050A)
300 errorLog.OutputError("%s is not a legal .PCX file", filename);
301 fclose(file);
302 return false;
305 //retrieve minimum x value
306 int xMin=fgetc(file); //loword
307 xMin |= fgetc(file) << 8; //hiword
309 //retrieve minimum y value
310 int yMin=fgetc(file); //loword
311 yMin |= fgetc(file) << 8; //hiword
313 //retrieve maximum x value
314 int xMax=fgetc(file); //loword
315 xMax |= fgetc(file) << 8; //hiword
317 //retrieve maximum y value
318 int yMax=fgetc(file); //loword
319 yMax |= fgetc(file) << 8; //hiword
321 //calculate width and height
322 width = xMax-xMin+1;
323 height= yMax-yMin+1;
325 //allocate memory for pixel data (paletted)
326 unsigned char * pixelData=new unsigned char[width*height];
327 if(!pixelData)
329 errorLog.OutputError("Unable to allocate %d bytes for the image data of %s",
330 width*height, filename);
331 fclose(file);
332 return false;
335 //set file pointer to beginning of image data
336 fseek(file, 128, SEEK_SET);
338 //decode and store the pixel data
339 unsigned int index=0;
341 while(index<(width*height))
343 int c = getc(file);
345 if(c>0xBF)
347 int numRepeat = 0x3F & c;
348 c=getc(file);
350 for(int i=0; i<numRepeat; i++)
351 pixelData[index++] = c;
353 else
354 pixelData[index++] = c;
356 fflush(stdout);
359 //allocate memory for the image palette
360 unsigned char * paletteData = new unsigned char[768];
362 //the palette is the last 769 bytes of the file
363 fseek(file, -769, SEEK_END);
365 //retrieve first character, should be equal to 12
366 int c=getc(file);
367 if(c!=12)
369 errorLog.OutputError("%s is not a legal .PCX file - the palette data has an illegal header, %d",
370 filename, c);
371 fclose(file);
372 return false;
375 //read and store the palette
376 fread(paletteData, 1, 768, file);
378 //close the file
379 fclose(file);
381 //allocate memory for the "unpaletted" data
382 data = new unsigned char[width*height*3];
383 if(!data)
385 errorLog.OutputError("Unable to allocate memory for the expanded data of %s", filename);
386 return false;
389 //calculate the "unpaletted" data - "flipping" the texture top-bottom
390 for(unsigned int j=0; j<height; j++)
392 for(unsigned int i=0; i<width; i++)
394 data[3*(j*width+i)] = (unsigned char) paletteData[3*pixelData[(height-1-j)*width+i]];
395 data[3*(j*width+i)+1] = (unsigned char) paletteData[3*pixelData[(height-1-j)*width+i]+1];
396 data[3*(j*width+i)+2] = (unsigned char) paletteData[3*pixelData[(height-1-j)*width+i]+2];
400 errorLog.OutputSuccess("Loaded %s correctly.", filename);
401 return true;
408 //Load a TGA texture
409 bool IMAGE::LoadTGA(const char * filename)
411 unsigned char UncompressedTGAHeader[12]={0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
412 unsigned char CompressedTGAHeader[12]={0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0};
413 unsigned char Uncompressed8BitTGAHeader[12]={0, 1, 1, 0, 0, 0, 1, 24, 0, 0, 0, 0};
415 unsigned char TGAcompare[12]; //Used to compare TGA header
417 FILE * file = fopen(filename, "rb"); //Open the TGA file
419 if( file==NULL ) //Does the file exist?
421 errorLog.OutputError("%s does not exist", filename);
422 return false;
425 //read the header
426 fread(TGAcompare, 1, sizeof(TGAcompare), file);
427 fclose(file);
429 if(memcmp(UncompressedTGAHeader, TGAcompare, sizeof(UncompressedTGAHeader))==0)
431 return LoadUncompressedTrueColorTGA(filename);
433 else if(memcmp(CompressedTGAHeader, TGAcompare, sizeof(CompressedTGAHeader))==0)
435 return LoadCompressedTrueColorTGA(filename);
437 else if(memcmp(Uncompressed8BitTGAHeader, TGAcompare, sizeof(Uncompressed8BitTGAHeader))==0)
439 return LoadUncompressed8BitTGA(filename);
441 else
443 errorLog.OutputError("%s is not a recognised type of TGA", filename);
444 return false;
447 return false;
450 //load an 8 bit uncompressed paletted TGA
451 bool IMAGE::LoadUncompressed8BitTGA(const char * filename)
453 unsigned char TGAHeader[12]={0, 1, 1, 0, 0, 0, 1, 24, 0, 0, 0, 0};
454 unsigned char TGAcompare[12]; //Used to compare TGA header
455 unsigned char header[6]; //First 6 useful bytes of the header
457 errorLog.OutputSuccess("Loading %s in LoadUncompressed8BitTGA()", filename);
459 FILE * file = fopen(filename, "rb"); //Open the TGA file
461 if(file == NULL) //Does the file exist?
463 errorLog.OutputError("%s does not exist.", filename);
464 return false;
467 if( fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)|| //Are there 12 bytes to read?
468 memcmp(TGAHeader, TGAcompare, sizeof(TGAHeader))!=0 || //Is the header correct?
469 fread(header, 1, sizeof(header), file)!=sizeof(header)) //Read next 6 bytes
471 fclose(file); //If anything else failed, close the file
472 errorLog.OutputError("Could not load %s correctly, general failure.", filename);
473 return false;
476 //save data into class member variables
477 width= header[1]*256+header[0]; //determine the image width
478 height= header[3]*256+header[2]; //determine image height
479 bpp= header[4];
481 if( width<=0 || //if width <=0
482 height<=0 || //or height<=0
483 bpp!=8) //bpp not 8
485 fclose(file); //close the file
486 errorLog.OutputError("%s's height or width is less than zero, or the TGA is not 8 bpp.", filename);
487 return false;
490 //set format
491 format=GL_RGB;
493 //make space for palette
494 unsigned char * palette=new unsigned char[256*3];
495 if(!palette)
497 errorLog.OutputError("Unable to allocate memory for palette");
498 return false;
501 //load the palette
502 fread(palette, 256*3, 1, file);
504 //allocate space for color indices
505 unsigned char * indices=new unsigned char[width*height];
506 if(!indices)
508 errorLog.OutputError("Unable to allocate memory for indices");
509 return false;
512 //load indices
513 fread(indices, 1, width*height, file);
515 //close the file
516 fclose(file);
518 //allocate space for the image data
519 data=new unsigned char[width*height*3];
520 if(!data)
522 fclose(file);
523 errorLog.OutputError("Unable to allocate memory for %s", filename);
524 return false;
527 //calculate the color values
528 for(unsigned int currentRow=0; currentRow<height; currentRow++)
530 for(unsigned int i=0; i<width; i++)
532 data[(currentRow*width+i)*3+0]=palette[indices[currentRow*width+i]*3+2];
533 data[(currentRow*width+i)*3+1]=palette[indices[currentRow*width+i]*3+1];
534 data[(currentRow*width+i)*3+2]=palette[indices[currentRow*width+i]*3+0];//BGR
538 errorLog.OutputSuccess("Loaded %s correctly.", filename);
539 return true;
546 //load an uncompressed TGA texture (24 or 32 bpp)
547 bool IMAGE::LoadUncompressedTrueColorTGA(const char * filename)
549 unsigned char TGAheader[12]={0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //Uncompressed TGA header
550 unsigned char TGAcompare[12]; //Used to compare TGA header
551 unsigned char header[6]; //First 6 useful bytes of the header
552 unsigned int bytesPerPixel; //bytes per pixel
553 unsigned int imageSize; //Stores Image size when in RAM
555 errorLog.OutputSuccess("Loading %s in LoadUncompressedTGA()", filename);
557 FILE * file = fopen(filename, "rb"); //Open the TGA file
559 if(file == NULL) //Does the file exist?
561 errorLog.OutputError("%s does not exist.", filename);
562 return false;
565 if( fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)|| //Are there 12 bytes to read?
566 memcmp(TGAheader, TGAcompare, sizeof(TGAheader))!=0 || //Is the header correct?
567 fread(header, 1, sizeof(header), file)!=sizeof(header)) //Read next 6 bytes
569 fclose(file); //If anything else failed, close the file
570 errorLog.OutputError("Could not load %s correctly, general failure.", filename);
571 return false;
574 //save data into class member variables
575 width= header[1]*256+header[0]; //determine the image width
576 height= header[3]*256+header[2]; //determine image height
577 bpp= header[4];
579 if( width<=0 || //if width <=0
580 height<=0 || //or height<=0
581 bpp!=24 && bpp!=32) //bpp not 24 or 32
583 fclose(file); //close the file
584 errorLog.OutputError("%s's height or width is less than zero, or the TGA is not 24 or 32 bpp.", filename);
585 return false;
588 //set format
589 if(bpp == 24)
590 format=GL_RGB;
591 else
592 format=GL_RGBA;
594 bytesPerPixel=bpp/8; //calc bytes per pixel
595 imageSize=width*height*bytesPerPixel; //calc memory required
597 data=new unsigned char[imageSize]; //reserve the memory for the data
599 if( data==NULL) //Does the storage memory exist?
601 errorLog.OutputError("Unable to allocate memory for %s image", filename);
602 fclose(file);
603 return false;
606 //read in the image data
607 if(fread(data, 1, imageSize, file)!=imageSize) //Does the image size match the required?
608 { //If not
609 if(data) //If data loaded
610 delete [] data; //free memory
611 errorLog.OutputError("Could not read %s image data", filename);
612 fclose(file); //close file
613 return false;
616 fclose(file);
618 //data is in BGR format
619 //swap b and r
620 for(int i=0; i<(int)imageSize; i+=bytesPerPixel)
622 //repeated XOR to swap bytes 0 and 2
623 data[i] ^= data[i+2] ^= data[i] ^= data[i+2];
626 errorLog.OutputSuccess("Loaded %s correctly.", filename);
627 return true;
634 //load a compressed TGA texture (24 or 32 bpp)
635 bool IMAGE::LoadCompressedTrueColorTGA(const char * filename)
637 unsigned char TGAheader[12]={0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //Compressed TGA header
638 unsigned char TGAcompare[12]; //Used to compare TGA header
639 unsigned char header[6]; //First 6 useful bytes of the header
640 unsigned int bytesPerPixel; //bytes per pixel
641 unsigned int imageSize; //Stores Image size when in RAM
643 errorLog.OutputSuccess("Loading %s in LoadCompressedTGA()", filename);
645 FILE * file = fopen(filename, "rb"); //Open the TGA file
647 if(file == NULL) //Does the file exist?
649 errorLog.OutputError("%s does not exist.", filename);
650 return false;
653 if( fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)|| //Are there 12 bytes to read?
654 memcmp(TGAheader, TGAcompare, sizeof(TGAheader))!=0 || //Is the header correct?
655 fread(header, 1, sizeof(header), file)!=sizeof(header)) //Read next 6 bytes
657 fclose(file); //If anything else failed, close the file
658 errorLog.OutputError("Could not load %s correctly, general failure.", filename);
659 return false;
662 //save data into class member variables
663 width= header[1]*256+header[0]; //determine the image width
664 height= header[3]*256+header[2]; //determine image height
665 bpp= header[4];
667 if( width<=0 || //if width <=0
668 height<=0 || //or height<=0
669 bpp!=24 && bpp!=32) //bpp not 24 or 32
671 fclose(file); //close the file
672 errorLog.OutputError("%s's height or width is less than zero, or the TGA is not 24 or 32 bpp.", filename);
673 return false;
676 //set format
677 if(bpp == 24)
678 format=GL_RGB;
679 else
680 format=GL_RGBA;
682 bytesPerPixel=bpp/8; //calc bytes per pixel
683 imageSize=width*height*bytesPerPixel; //calc memory required
685 data=new unsigned char[imageSize]; //reserve the memory for the data
686 if(!data) //Does the storage memory exist?
688 errorLog.OutputError("Unable to allocate memory for %s image", filename);
689 fclose(file);
690 return false;
693 //read in the image data
694 int pixelCount = height*width;
695 int currentPixel= 0;
696 int currentByte = 0;
697 unsigned char * colorBuffer=new unsigned char[bytesPerPixel];
701 unsigned char chunkHeader=0;
703 if(fread(&chunkHeader, sizeof(unsigned char), 1, file) == 0)
705 errorLog.OutputError("Could not read RLE chunk header");
706 if(file)
707 fclose(file);
708 if(data)
709 delete [] data;
710 return false;
713 if(chunkHeader<128) //Read raw color values
715 chunkHeader++;
717 for(short counter=0; counter<chunkHeader; counter++)
719 if(fread(colorBuffer, 1, bytesPerPixel, file) != bytesPerPixel)
721 errorLog.OutputError("Unable to read %s image data", filename);
723 if(file)
724 fclose(file);
726 if(colorBuffer)
727 delete [] colorBuffer;
729 if(data)
730 delete [] data;
732 return false;
735 //transfer pixel color to data (swapping r and b values)
736 data[currentByte] = colorBuffer[2];
737 data[currentByte+1] = colorBuffer[1];
738 data[currentByte+2] = colorBuffer[0];
740 if(bytesPerPixel==4)
741 data[currentByte+3]=colorBuffer[3];
743 currentByte+=bytesPerPixel;
744 currentPixel++;
746 if(currentPixel > pixelCount)
748 errorLog.OutputError("Too many pixels read");
749 if(file)
750 fclose(file);
751 if(colorBuffer)
752 delete [] colorBuffer;
753 if(data)
754 delete [] data;
755 return false;
759 else //chunkHeader>=128
761 chunkHeader-=127;
763 if(fread(colorBuffer, 1, bytesPerPixel, file) != bytesPerPixel)
765 errorLog.OutputError("Unable to read %s image data", filename);
767 if(file)
768 fclose(file);
769 if(colorBuffer)
770 delete [] colorBuffer;
771 if(data)
772 delete [] data;
773 return false;
776 for(short counter=0; counter<chunkHeader; counter++)
778 //transfer pixel color to data (swapping r and b values)
779 data[currentByte] = colorBuffer[2];
780 data[currentByte+1] = colorBuffer[1];
781 data[currentByte+2] = colorBuffer[0];
783 if(bytesPerPixel==4)
784 data[currentByte+3]=colorBuffer[3];
786 currentByte+=bytesPerPixel;
787 currentPixel++;
789 if(currentPixel > pixelCount)
791 errorLog.OutputError("Too many pixels read");
792 if(file)
793 fclose(file);
794 if(colorBuffer)
795 delete [] colorBuffer;
796 if(data)
797 delete [] data;
798 return false;
802 }while(currentPixel<pixelCount);
804 fclose(file);
806 errorLog.OutputSuccess("Loaded %s correctly.", filename);
807 return true;
822 //load in an 8 bit greyscale TGA as an alpha channel
823 bool IMAGE::LoadAlphaTGA(const char * filename)
825 unsigned char TGAHeader[12]={0, 1, 1, 0, 0, 0, 1, 24, 0, 0, 0, 0};
826 unsigned char TGAcompare[12]; //Used to compare TGA header
827 unsigned char header[6]; //First 6 useful bytes of the header
829 errorLog.OutputSuccess("Loading %s in LoadAlphaTGA()", filename);
831 if(!(format==GL_RGB || format==GL_RGBA))
833 errorLog.OutputError("Can only load an alpha channel to RGB / RGBA format images. %s caused error", filename);
834 return false;
837 FILE * file = fopen(filename, "rb"); //Open the TGA file
839 if(file == NULL) //Does the file exist?
841 errorLog.OutputError("%s does not exist.", filename);
842 return false;
845 if( fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)|| //Are there 12 bytes to read?
846 memcmp(TGAHeader, TGAcompare, sizeof(TGAHeader))!=0 || //Is the header correct?
847 fread(header, 1, sizeof(header), file)!=sizeof(header)) //Read next 6 bytes
849 fclose(file); //If anything else failed, close the file
850 errorLog.OutputError("Could not load %s correctly, general failure.", filename);
851 return false;
854 //save data into class member variables
855 unsigned int alphaWidth= header[1]*256+header[0]; //determine the image width
856 unsigned int alphaHeight= header[3]*256+header[2]; //determine image height
857 int alphaBpp= header[4];
859 if( alphaWidth<=0 || //if width <=0
860 alphaHeight<=0 || //or height<=0
861 alphaBpp!=8) //bpp not 8
863 fclose(file); //close the file
864 errorLog.OutputError("%s's height or width is less than zero, or the TGA is not 8 bpp.", filename);
865 return false;
868 //check it is the same size as the image
869 if(alphaWidth!=width || alphaHeight!=height)
871 errorLog.OutputError("%s is not the same size as the color texture", filename);
872 return false;
875 //make space for palette
876 unsigned char * palette=new unsigned char[256*3];
877 if(!palette)
879 errorLog.OutputError("Unable to allocate memory for palette");
880 return false;
883 //load the palette
884 fread(palette, 256*3, 1, file);
886 //we dont use the palette
887 delete [] palette;
888 palette=NULL;
890 //allocate space for alpha values
891 unsigned char * values=new unsigned char[width*height];
892 if(!values)
894 errorLog.OutputError("Unable to allocate memory for alpha values");
895 return false;
898 //load indices
899 fread(values, 1, alphaWidth*alphaHeight, file);
901 //close the file
902 fclose(file);
904 //now put in the alpha data
905 if(format==GL_RGBA)
907 for(unsigned int i=0; i<width*height; i++)
909 data[i*4+3]=values[i];
912 else if(format==GL_RGB)
914 unsigned char * tempData=new unsigned char[width*height*4];
915 if(!tempData)
917 errorLog.OutputError("Unable to allocate memory for Temporary Data");
918 return false;
921 for(unsigned int i=0; i<width*height; i++)
923 tempData[i*4+0]=data[i*3+0];
924 tempData[i*4+1]=data[i*3+1];
925 tempData[i*4+2]=data[i*3+2];
926 tempData[i*4+3]=values[i];
929 //update member variables
930 bpp=32;
931 format=GL_RGBA;
933 if(data)
934 delete [] data;
935 data=tempData;
938 errorLog.OutputSuccess("Loaded %s correctly.", filename);
939 return true;
943 void IMAGE::FlipVertically()
945 //dont flip zero or 1 height images
946 if(height==0 || height==1)
947 return;
949 int rowsToSwap=0;
950 //see how many rows to swap
951 if(height%2==1)
952 rowsToSwap=(height-1)/2;
953 else
954 rowsToSwap=height/2;
956 //create space for a temporary row
957 GLubyte * tempRow=new GLubyte[width*bpp/8];
958 if(!tempRow)
960 errorLog.OutputError("Unable to flip image, unable to create space for temporary row");
961 return;
964 //loop through rows to swap
965 for(int i=0; i<rowsToSwap; ++i)
967 //copy row i into temp
968 memcpy(tempRow, &data[i*width*bpp/8], width*bpp/8);
969 //copy row height-i-1 to row i
970 memcpy(&data[i*width*bpp/8], &data[(height-i-1)*width*bpp/8], width*bpp/8);
971 //copy temp into row height-i-1
972 memcpy(&data[(height-i-1)*width*bpp/8], tempRow, width*bpp/8);
975 //free tempRow
976 if(tempRow)
977 delete [] tempRow;
978 tempRow=NULL;