Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3110 was 3110, checked in by bensch, 20 years ago

orxonox/branches/images: test for jpeg and png libs in configure.ac and material.cc/h

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