Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/images/importer/material.cc @ 3094

Last change on this file since 3094 was 3094, checked in by bensch, 19 years ago

orxonox/branches/images: importing uncompressed TGA-files

File size: 25.5 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14
15   TGA-code: borrowed from nehe-Tutorials
16*/
17
18#include "material.h"
19
20/**
21   \brief creates a default Material with no Name
22   normally you call this to create a material List (for an obj-file) and then append with addMaterial()
23*/
24Material::Material()
25{
26  init();
27 
28  setName ("");
29}
30
31/**
32   \brief creates a Material.
33   \param mtlName Name of the Material to be added to the Material List
34*/
35Material::Material (char* mtlName)
36{
37  init();
38 
39  setName (mtlName);
40}
41
42/**
43    \brief deletes a Material
44*/
45Material::~Material()
46{
47  if (name)
48    delete []name;
49  if (diffuseTextureSet)
50    glDeleteTextures (1, &diffuseTexture);
51  if (verbose >= 2)
52    printf ("delete Material %s.\n", name);
53  if (nextMat != NULL)
54    delete nextMat;
55}
56
57/**
58   \brief adds a new Material to the List.
59   this Function will append a new Material to the end of a Material List.
60   \param mtlName The name of the Material to be added.
61*/
62Material* Material::addMaterial(char* mtlName)
63{
64  if (verbose >=2)
65    printf ("adding Material %s.\n", mtlName);
66  Material* newMat = new Material(mtlName);
67  Material* tmpMat = this;
68  while (tmpMat->nextMat != NULL)
69    {
70      tmpMat = tmpMat->nextMat;
71    }
72  tmpMat->nextMat = newMat;
73  return newMat;
74 
75}
76
77/**
78   \brief initializes a new Material with its default Values
79*/
80void Material::init(void)
81{
82  if (verbose >= 3)
83    printf ("initializing new Material.\n");
84  nextMat = NULL;
85
86  setIllum(1);
87  setDiffuse(0,0,0);
88  setAmbient(0,0,0);
89  setSpecular(.5,.5,.5);
90  setShininess(2.0);
91  setTransparency(0.0);
92
93  diffuseTextureSet = false;
94  ambientTextureSet = false;
95  specularTextureSet = false;
96
97 
98}
99
100/**
101   \brief Search for a Material called mtlName
102   \param mtlName the Name of the Material to search for
103   \returns Material named mtlName if it is found. NULL otherwise.
104*/
105Material* Material::search (char* mtlName)
106{
107  if (verbose >=3)
108    printf ("Searching for material %s", mtlName);
109  Material* searcher = this;
110  while (searcher != NULL)
111    {
112      if (verbose >= 3)
113        printf (".");
114      if (!strcmp (searcher->getName(), mtlName))
115        {
116          if (verbose >= 3)
117            printf ("found.\n");
118          return searcher;
119        }
120      searcher = searcher->nextMat;
121    }
122  if (verbose >=3)
123    printf ("not found\n");
124  return NULL;
125}
126
127/**
128   \brief sets the material with which the following Faces will be painted
129*/
130bool Material::select (void)
131{
132  // setting diffuse color
133  //  glColor3f (diffuse[0], diffuse[1], diffuse[2]);
134  glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
135
136  // setting ambient color
137  glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
138
139  // setting up Sprecular
140  glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
141
142  // setting up Shininess
143  glMaterialf(GL_FRONT, GL_SHININESS, shininess);
144 
145  // setting illumination Model
146  if (illumModel == 1)
147    glShadeModel(GL_FLAT);
148  else if (illumModel >= 2)
149    glShadeModel(GL_SMOOTH);
150
151  if (diffuseTextureSet)
152    glBindTexture(GL_TEXTURE_2D, diffuseTexture);
153  else
154    glBindTexture(GL_TEXTURE_2D, 0);
155 
156}
157
158
159/**
160   \brief Set the Name of the Material. (Important for searching)
161   \param mtlName the Name of the Material to be set.
162*/ 
163void Material::setName (char* mtlName)
164{
165  if (verbose >= 3)
166    printf("setting Material Name to %s.\n", mtlName);
167  name = new char [strlen(mtlName)];
168  strcpy(name, mtlName);
169  //  printf ("adding new Material: %s, %p\n", this->getName(), this);
170
171}
172/**
173   \returns The Name of The Material
174*/
175char* Material::getName (void)
176{
177  return name;
178}
179
180/**
181   \brief Sets the Material Illumination Model.
182   \brief illu illumination Model in int form
183*/
184void Material::setIllum (int illum)
185{
186  if (verbose >= 3)
187    printf("setting illumModel of Material %s to %i", name, illum);
188  illumModel = illum;
189  //  printf ("setting illumModel to: %i\n", illumModel);
190}
191/**
192   \brief Sets the Material Illumination Model.
193   \brief illu illumination Model in char* form
194*/void Material::setIllum (char* illum)
195{
196  setIllum (atoi(illum));
197}
198
199/**
200   \brief Sets the Material Diffuse Color.
201   \param r Red Color Channel.
202   \param g Green Color Channel.
203   \param b Blue Color Channel.
204*/
205void Material::setDiffuse (float r, float g, float b)
206{
207  if (verbose >= 3)
208    printf ("setting Diffuse Color of Material %s to r=%f g=%f b=%f.\n", name, r, g, b);
209  diffuse[0] = r;
210  diffuse[1] = g;
211  diffuse[2] = b; 
212  diffuse[3] = 1.0;
213
214}
215/**
216   \brief Sets the Material Diffuse Color.
217   \param rgb The red, green, blue channel in char format (with spaces between them)
218*/
219void Material::setDiffuse (char* rgb)
220{
221  char r[20],g[20],b[20];
222  sscanf (rgb, "%s %s %s", r, g, b);
223  setDiffuse (atof(r), atof(g), atof(b));
224}
225
226/**
227   \brief Sets the Material Ambient Color.
228   \param r Red Color Channel.
229   \param g Green Color Channel.
230   \param b Blue Color Channel.
231*/
232void Material::setAmbient (float r, float g, float b)
233{
234  if (verbose >=3)
235    printf ("setting Ambient Color of Material %s to r=%f g=%f b=%f.\n", name, r, g, b);
236  ambient[0] = r;
237  ambient[1] = g;
238  ambient[2] = b;
239  ambient[3] = 1.0;
240}
241/**
242   \brief Sets the Material Ambient Color.
243   \param rgb The red, green, blue channel in char format (with spaces between them)
244*/
245void Material::setAmbient (char* rgb)
246{
247  char r[20],g[20],b[20];
248  sscanf (rgb, "%s %s %s", r, g, b);
249  setAmbient (atof(r), atof(g), atof(b));
250}
251
252/**
253   \brief Sets the Material Specular Color.
254   \param r Red Color Channel.
255   \param g Green Color Channel.
256   \param b Blue Color Channel.
257*/
258void Material::setSpecular (float r, float g, float b)
259{
260  if (verbose >= 3)
261    printf ("setting Specular Color of Material %s to r=%f g=%f b=%f.\n", name, r, g, b);
262  specular[0] = r;
263  specular[1] = g;
264  specular[2] = b;
265  specular[3] = 1.0;
266 }
267/**
268   \brief Sets the Material Specular Color.
269   \param rgb The red, green, blue channel in char format (with spaces between them)
270*/
271void Material::setSpecular (char* rgb)
272{
273  char r[20],g[20],b[20];
274  sscanf (rgb, "%s %s %s", r, g, b);
275  setSpecular (atof(r), atof(g), atof(b));
276}
277
278/**
279   \brief Sets the Material Shininess.
280   \param shini stes the Shininess from float.
281*/
282void Material::setShininess (float shini)
283{
284  shininess = shini;
285}
286/**
287   \brief Sets the Material Shininess.
288   \param shini stes the Shininess from char*.
289*/
290void Material::setShininess (char* shini)
291{
292  setShininess (atof(shini));
293}
294
295/**
296   \brief Sets the Material Transparency.
297   \param trans stes the Transparency from int.
298*/
299void Material::setTransparency (float trans)
300{
301  if (verbose >= 3)
302    printf ("setting Transparency of Material %s to %f.\n", name, trans);
303  transparency = trans;
304}
305/**
306   \brief Sets the Material Transparency.
307   \param trans stes the Transparency from char*.
308*/
309void Material::setTransparency (char* trans)
310{
311  char tr[20];
312  sscanf (trans, "%s", tr);
313  setTransparency (atof(tr));
314}
315
316// MAPPING //
317
318/**
319   \brief Sets the Materials Diffuse Map
320   \param dMap the Name of the Image to Use
321*/
322void Material::setDiffuseMap(char* dMap)
323{
324  if (verbose>=2)
325    printf ("setting Diffuse Map %s\n", dMap);
326
327  //  diffuseTextureSet = loadBMP(dMap, &diffuseTexture);
328  diffuseTextureSet = loadImage(dMap, &diffuseTexture);
329
330}
331
332/**
333   \brief Sets the Materials Ambient Map
334   \param aMap the Name of the Image to Use
335*/
336void Material::setAmbientMap(char* aMap)
337{
338  SDL_Surface* ambientMap;
339
340}
341
342/**
343   \brief Sets the Materials Specular Map
344   \param sMap the Name of the Image to Use
345*/
346void Material::setSpecularMap(char* sMap)
347{
348  SDL_Surface* specularMap;
349
350}
351
352/**
353   \brief Sets the Materials Bumpiness
354   \param bump the Name of the Image to Use
355*/
356void Material::setBump(char* bump)
357{
358
359}
360
361bool Material::loadTexToGL (Image* pImage, GLuint* texture)
362{
363  glGenTextures(1, texture);
364  glBindTexture(GL_TEXTURE_2D, *texture);
365  /* not Working, and not needed.
366  glTexImage2D( GL_TEXTURE_2D, 0, 3, width,
367                height, 0, GL_BGR,
368                GL_UNSIGNED_BYTE, map->pixels );
369  */ 
370  gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pImage->width, pImage->height, GL_RGB, GL_UNSIGNED_BYTE, pImage->data);
371 
372  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
373  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); 
374}
375
376
377
378/**
379   \brief Makes the Programm ready to Read-in a texture-File
380   1. Checks what type of Image should be imported
381   2. ToDO: Checks where to find the Image
382*/
383bool Material::loadImage(char* imageName, GLuint* texture)
384{
385  if (!strncmp(imageName+strlen(imageName)-4, ".bmp", 4))
386    {
387      if (verbose >=2)
388        printf ("Requested bmp-image. Trying to Import.\n");
389      return loadBMP(imageName, texture);
390    }
391
392  else if (!strncmp(imageName+strlen(imageName)-4, ".jpg", 4) || !strncmp(imageName+strlen(imageName)-5, ".jpg", 5))
393    {
394      if (verbose >=2)
395        printf ("Requested jpeg-image. Trying to Import\n");
396      return loadJPG(imageName, texture);
397    }
398  else if (!strncmp(imageName+strlen(imageName)-4, ".tga", 4))
399    {
400      if (verbose >=2)
401        printf ("Requested tga-image. Trying to Import\n");
402      return loadTGA(imageName, texture);
403    }
404  else
405    {
406      if (verbose >=1)
407        printf ("Requested Image was not recognized in its type. (Maybe a type-Cast-error.)\n FileName: %s", imageName);
408      return false;
409    }
410
411}
412
413/**
414   \brief reads in a Windows BMP-file, and imports it to openGL.
415   \param bmpName The name of the Image to load.
416   \param texture A pointer to the Texture which should be read to.
417*/
418bool Material::loadBMP (char* bmpName, GLuint* texture)
419{
420  Image* pImage = new Image;
421  FILE *file;
422  unsigned long size;                 // size of the image in bytes.
423  unsigned long i;                    // standard counter.
424  unsigned short int planes;          // number of planes in image (must be 1)
425  unsigned short int bpp;             // number of bits per pixel (must be 24)
426  GLuint temp;                          // temporary color storage for bgr-rgb conversion.
427
428  // make sure the file is there.
429  if ((file = fopen(bmpName, "rb"))==NULL)
430    {
431      if (verbose >=1)
432        printf("File Not Found : %s\n",bmpName);
433      return false;
434    }
435  // seek through the bmp header, up to the width/height:
436  fseek(file, 18, SEEK_CUR);
437 
438  // read the width
439  if ((i = fread(&pImage->width, 4, 1, file)) != 1) 
440    {
441      if (verbose >=1)
442        printf("Error reading width from %s.\n", bmpName);
443      return false;
444    }
445  // read the height
446  if ((i = fread(&pImage->height, 4, 1, file)) != 1) 
447    {
448      if (verbose>=1)
449        printf("Error reading height from %s.\n", bmpName);
450      return false;
451    }
452 
453  // calculate the size (assuming 24 bits or 3 bytes per pixel).
454  size = pImage->width * pImage->height * 3;
455 
456  // read the planes
457  if ((fread(&planes, 2, 1, file)) != 1) 
458    {
459      if (verbose>=1)
460        printf("Error reading planes from %s.\n", bmpName);
461      return false;
462    }
463  if (planes != 1) 
464    {
465      if (verbose>=1)
466        printf("Planes from %s is not 1: %u\n", bmpName, planes);
467      return false;
468    }
469 
470  // read the bpp
471  if ((i = fread(&bpp, 2, 1, file)) != 1) 
472    {
473      if (verbose>=1)
474        printf("Error reading bpp from %s.\n", bmpName);
475      return false;
476    }
477  if (bpp != 24) 
478    {
479      if (verbose>=1)
480        printf("Bpp from %s is not 24: %u\n", bmpName, bpp);
481      return false;
482    }
483 
484  // seek past the rest of the bitmap header.
485  fseek(file, 24, SEEK_CUR);
486 
487  // read the data.
488  pImage->data = (GLubyte *) malloc(size);
489  if (pImage->data == NULL) 
490    {
491      if (verbose>=1)
492        printf("Error allocating memory for color-corrected image data");
493      return false;     
494    }
495 
496  if ((i = fread(pImage->data, size, 1, file)) != 1) 
497    {
498      if (verbose>=1)
499        printf("Error reading image data from %s.\n", bmpName);
500      return false;
501    }
502  fclose(file);
503
504  // reverse all of the colors. (bgr -> rgb)
505  for (i=0;i<size;i+=3) 
506    { 
507      temp = pImage->data[i];
508      pImage->data[i] = pImage->data[i+2];
509      pImage->data[i+2] = temp;
510    }
511  loadTexToGL (pImage, texture);
512 
513  return true;
514
515  if (pImage)
516    {
517      if (pImage->data)
518        {
519          free(pImage->data);
520        }
521     
522      free(pImage);
523    }
524
525}
526
527bool Material::loadJPG (char* jpgName, GLuint* texture)
528{
529  struct jpeg_decompress_struct cinfo;
530  Image *pImage = NULL;
531  FILE *pFile;
532 
533  // Open a file pointer to the jpeg file and check if it was found and opened
534  if((pFile = fopen(jpgName, "rb")) == NULL) 
535    {
536      // Display an error message saying the file was not found, then return NULL
537      printf("Unable to load JPG File %s.\n", jpgName);
538      return false;
539    }
540 
541  // Create an error handler
542  jpeg_error_mgr jerr;
543 
544  // Have our compression info object point to the error handler address
545  cinfo.err = jpeg_std_error(&jerr);
546 
547  // Initialize the decompression object
548  jpeg_create_decompress(&cinfo);
549 
550  // Specify the data source (Our file pointer)
551  jpeg_stdio_src(&cinfo, pFile);
552 
553  // Allocate the structure that will hold our eventual jpeg data (must free it!)
554  pImage = (Image*)malloc(sizeof(Image));
555 
556  // Decode the jpeg file and fill in the image data structure to pass back
557  decodeJPG(&cinfo, pImage);
558 
559  // This releases all the stored memory for reading and decoding the jpeg
560  jpeg_destroy_decompress(&cinfo);
561 
562  // Close the file pointer that opened the file
563  fclose(pFile);
564 
565
566  if(pImage == NULL)
567    exit(0);
568 
569  loadTexToGL (pImage, texture);
570  if (pImage)
571    {
572      if (pImage->data)
573        {
574          free(pImage->data);
575        }
576     
577      free(pImage);
578    }
579  return true;
580}
581
582void Material::decodeJPG(jpeg_decompress_struct* cinfo, Image* pImageData)
583{
584  // Read in the header of the jpeg file
585  jpeg_read_header(cinfo, TRUE);
586 
587  // Start to decompress the jpeg file with our compression info
588  jpeg_start_decompress(cinfo);
589 
590  // Get the image dimensions and row span to read in the pixel data
591  pImageData->rowSpan = cinfo->image_width * cinfo->num_components;
592  pImageData->width   = cinfo->image_width;
593  pImageData->height   = cinfo->image_height;
594 
595  // Allocate memory for the pixel buffer
596  pImageData->data = new unsigned char[pImageData->rowSpan * pImageData->height];
597 
598  // Here we use the library's state variable cinfo.output_scanline as the
599  // loop counter, so that we don't have to keep track ourselves.
600 
601  // Create an array of row pointers
602  unsigned char** rowPtr = new unsigned char*[pImageData->height];
603  for (int i = 0; i < pImageData->height; i++)
604    rowPtr[i] = &(pImageData->data[i*pImageData->rowSpan]);
605 
606  // Now comes the juice of our work, here we extract all the pixel data
607  int rowsRead = 0;
608  while (cinfo->output_scanline < cinfo->output_height) 
609    {
610      // Read in the current row of pixels and increase the rowsRead count
611      rowsRead += jpeg_read_scanlines(cinfo, &rowPtr[rowsRead], cinfo->output_height - rowsRead);
612    }
613 
614  // Delete the temporary row pointers
615  delete [] rowPtr;
616 
617  // Finish decompressing the data
618  jpeg_finish_decompress(cinfo);
619}
620
621
622
623
624bool Material::loadTGA(const char * tgaName, GLuint* texture)
625{
626  typedef struct
627  {
628    GLubyte Header[12];                                                                 /* TGA File Header */
629  } TGAHeader;
630 TGAHeader tgaHeader;                   
631
632  GLubyte uTGAcompare[12] = {0,0,2, 0,0,0,0,0,0,0,0,0}; /* Uncompressed TGA Header */
633  GLubyte cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0}; /* Compressed TGA Header */
634  FILE * fTGA;
635  fTGA = fopen(tgaName, "rb");
636
637  if(fTGA == NULL)
638    {
639      printf("Error could not open texture file: %s\n", tgaName);
640      return false;
641    }
642 
643  if(fread(&tgaHeader, sizeof(TGAHeader), 1, fTGA) == 0) /// hmm... don't know if this is io
644    {
645      printf("Error could not read file header of %s\n", tgaName);
646      if(fTGA != NULL)
647        {
648          fclose(fTGA);
649        }
650      return false;
651    }
652 
653  if(memcmp(uTGAcompare, &tgaHeader, sizeof(TGAHeader)) == 0)
654    {
655      loadUncompressedTGA(tgaName, fTGA, texture);
656      if (fTGA)
657        fclose (fTGA);
658    }
659  else if(memcmp(cTGAcompare, &tgaHeader, sizeof(TGAHeader)) == 0)
660    {
661      //loadCompressedTGA(tgaName, fTGA, texture);
662        if (fTGA)
663          fclose (fTGA);
664    }
665  else
666    {
667      printf("Error TGA file be type 2 or type 10\n");
668      if (fTGA)
669        fclose(fTGA);
670      return false;
671    }
672  return true;
673}
674
675bool Material::loadUncompressedTGA(const char * filename, FILE * fTGA, GLuint* texture)
676{
677  GLubyte header[6];      // First 6 Useful Bytes From The Header
678  GLuint  bytesPerPixel;  // Holds Number Of Bytes Per Pixel Used In The TGA File
679  GLuint  imageSize;      // Used To Store The Image Size When Setting Aside Ram
680  GLuint  temp;           // Temporary Variable
681  GLuint  type;
682  GLuint  Height;         // Height of Image
683  GLuint  Width;          // Width of Image
684  GLuint  Bpp;            // Bits Per Pixel
685
686  Image* pImage = new Image;
687  GLuint cswap;
688  if(fread(header, sizeof(header), 1, fTGA) == 0)
689    {
690      printf("Error could not read info header\n");
691      return false;
692    }
693 
694  Width = pImage->width  = header[1] * 256 + header[0];
695  Height =  pImage->height = header[3] * 256 + header[2];
696  Bpp = pImage->bpp = header[4];
697  // Make sure all information is valid
698  if((pImage->width <= 0) || (pImage->height <= 0) || ((pImage->bpp != 24) && (pImage->bpp !=32)))
699    {
700      printf("Error invalid texture information\n");
701      return false;
702    }
703 
704  if(pImage->bpp == 24) 
705    {
706      pImage->type = GL_RGB;
707    }
708  else
709    {
710      pImage->type = GL_RGBA;
711    }
712 
713  bytesPerPixel = (Bpp / 8);
714  imageSize = (bytesPerPixel * Width * Height);
715  pImage->data = (GLubyte*) malloc(imageSize);
716 
717  if(pImage->data == NULL)
718    {
719      printf("Error could not allocate memory for image\n");
720      return false;
721    }
722 
723  if(fread(pImage->data, 1, imageSize, fTGA) != imageSize)
724    {
725      printf("Error could not read image data\n");
726      if(pImage->data != NULL)
727        {
728          free(pImage->data);
729        }
730      return false;
731    }
732 
733  /* Byte Swapping Optimized By Steve Thomas */
734  for(cswap = 0; cswap < (int)imageSize; cswap += bytesPerPixel)
735    {
736      pImage->data[cswap] ^= pImage->data[cswap+2] ^=
737        pImage->data[cswap] ^= pImage->data[cswap+2];
738    }
739 
740  loadTexToGL (pImage, texture);
741
742  return true;
743}
744
745#ifdef __auskomentiert__
746bool Material::LoadCompressedTGA(Texture * texture,const char * filename, FILE * fTGA)
747{
748  GLuint pixelcount     = Height * Width;                                                       /* Nuber of pixels in the image */
749  GLuint currentpixel   = 0;                                                                                            /* Current pixel being read */
750  GLuint currentbyte    = 0;                                                                                            /* Current byte */
751  GLubyte * colorbuffer = (GLubyte *)malloc(bytesPerPixel);                     /* Storage for 1 pixel */
752 
753  if(fread(header, sizeof(header), 1, fTGA) == 0)                               /* Attempt to read header */
754    {
755      printf("Error could not read info header");                                                       /* Display Error */
756      if(fTGA != NULL)                                                                                                  /* If file is open */
757        {
758          fclose(fTGA);                                                                                                 /* Close it */
759        }
760      return false;                                                                                                             /* Return failed */
761    }
762 
763  pImage->width  = header[1] * 256 + header[0];                                 /* Determine The TGA Width      (highbyte*256+lowbyte) */
764  pImage->height = header[3] * 256 + header[2];                                 /* Determine The TGA Height     (highbyte*256+lowbyte) */
765  pImage->bpp   = header[4];                                                                            /* Determine Bits Per Pixel */
766  Width         = pImage->width;                                                                                /* Copy width to local structure */
767  Height                = pImage->height;                                                                               /* Copy width to local structure */
768  Bpp                   = pImage->bpp;                                                                                  /* Copy width to local structure */
769 
770  if((pImage->width <= 0) || (pImage->height <= 0) || ((pImage->bpp != 24) && (pImage->bpp !=32)))      /*Make sure all pImage info is ok */
771    {
772      printf("Error Invalid pImage information");                                               /* If it isnt...Display error */
773      if(fTGA != NULL)                                                                                                  /* Check if file is open */
774        {
775          fclose(fTGA);                                                                                                 /* Ifit is, close it */
776        }
777      return false;                                                                                                             /* Return failed */
778    }
779 
780  bytesPerPixel = (Bpp / 8);                                                                    /* Compute BYTES per pixel */
781  imageSize             = (bytesPerPixel * Width * Height);             /* Compute amout of memory needed to store image */
782  pImage->data  = (GLubyte *)malloc(imageSize);                                 /* Allocate that much memory */
783 
784  if(pImage->data == NULL)                                                                                      /* If it wasnt allocated correctly.. */
785    {
786      printf("Error could not allocate memory for image");                              /* Display Error */
787      fclose(fTGA);                                                                                                             /* Close file */
788      return false;                                                                                                             /* Return failed */
789    }
790 
791  do
792    {
793      GLubyte chunkheader = 0;                                                                                  /* Storage for "chunk" header */
794     
795      if(fread(&chunkheader, sizeof(GLubyte), 1, fTGA) == 0)                            /* Read in the 1 byte header */
796        {
797          printf("Error could not read RLE header");                                            /*Display Error */
798          if(fTGA != NULL)                                                                                              /* If file is open */
799            {
800              fclose(fTGA);                                                                                             /* Close file */
801            }
802          if(pImage->data != NULL)                                                                      /* If there is stored image data */
803            {
804              free(pImage->data);                                                                       /* Delete image data */
805            }
806          return false;                                                                                                 /* Return failed */
807        }
808     
809      if(chunkheader < 128)                                                                                             /* If the ehader is < 128, it means the that is the number of RAW color packets minus 1 */
810        {
811          short counter;                                                                                                        /* that follow the header */
812          chunkheader++;                                                                                                        /* add 1 to get number of following color values */
813          for(counter = 0; counter < chunkheader; counter++)                            /* Read RAW color values */
814            {
815              if(fread(colorbuffer, 1, bytesPerPixel, fTGA) != bytesPerPixel) /* Try to read 1 pixel */
816                {
817                  printf("Error could not read image data");                            /* IF we cant, display an error */
818                 
819                  if(fTGA != NULL)                                                                              /* See if file is open */
820                    {
821                      fclose(fTGA);                                                                             /* If so, close file */
822                    }
823                 
824                  if(colorbuffer != NULL)                                                                       /* See if colorbuffer has data in it */
825                    {
826                      free(colorbuffer);                                                                        /* If so, delete it */
827                    }
828                 
829                  if(pImage->data != NULL)                                                                              /* See if there is stored Image data */
830                    {
831                      free(pImage->data);                                                                               /* If so, delete it too */
832                    }
833                 
834                  return false;                                                                                                         /* Return failed */
835                }
836              /* write to memory */
837              pImage->data[currentbyte          ] = colorbuffer[2];                                 /* Flip R and B vcolor values around in the process */
838              pImage->data[currentbyte + 1      ] = colorbuffer[1];
839              pImage->data[currentbyte + 2      ] = colorbuffer[0];
840             
841              if(bytesPerPixel == 4)                                                                                            /* if its a 32 bpp image */
842                {
843                  pImage->data[currentbyte + 3] = colorbuffer[3];                               /* copy the 4th byte */
844                }
845             
846              currentbyte += bytesPerPixel;                                                                             /* Increase thecurrent byte by the number of bytes per pixel */
847              currentpixel++;                                                                                                                   /* Increase current pixel by 1 */
848             
849              if(currentpixel > pixelcount)                                                                                     /* Make sure we havent read too many pixels */
850                {
851                  printf("Error too many pixels read");                                                         /* if there is too many... Display an error! */
852                 
853                  if(fTGA != NULL)                                                                                                      /* If there is a file open */
854                    {
855                      fclose(fTGA);                                                                                                     /* Close file */
856                    }
857                 
858                  if(colorbuffer != NULL)                                                                                               /* If there is data in colorbuffer */
859                    {
860                      free(colorbuffer);                                                                                                /* Delete it */
861                    }
862                 
863                  if(pImage->data != NULL)                                                                              /* If there is Image data */
864                    {
865                      free(pImage->data);                                                                               /* delete it */
866                    }
867                 
868                  return false;                                                                                                         /* Return failed */
869                }
870            }
871        }
872      else                                                                                                                                                      /* chunkheader > 128 RLE data, next color  reapeated chunkheader - 127 times */
873        {
874          short counter;
875          chunkheader -= 127;                                                                                                                   /* Subteact 127 to get rid of the ID bit */
876          if(fread(colorbuffer, 1, bytesPerPixel, fTGA) != bytesPerPixel)               /* Attempt to read following color values */
877            {
878              printf("Error could not read from file");                 /* If attempt fails.. Display error (again) */
879             
880              if(fTGA != NULL)                                                                                                          /* If thereis a file open */
881                {
882                  fclose(fTGA);                                                                                                         /* Close it */
883                }
884             
885              if(colorbuffer != NULL)                                                                                                   /* If there is data in the colorbuffer */
886                {
887                  free(colorbuffer);                                                                                                    /* delete it */
888                }
889             
890              if(pImage->data != NULL)                                                                                  /* If thereis image data */
891                {
892                  free(pImage->data);                                                                                   /* delete it */
893                }
894             
895              return false;                                                                                                                     /* return failed */
896            }
897         
898          for(counter = 0; counter < chunkheader; counter++)                                    /* copy the color into the image data as many times as dictated */
899            {                                                                                                                                                   /* by the header */
900              pImage->data[currentbyte          ] = colorbuffer[2];                                     /* switch R and B bytes areound while copying */
901              pImage->data[currentbyte + 1      ] = colorbuffer[1];
902              pImage->data[currentbyte + 2      ] = colorbuffer[0];
903             
904              if(bytesPerPixel == 4)                                                                                            /* If TGA images is 32 bpp */
905                {
906                  pImage->data[currentbyte + 3] = colorbuffer[3];                               /* Copy 4th byte */
907                }
908             
909              currentbyte += bytesPerPixel;                                                                             /* Increase current byte by the number of bytes per pixel */
910              currentpixel++;                                                                                                                   /* Increase pixel count by 1 */
911             
912              if(currentpixel > pixelcount)                                                                                     /* Make sure we havent written too many pixels */
913                {
914                  printf("Error too many pixels read");                                                         /* if there is too many... Display an error! */
915                 
916                  if(fTGA != NULL)                                                                                                      /* If there is a file open */
917                    {
918                      fclose(fTGA);                                                                                                     /* Close file */
919                    }
920                 
921                  if(colorbuffer != NULL)                                                                                               /* If there is data in colorbuffer */
922                    {
923                      free(colorbuffer);                                                                                                /* Delete it */
924                    }
925                 
926                  if(pImage->data != NULL)                                                                              /* If there is Image data */
927                    {
928                      free(pImage->data);                                                                               /* delete it */
929                    }
930                 
931                  return false;                                                                                                         /* Return failed */
932                }
933            }
934        }
935    }
936 
937  while(currentpixel < pixelcount);                                                                                                     /* Loop while there are still pixels left */
938  fclose(fTGA);                                                                                                                                         /* Close the file */
939  return true;                                                                                                                                          /* return success */
940}
941
942#endif
Note: See TracBrowser for help on using the repository browser.