TGALoader.cpp
上传用户:arsena_zhu
上传日期:2022-07-12
资源大小:399k
文件大小:16k
源码类别:

OpenGL

开发平台:

Visual C++

  1. /********************************************************************************
  2. * Name: TGA.cpp *
  3. * Header: tga.h *
  4. * Purpose: Load Compressed and Uncompressed TGA files *
  5. * Functions: LoadTGA(TGATexture * texture, char * filename) *
  6. * LoadCompressedTGA(TGATexture * texture, char * filename, FILE * fTGA) *
  7. * LoadUncompressedTGA(TGATexture * texture, char * filename, FILE * fTGA)*
  8. ********************************************************************************/
  9. #include "main.h"
  10. /********************************************************************************
  11. * name : LoadTGA(TGATexture * texture, char * filename) *
  12. * function: Open and test the file to make sure it is a valid TGA file *
  13. * parems: texture, pointer to a Texture structure *
  14. * filename, string pointing to file to open *
  15. ********************************************************************************/
  16. /*******************************************************************************
  17. * TGA LOADER
  18. *******************************************************************************/
  19. bool LoadTGA(TGATexture *tgatex, char *filename)
  20. {
  21. strcpy(tgatex->filename, filename);
  22. GLubyte uTGAcompare[12] = {0,0,2, 0,0,0,0,0,0,0,0,0}; // Uncompressed TGA Header
  23. tgatex->file = fopen(tgatex->filename, "rb"); // Open file for reading
  24. if(tgatex->file == NULL) // If it didn't open....
  25. {
  26. MessageBox(NULL, "Could not open texture file", filename, MB_OK); // Display an error message
  27. return false; // Exit function
  28. }
  29. fread(tgatex->versionHeader, 1, sizeof(tgatex->versionHeader), tgatex->file);
  30. if (memcmp(uTGAcompare, tgatex->versionHeader, sizeof(tgatex->versionHeader)) == 0) // See if header matches the predefined header of 
  31. {
  32. fread(tgatex->header, 1, sizeof(tgatex->header), tgatex->file);
  33. if(!LoadUncompressedTGAData(tgatex))
  34. {
  35. MessageBox(NULL, "error while loading image", "error", MB_OK); // Display an error
  36. return false;
  37. }
  38. }
  39. else // If header matches neither type
  40. {
  41. MessageBox(NULL, "bad TGA file", "Invalid Image", MB_OK); // Display an error
  42. return false; // Exit function
  43. }
  44. fclose(tgatex->file);
  45. return true;
  46. }
  47. GLuint LoadTGAIntoGL(char *filename)
  48. {
  49. ////////////////////////////////////////////////////////////////////////////////
  50. // !! THIS NEEDS TO BE FIXED !!
  51. ////////////////////////////////////////////////////////////////////////////////
  52. char brm[128];
  53. char fname[128];
  54. char file_name[128];
  55. strcpy(file_name, filename);
  56. // MessageBox(NULL, file_name, "filename",MB_OK|MB_ICONEXCLAMATION);
  57. for (int i=0; i < 128 ; i++)
  58. {
  59. fname[i]=file_name[i+1];
  60. }
  61. // MessageBox(NULL, fname, "fname",MB_OK|MB_ICONEXCLAMATION);
  62. strcpy(brm, "data\models");
  63. strcat(brm, fname);
  64. // MessageBox(NULL, brm, "fname",MB_OK|MB_ICONEXCLAMATION);
  65. ////////////////////////////////////////////////////////////////////////////////
  66. return LoadTGAIntoGL(brm, NULL, NULL);
  67. }
  68. GLuint LoadTGAIntoGL(char *filename, int *get_x, int *get_y) // Load a TGA file
  69. {
  70. TGATexture t;
  71. GLubyte uTGAcompare[12] = {0,0,2, 0,0,0,0,0,0,0,0,0}; // Uncompressed TGA Header
  72. GLubyte cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0}; // Compressed TGA Header
  73. t.file = fopen(t.filename, "rb"); // Open file for reading
  74. if(t.file == NULL) // If it didn't open....
  75. {
  76. MessageBox(NULL, "Could not open texture file", filename, MB_OK); // Display an error message
  77. return false; // Exit function
  78. }
  79. if(fread(t.header, sizeof(t.header), 1, t.file) == 0) // Attempt to read 12 byte header from file
  80. {
  81. MessageBox(NULL, "Could not read file header", "ERROR", MB_OK); // If it fails, display an error message 
  82. if(t.file != NULL) // Check to seeiffile is still open
  83. {
  84. fclose(t.file); // If it is, close it
  85. }
  86. return false; // Exit function
  87. }
  88. if(memcmp(uTGAcompare, &t.header, sizeof(t.header)) == 0) // See if header matches the predefined header of 
  89. { // an Uncompressed TGA image
  90. LoadUncompressedTGAData(&t); // If so, jump to Uncompressed TGA loading code
  91. }
  92. else if(memcmp(cTGAcompare, &t.header, sizeof(t.header)) == 0) // See if header matches the predefined header of
  93. { // an RLE compressed TGA image
  94. LoadCompressedTGAData(&t); // If so, jump to Compressed TGA loading code
  95. }
  96. else // If header matches neither type
  97. {
  98. MessageBox(NULL, "TGA file be type 2 or type 10 ", "Invalid Image", MB_OK); // Display an error
  99. return false; // Exit function
  100. }
  101. fclose(t.file);
  102. if (get_x != NULL && get_y != NULL)
  103. {
  104. *get_x = t.width;
  105. *get_y = t.height;
  106. }
  107. // textures on models were vertically inverted without this
  108. // (by psycho ;] (proud of this unique 'low level' function, lol))
  109. // by the way, it's inverted only on models, not in normal gui pictures :/
  110. if (t.bpp == 24 && get_x == NULL && get_y == NULL)
  111. {
  112. TGATexture tex;
  113. tex.image = (GLubyte *)malloc(t.size);
  114. int yy = t.height;
  115. int xx = t.width*3;
  116. for(GLuint i=0; i<yy; i++)
  117. {
  118. for(GLuint j=0; j<xx; j+=(t.bpp/8))
  119. {
  120. tex.image[ (i*xx) + j ] = t.image[ (yy-1-i)*xx + j ];
  121. tex.image[ (i*xx) + j + 1] = t.image[ (yy-1-i)*xx + j + 1];
  122. tex.image[ (i*xx) + j + 2] = t.image[ (yy-1-i)*xx + j + 2];
  123. }
  124. }
  125. delete [] t.image;
  126. t.image = tex.image;
  127. }
  128. return GenerateTexture(&t);
  129. }
  130. int GenerateTexture(TGATexture *t)
  131. {
  132. glGenTextures(1, &t->texID);
  133. glBindTexture(GL_TEXTURE_2D, t->texID);
  134. glTexImage2D(GL_TEXTURE_2D, 0, t->bpp / 8, t->width, t->height, 0,
  135. t->type, GL_UNSIGNED_BYTE, t->image);
  136. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  137. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  138. return t->texID;
  139. }
  140. bool LoadUncompressedTGAData(TGATexture *t) // Load an uncompressed TGA (note, much of this code is based on NeHe's 
  141. { // TGA Loading code nehe.gamedev.net)
  142. /*
  143. if(fread(t->header, sizeof(t->header), 1, t->file) == 0) // Read TGA header
  144. {
  145. MessageBox(NULL, "Could not read info header", "ERROR", MB_OK); // Display error
  146. if(t->file != NULL) // if file is still open
  147. {
  148. fclose(t->file); // Close it
  149. }
  150. return false; // Return failular
  151. }
  152. */
  153. t->width  = t->header[1] * 256 + t->header[0]; // Determine The TGA Width (highbyte*256+lowbyte)
  154. t->height = t->header[3] * 256 + t->header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
  155. t->bpp = t->header[4]; // Determine the bits per pixel
  156. if((t->width <= 0) || (t->height <= 0) || ((t->bpp != 24) && (t->bpp !=32))) // Make sure all information is valid
  157. {
  158. MessageBox(NULL, "Invalid texture information", "ERROR", MB_OK); // Display Error
  159. if(t->file != NULL) // Check if file is still open
  160. {
  161. fclose(t->file); // If so, close it
  162. }
  163. return false; // Return failed
  164. }
  165. if(t->bpp == 24) // If the BPP of the image is 24...
  166. t->type = GL_RGB; // Set Image type to GL_RGB
  167. else // Else if its 32 BPP
  168. t->type = GL_RGBA; // Set image type to GL_RGBA
  169. t->size = (t->bpp/8 * t->width * t->height); // Compute the total amout ofmemory needed to store data
  170. t->image = (GLubyte *)malloc(t->size); // Allocate that much memory
  171. if(t->image == NULL) // If no space was allocated
  172. {
  173. MessageBox(NULL, "Could not allocate memory for image", "ERROR", MB_OK); // Display Error
  174. fclose(t->file); // Close the file
  175. return false; // Return failed
  176. }
  177. if(fread(t->image, 1, t->size, t->file) != t->size) // Attempt to read image data
  178. {
  179. MessageBox(NULL, "Could not read image data", "ERROR", MB_OK); // Display Error
  180. if(t->image != NULL) // If imagedata has data in it
  181. {
  182. free(t->image); // Delete data from memory
  183. }
  184. fclose(t->file); // Close file
  185. return false; // Return failed
  186. }
  187. // Byte Swapping Optimized By Steve Thomas
  188. for(GLuint cswap = 0; cswap < t->size; cswap += t->bpp/8)
  189. {
  190. t->image[cswap] ^= t->image[cswap+2] ^=
  191. t->image[cswap] ^= t->image[cswap+2];
  192. }
  193. fclose(t->file); // Close file
  194. return true; // Return success
  195. }
  196. bool LoadCompressedTGAData(TGATexture *t) // Load COMPRESSED TGAs
  197. if(fread(t->header, sizeof(t->header), 1, t->file) == 0) // Attempt to read header
  198. {
  199. MessageBox(NULL, "Could not read info header", "ERROR", MB_OK); // Display Error
  200. if(t->file != NULL) // If file is open
  201. {
  202. fclose(t->file); // Close it
  203. }
  204. return false; // Return failed
  205. }
  206. t->width  = t->header[1] * 256 + t->header[0]; // Determine The TGA Width (highbyte*256+lowbyte)
  207. t->height = t->header[3] * 256 + t->header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
  208. t->bpp = t->header[4]; // Determine Bits Per Pixel
  209. if((t->width <= 0) || (t->height <= 0) || ((t->bpp != 24) && (t->bpp !=32))) //Make sure all texture info is ok
  210. {
  211. MessageBox(NULL, "Invalid texture information", "ERROR", MB_OK); // If it isnt...Display error
  212. if(t->file != NULL) // Check if file is open
  213. {
  214. fclose(t->file); // Ifit is, close it
  215. }
  216. return false; // Return failed
  217. }
  218. if(t->bpp == 24) // If the BPP of the image is 24...
  219. t->type = GL_RGB; // Set Image type to GL_RGB
  220. else // Else if its 32 BPP
  221. t->type = GL_RGBA; // Set image type to GL_RGBA
  222. t->size = (t->bpp/8 * t->width * t->height); // Compute amout of memory needed to store image
  223. t->image = (GLubyte *)malloc(t->size); // Allocate that much memory
  224. if(t->image == NULL) // If it wasnt allocated correctly..
  225. {
  226. MessageBox(NULL, "Could not allocate memory for image", "ERROR", MB_OK); // Display Error
  227. fclose(t->file); // Close file
  228. return false; // Return failed
  229. }
  230. GLuint pixelcount = t->height * t->width; // Nuber of pixels in the image
  231. GLuint currentpixel = 0; // Current pixel being read
  232. GLuint currentbyte = 0; // Current byte 
  233. GLubyte * colorbuffer = (GLubyte *)malloc(t->bpp/8); // Storage for 1 pixel
  234. do
  235. {
  236. GLubyte chunkheader = 0; // Storage for "chunk" header
  237. if(fread(&chunkheader, sizeof(GLubyte), 1, t->file) == 0) // Read in the 1 byte header
  238. {
  239. MessageBox(NULL, "Could not read RLE header", "ERROR", MB_OK); // Display Error
  240. if(t->file != NULL) // If file is open
  241. {
  242. fclose(t->file); // Close file
  243. }
  244. if(t->image != NULL) // If there is stored image data
  245. {
  246. free(t->image); // Delete image data
  247. }
  248. return false; // Return failed
  249. }
  250. if(chunkheader < 128) // If the ehader is < 128, it means the that is the number of RAW color packets minus 1
  251. { // that follow the header
  252. chunkheader++; // add 1 to get number of following color values
  253. for(short counter = 0; counter < chunkheader; counter++) // Read RAW color values
  254. {
  255. if(fread(colorbuffer, 1, t->bpp/8, t->file) != t->bpp/8) // Try to read 1 pixel
  256. {
  257. MessageBox(NULL, "Could not read image data", "ERROR", MB_OK); // IF we cant, display an error
  258. if(t->file != NULL) // See if file is open
  259. {
  260. fclose(t->file); // If so, close file
  261. }
  262. if(colorbuffer != NULL) // See if colorbuffer has data in it
  263. {
  264. free(colorbuffer); // If so, delete it
  265. }
  266. if(t->image != NULL) // See if there is stored Image data
  267. {
  268. free(t->image); // If so, delete it too
  269. }
  270. return false; // Return failed
  271. }
  272. // write to memory
  273. t->image[currentbyte ] = colorbuffer[2];     // Flip R and B vcolor values around in the process 
  274. t->image[currentbyte + 1 ] = colorbuffer[1];
  275. t->image[currentbyte + 2 ] = colorbuffer[0];
  276. if(t->bpp/8 == 4) // if its a 32 bpp image
  277. {
  278. t->image[currentbyte + 3] = colorbuffer[3]; // copy the 4th byte
  279. }
  280. currentbyte += t->bpp/8; // Increase thecurrent byte by the number of bytes per pixel
  281. currentpixel++; // Increase current pixel by 1
  282. if(currentpixel > pixelcount) // Make sure we havent read too many pixels
  283. {
  284. MessageBox(NULL, "Too many pixels read", "ERROR", MB_OK | MB_ICONERROR ); // if there is too many... Display an error!
  285. if(t->file != NULL) // If there is a file open
  286. {
  287. fclose(t->file); // Close file
  288. }
  289. if(colorbuffer != NULL) // If there is data in colorbuffer
  290. {
  291. free(colorbuffer); // Delete it
  292. }
  293. if(t->image != NULL) // If there is Image data
  294. {
  295. free(t->image); // delete it
  296. }
  297. return false; // Return failed
  298. }
  299. }
  300. }
  301. else // chunkheader > 128 RLE data, next color reapeated chunkheader - 127 times
  302. {
  303. chunkheader -= 127; // Subteact 127 to get rid of the ID bit
  304. if(fread(colorbuffer, 1, t->bpp/8, t->file) != t->bpp/8) // Attempt to read following color values
  305. {
  306. MessageBox(NULL, "Could not read from file", "ERROR", MB_OK); // If attempt fails.. Display error (again)
  307. if(t->file != NULL) // If thereis a file open
  308. {
  309. fclose(t->file); // Close it
  310. }
  311. if(colorbuffer != NULL) // If there is data in the colorbuffer
  312. {
  313. free(colorbuffer); // delete it
  314. }
  315. if(t->image != NULL) // If thereis image data
  316. {
  317. free(t->image); // delete it
  318. }
  319. return false; // return failed
  320. }
  321. for(short counter = 0; counter < chunkheader; counter++) // copy the color into the image data as many times as dictated 
  322. { // by the header
  323. t->image[currentbyte ] = colorbuffer[2]; // switch R and B bytes areound while copying
  324. t->image[currentbyte + 1 ] = colorbuffer[1];
  325. t->image[currentbyte + 2 ] = colorbuffer[0];
  326. if(t->bpp/8 == 4) // If TGA images is 32 bpp
  327. {
  328. t->image[currentbyte + 3] = colorbuffer[3]; // Copy 4th byte
  329. }
  330. currentbyte += t->bpp/8; // Increase current byte by the number of bytes per pixel
  331. currentpixel++; // Increase pixel count by 1
  332. if(currentpixel > pixelcount) // Make sure we havent written too many pixels
  333. {
  334. MessageBox(NULL, "Too many pixels read", "ERROR", MB_OK | MB_ICONERROR ); // if there is too many... Display an error!
  335. if(t->file != NULL) // If there is a file open
  336. {
  337. fclose(t->file); // Close file
  338. }
  339. if(colorbuffer != NULL) // If there is data in colorbuffer
  340. {
  341. free(colorbuffer); // Delete it
  342. }
  343. if(t->image != NULL) // If there is Image data
  344. {
  345. free(t->image); // delete it
  346. }
  347. return false; // Return failed
  348. }
  349. }
  350. }
  351. }
  352. while(currentpixel < pixelcount); // Loop while there are still pixels left
  353. fclose(t->file); // Close the file
  354. return true; // return success
  355. }