Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/images: testing SDL_image. It rocks.

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