Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

imagesgi.cpp 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. /******************************************************************************
  2. ** Filename : imageSgi.cpp
  3. ** UNCLASSIFIED
  4. **
  5. ** Description : Utility to read SGI image format files. This code was
  6. ** originally a SGI image loading utility provided with the
  7. ** Mesa 3D library @ http://www.mesa3d.org by Brain Paul.
  8. ** This has been extended to read all SGI image formats
  9. ** (e.g. INT, INTA, RGB, RGBA).
  10. **
  11. ** Revision History:
  12. ** Date Name Description
  13. ** 06/07/99 BRC Initial Release
  14. **
  15. ** Note:
  16. **
  17. ** The SGI Image Data (if not RLE)
  18. **
  19. ** If the image is stored verbatim (without RLE), then image data directly
  20. ** follows the 512 byte header. The data for each scanline of the first
  21. ** channel is written first. If the image has more than 1 channel, all
  22. ** the data for the first channel is written, followed by the remaining
  23. ** channels. If the BPC value is 1, then each scanline is written as XSIZE
  24. ** bytes. If the BPC value is 2, then each scanline is written as XSIZE
  25. ** shorts. These shorts are stored in the byte order described above.
  26. **
  27. ******************************************************************************/
  28. #define __IMAGESGI_CPP
  29. #include "imagesgi.h"
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include <math.h>
  34. #include <assert.h>
  35. struct sImageSgiRaw
  36. {
  37. struct sImageSgiHeader header;
  38. unsigned char *chan0;
  39. unsigned char *chan1;
  40. unsigned char *chan2;
  41. unsigned char *chan3;
  42. unsigned int *rowStart;
  43. int *rowSize;
  44. };
  45. // Static routines
  46. static struct sImageSgiRaw *ImageSgiRawOpen(char const * const fileName);
  47. static void ImageSgiRawClose(struct sImageSgiRaw *raw);
  48. static void ImageSgiRawGetRow(struct sImageSgiRaw *raw, unsigned char *buf,
  49. int y, int z);
  50. static void ImageSgiRawGetData(struct sImageSgiRaw *raw, struct sImageSgi
  51. *final);
  52. static void *SwitchEndian16(void *value);
  53. static void *SwitchEndian32(void *value);
  54. // Static variables
  55. FILE *mFp = NULL;
  56. unsigned char *mChanTmp = NULL;
  57. /*****************************************************************************/
  58. struct sImageSgi *ImageSgiOpen(char const * const fileName)
  59. {
  60. struct sImageSgiRaw *raw = NULL;
  61. struct sImageSgi *final = NULL;
  62. raw = ImageSgiRawOpen(fileName);
  63. final = new struct sImageSgi;
  64. assert(final);
  65. if(final)
  66. {
  67. final->header = raw->header;
  68. final->data = NULL;
  69. ImageSgiRawGetData(raw, final);
  70. ImageSgiRawClose(raw);
  71. }
  72. return final;
  73. } // ImageSgiRawOpen
  74. /*****************************************************************************/
  75. void ImageSgiClose(struct sImageSgi *image)
  76. {
  77. if(image)
  78. {
  79. if(image->data)
  80. delete[] image->data;
  81. image->data = NULL;
  82. delete image;
  83. }
  84. image = NULL;
  85. return;
  86. } // ImageSgiClose
  87. /*****************************************************************************/
  88. static struct sImageSgiRaw *ImageSgiRawOpen(char const * const fileName)
  89. {
  90. struct sImageSgiRaw *raw = NULL;
  91. int x;
  92. int i;
  93. bool swapFlag = false;
  94. union
  95. {
  96. int testWord;
  97. char testByte[4];
  98. } endianTest;
  99. endianTest.testWord = 1;
  100. // Determine endianess of platform.
  101. if(endianTest.testByte[0] == 1)
  102. swapFlag = true;
  103. else
  104. swapFlag = false;
  105. raw = new struct sImageSgiRaw;
  106. assert(raw);
  107. if(raw)
  108. {
  109. raw->chan0 = NULL;
  110. raw->chan1 = NULL;
  111. raw->chan2 = NULL;
  112. raw->chan3 = NULL;
  113. raw->rowStart = NULL;
  114. raw->rowSize = NULL;
  115. mFp = fopen(fileName, "rb");
  116. assert(mFp);
  117. fread(&raw->header, sizeof(struct sImageSgiHeader), 1, mFp);
  118. if(swapFlag == true)
  119. {
  120. SwitchEndian16(&raw->header.magic);
  121. SwitchEndian16(&raw->header.type);
  122. SwitchEndian16(&raw->header.dim);
  123. SwitchEndian16(&raw->header.xsize);
  124. SwitchEndian16(&raw->header.ysize);
  125. SwitchEndian16(&raw->header.zsize);
  126. }
  127. mChanTmp = new unsigned char[raw->header.xsize * raw->header.ysize];
  128. assert(mChanTmp);
  129. switch(raw->header.zsize)
  130. {
  131. case 4:
  132. raw->chan3 = new unsigned char[raw->header.xsize *
  133. raw->header.ysize];
  134. assert(raw->chan3);
  135. case 3:
  136. raw->chan2 = new unsigned char[raw->header.xsize *
  137. raw->header.ysize];
  138. assert(raw->chan2);
  139. case 2:
  140. raw->chan1 = new unsigned char[raw->header.xsize *
  141. raw->header.ysize];
  142. assert(raw->chan1);
  143. case 1:
  144. raw->chan0 = new unsigned char[raw->header.xsize *
  145. raw->header.ysize];
  146. assert(raw->chan0);
  147. }
  148. if(raw->header.type == IMAGE_SGI_TYPE_RLE)
  149. {
  150. x = raw->header.ysize * raw->header.zsize * sizeof(unsigned int);
  151. raw->rowStart = new unsigned int[x];
  152. raw->rowSize = new int[x];
  153. fseek(mFp, sizeof(struct sImageSgiHeader), SEEK_SET);
  154. fread(raw->rowStart, 1, x, mFp);
  155. fread(raw->rowSize, 1, x, mFp);
  156. if(swapFlag == true)
  157. {
  158. for(i=0; i<x/sizeof(unsigned int); i++)
  159. SwitchEndian32(&raw->rowStart[i]);
  160. for(i=0; i<x/sizeof(int); i++)
  161. SwitchEndian32(&raw->rowSize[i]);
  162. }
  163. }
  164. }
  165. return raw;
  166. } // ImageSgiRawOpen
  167. /*****************************************************************************/
  168. static void ImageSgiRawClose(struct sImageSgiRaw *raw)
  169. {
  170. fclose(mFp);
  171. mFp = NULL;
  172. if(mChanTmp)
  173. delete[] mChanTmp;
  174. mChanTmp = NULL;
  175. if(raw->chan0)
  176. delete[] raw->chan0;
  177. raw->chan0 = NULL;
  178. if(raw->chan1)
  179. delete[] raw->chan1;
  180. raw->chan1 = NULL;
  181. if(raw->chan2)
  182. delete[] raw->chan2;
  183. raw->chan2 = NULL;
  184. if(raw->chan3)
  185. delete[] raw->chan3;
  186. raw->chan3 = NULL;
  187. if(raw)
  188. delete raw;
  189. raw = NULL;
  190. return;
  191. } // ImageSgiRawClose
  192. /*****************************************************************************/
  193. static void ImageSgiRawGetRow(struct sImageSgiRaw *raw, unsigned char *buf,
  194. int y, int z)
  195. {
  196. unsigned char *iPtr = NULL;
  197. unsigned char *oPtr = NULL;
  198. unsigned char pixel;
  199. int count;
  200. if((raw->header.type & 0xFF00) == 0x0100)
  201. {
  202. fseek(mFp, raw->rowStart[y+z*raw->header.ysize], SEEK_SET);
  203. fread(mChanTmp, 1, (unsigned int)raw->rowSize[y+z*raw->header.ysize],
  204. mFp);
  205. iPtr = mChanTmp;
  206. oPtr = buf;
  207. while(1)
  208. {
  209. pixel = *iPtr++;
  210. count = (int)(pixel & 0x7F);
  211. if(!count)
  212. {
  213. return;
  214. }
  215. if (pixel & 0x80)
  216. {
  217. while (count--)
  218. {
  219. *oPtr++ = *iPtr++;
  220. }
  221. }
  222. else
  223. {
  224. pixel = *iPtr++;
  225. while (count--)
  226. {
  227. *oPtr++ = pixel;
  228. }
  229. }
  230. }
  231. }
  232. else
  233. {
  234. fseek(mFp,
  235. sizeof(struct sImageSgiHeader)+(y*raw->header.xsize) +
  236. (z*raw->header.xsize*raw->header.ysize),
  237. SEEK_SET);
  238. fread(buf, 1, raw->header.xsize, mFp);
  239. }
  240. return;
  241. } // ImageSgiRawGetRow
  242. /*****************************************************************************/
  243. static void ImageSgiRawGetData(struct sImageSgiRaw *raw, struct sImageSgi
  244. *final)
  245. {
  246. unsigned char *ptr = NULL;
  247. int i, j;
  248. final->data =
  249. new unsigned
  250. char[raw->header.xsize*raw->header.ysize*raw->header.zsize];
  251. assert(final->data);
  252. ptr = final->data;
  253. for(i=0; i<raw->header.ysize; i++)
  254. {
  255. switch(raw->header.zsize)
  256. {
  257. case 1:
  258. ImageSgiRawGetRow(raw, raw->chan0, i, 0);
  259. for(j=0; j<raw->header.xsize; j++)
  260. *(ptr++) = raw->chan0[j];
  261. break;
  262. case 2:
  263. ImageSgiRawGetRow(raw, raw->chan0, i, 0);
  264. ImageSgiRawGetRow(raw, raw->chan1, i, 1);
  265. for(j=0; j<raw->header.xsize; j++)
  266. {
  267. *(ptr++) = raw->chan0[j];
  268. *(ptr++) = raw->chan1[j];
  269. }
  270. break;
  271. case 3:
  272. ImageSgiRawGetRow(raw, raw->chan0, i, 0);
  273. ImageSgiRawGetRow(raw, raw->chan1, i, 1);
  274. ImageSgiRawGetRow(raw, raw->chan2, i, 2);
  275. for(j=0; j<raw->header.xsize; j++)
  276. {
  277. *(ptr++) = raw->chan0[j];
  278. *(ptr++) = raw->chan1[j];
  279. *(ptr++) = raw->chan2[j];
  280. }
  281. break;
  282. case 4:
  283. ImageSgiRawGetRow(raw, raw->chan0, i, 0);
  284. ImageSgiRawGetRow(raw, raw->chan1, i, 1);
  285. ImageSgiRawGetRow(raw, raw->chan2, i, 2);
  286. ImageSgiRawGetRow(raw, raw->chan3, i, 3);
  287. for(j=0; j<raw->header.xsize; j++)
  288. {
  289. *(ptr++) = raw->chan0[j];
  290. *(ptr++) = raw->chan1[j];
  291. *(ptr++) = raw->chan2[j];
  292. *(ptr++) = raw->chan3[j];
  293. }
  294. break;
  295. }
  296. }
  297. return;
  298. } // ImageSgiRawGetData
  299. /*****************************************************************************/
  300. static void *SwitchEndian16(void *value)
  301. {
  302. short value16 = *(short *) value;
  303. value16 = ((value16 & 0xff00) >> 8L) +
  304. ((value16 & 0x00ff) << 8L);
  305. *(short *)value = value16;
  306. return value;
  307. } // SwitchEndian16
  308. /*****************************************************************************/
  309. static void *SwitchEndian32(void *value)
  310. {
  311. int value32 = *(int *) value;
  312. value32 = ((value32 & 0xff000000) >> 24L) +
  313. ((value32 & 0x00ff0000) >> 8) +
  314. ((value32 & 0x0000ff00) << 8) +
  315. ((value32 & 0x000000ff) << 24L);
  316. *(int *)value = value32;
  317. return value;
  318. } // SwitchEndian32