/libs/cocos2d/Support/TGAlib.m

http://github.com/kstenerud/ObjectAL-for-iPhone · Objective C · 272 lines · 172 code · 52 blank · 48 comment · 44 complexity · 2775f3c681677cfdf2b3d22d26dfeaa5 MD5 · raw file

  1. //
  2. // TGA lib for cocos2d-iphone
  3. //
  4. // sources from: http://www.lighthouse3d.com/opengl/terrain/index.php3?tgasource
  5. //
  6. // TGA RLE compression support by Ernesto Corvi
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #import "TGAlib.h"
  11. // load the image header fields. We only keep those that matter!
  12. void tgaLoadHeader(FILE *file, tImageTGA *info) {
  13. unsigned char cGarbage;
  14. short int iGarbage;
  15. fread(&cGarbage, sizeof(unsigned char), 1, file);
  16. fread(&cGarbage, sizeof(unsigned char), 1, file);
  17. // type must be 2 or 3
  18. fread(&info->type, sizeof(unsigned char), 1, file);
  19. fread(&iGarbage, sizeof(short int), 1, file);
  20. fread(&iGarbage, sizeof(short int), 1, file);
  21. fread(&cGarbage, sizeof(unsigned char), 1, file);
  22. fread(&iGarbage, sizeof(short int), 1, file);
  23. fread(&iGarbage, sizeof(short int), 1, file);
  24. fread(&info->width, sizeof(short int), 1, file);
  25. fread(&info->height, sizeof(short int), 1, file);
  26. fread(&info->pixelDepth, sizeof(unsigned char), 1, file);
  27. fread(&cGarbage, sizeof(unsigned char), 1, file);
  28. info->flipped = 0;
  29. if ( cGarbage & 0x20 ) info->flipped = 1;
  30. }
  31. // loads the image pixels. You shouldn't call this function directly
  32. void tgaLoadImageData(FILE *file, tImageTGA *info) {
  33. int mode,total,i;
  34. unsigned char aux;
  35. // mode equal the number of components for each pixel
  36. mode = info->pixelDepth / 8;
  37. // total is the number of unsigned chars we'll have to read
  38. total = info->height * info->width * mode;
  39. fread(info->imageData,sizeof(unsigned char),total,file);
  40. // mode=3 or 4 implies that the image is RGB(A). However TGA
  41. // stores it as BGR(A) so we'll have to swap R and B.
  42. if (mode >= 3)
  43. for (i=0; i < total; i+= mode) {
  44. aux = info->imageData[i];
  45. info->imageData[i] = info->imageData[i+2];
  46. info->imageData[i+2] = aux;
  47. }
  48. }
  49. // loads the RLE encoded image pixels. You shouldn't call this function directly
  50. void tgaLoadRLEImageData(FILE *file, tImageTGA *info)
  51. {
  52. unsigned int mode,total,i, index = 0;
  53. unsigned char aux[4], runlength = 0;
  54. unsigned int skip = 0, flag = 0;
  55. // mode equal the number of components for each pixel
  56. mode = info->pixelDepth / 8;
  57. // total is the number of unsigned chars we'll have to read
  58. total = info->height * info->width;
  59. for( i = 0; i < total; i++ )
  60. {
  61. // if we have a run length pending, run it
  62. if ( runlength != 0 )
  63. {
  64. // we do, update the run length count
  65. runlength--;
  66. skip = (flag != 0);
  67. }
  68. else
  69. {
  70. // otherwise, read in the run length token
  71. if ( fread(&runlength,sizeof(unsigned char),1,file) != 1 )
  72. return;
  73. // see if it's a RLE encoded sequence
  74. flag = runlength & 0x80;
  75. if ( flag ) runlength -= 128;
  76. skip = 0;
  77. }
  78. // do we need to skip reading this pixel?
  79. if ( !skip )
  80. {
  81. // no, read in the pixel data
  82. if ( fread(aux,sizeof(unsigned char),mode,file) != mode )
  83. return;
  84. // mode=3 or 4 implies that the image is RGB(A). However TGA
  85. // stores it as BGR(A) so we'll have to swap R and B.
  86. if ( mode >= 3 )
  87. {
  88. unsigned char tmp;
  89. tmp = aux[0];
  90. aux[0] = aux[2];
  91. aux[2] = tmp;
  92. }
  93. }
  94. // add the pixel to our image
  95. memcpy(&info->imageData[index], aux, mode);
  96. index += mode;
  97. }
  98. }
  99. void tgaFlipImage( tImageTGA *info )
  100. {
  101. // mode equal the number of components for each pixel
  102. int mode = info->pixelDepth / 8;
  103. int rowbytes = info->width*mode;
  104. unsigned char *row = (unsigned char *)malloc(rowbytes);
  105. int y;
  106. if (row == NULL) return;
  107. for( y = 0; y < (info->height/2); y++ )
  108. {
  109. memcpy(row, &info->imageData[y*rowbytes],rowbytes);
  110. memcpy(&info->imageData[y*rowbytes], &info->imageData[(info->height-(y+1))*rowbytes], rowbytes);
  111. memcpy(&info->imageData[(info->height-(y+1))*rowbytes], row, rowbytes);
  112. }
  113. free(row);
  114. info->flipped = 0;
  115. }
  116. // this is the function to call when we want to load an image
  117. tImageTGA * tgaLoad(const char *filename) {
  118. FILE *file;
  119. tImageTGA *info;
  120. int mode,total;
  121. // allocate memory for the info struct and check!
  122. info = (tImageTGA *)malloc(sizeof(tImageTGA));
  123. if (info == NULL)
  124. return(NULL);
  125. // open the file for reading (binary mode)
  126. file = fopen(filename, "rb");
  127. if (file == NULL) {
  128. info->status = TGA_ERROR_FILE_OPEN;
  129. return(info);
  130. }
  131. // load the header
  132. tgaLoadHeader(file,info);
  133. // check for errors when loading the header
  134. if (ferror(file)) {
  135. info->status = TGA_ERROR_READING_FILE;
  136. fclose(file);
  137. return(info);
  138. }
  139. // check if the image is color indexed
  140. if (info->type == 1) {
  141. info->status = TGA_ERROR_INDEXED_COLOR;
  142. fclose(file);
  143. return(info);
  144. }
  145. // check for other types (compressed images)
  146. if ((info->type != 2) && (info->type !=3) && (info->type !=10) ) {
  147. info->status = TGA_ERROR_COMPRESSED_FILE;
  148. fclose(file);
  149. return(info);
  150. }
  151. // mode equals the number of image components
  152. mode = info->pixelDepth / 8;
  153. // total is the number of unsigned chars to read
  154. total = info->height * info->width * mode;
  155. // allocate memory for image pixels
  156. info->imageData = (unsigned char *)malloc(sizeof(unsigned char) *
  157. total);
  158. // check to make sure we have the memory required
  159. if (info->imageData == NULL) {
  160. info->status = TGA_ERROR_MEMORY;
  161. fclose(file);
  162. return(info);
  163. }
  164. // finally load the image pixels
  165. if ( info->type == 10 )
  166. tgaLoadRLEImageData(file, info);
  167. else
  168. tgaLoadImageData(file,info);
  169. // check for errors when reading the pixels
  170. if (ferror(file)) {
  171. info->status = TGA_ERROR_READING_FILE;
  172. fclose(file);
  173. return(info);
  174. }
  175. fclose(file);
  176. info->status = TGA_OK;
  177. if ( info->flipped )
  178. {
  179. tgaFlipImage( info );
  180. if ( info->flipped ) info->status = TGA_ERROR_MEMORY;
  181. }
  182. return(info);
  183. }
  184. // converts RGB to greyscale
  185. void tgaRGBtogreyscale(tImageTGA *info) {
  186. int mode,i,j;
  187. unsigned char *newImageData;
  188. // if the image is already greyscale do nothing
  189. if (info->pixelDepth == 8)
  190. return;
  191. // compute the number of actual components
  192. mode = info->pixelDepth / 8;
  193. // allocate an array for the new image data
  194. newImageData = (unsigned char *)malloc(sizeof(unsigned char) *
  195. info->height * info->width);
  196. if (newImageData == NULL) {
  197. return;
  198. }
  199. // convert pixels: greyscale = o.30 * R + 0.59 * G + 0.11 * B
  200. for (i = 0,j = 0; j < info->width * info->height; i +=mode, j++)
  201. newImageData[j] =
  202. (unsigned char)(0.30 * info->imageData[i] +
  203. 0.59 * info->imageData[i+1] +
  204. 0.11 * info->imageData[i+2]);
  205. //free old image data
  206. free(info->imageData);
  207. // reassign pixelDepth and type according to the new image type
  208. info->pixelDepth = 8;
  209. info->type = 3;
  210. // reassing imageData to the new array.
  211. info->imageData = newImageData;
  212. }
  213. // releases the memory used for the image
  214. void tgaDestroy(tImageTGA *info) {
  215. if (info != NULL) {
  216. if (info->imageData != NULL)
  217. free(info->imageData);
  218. free(info);
  219. }
  220. }