IFF.C 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. /****************************************************************************
  2. * iff.c
  3. *
  4. * This file implements a simple IFF format file reader.
  5. *
  6. * from Persistence of Vision(tm) Ray Tracer
  7. * Copyright 1996,1999 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. * NOTICE: This source code file is provided so that users may experiment
  10. * with enhancements to POV-Ray and to port the software to platforms other
  11. * than those supported by the POV-Ray Team. There are strict rules under
  12. * which you are permitted to use this file. The rules are in the file
  13. * named POVLEGAL.DOC which should be distributed with this file.
  14. * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. * Team Coordinator by email to team-coord@povray.org or visit us on the web at
  16. * http://www.povray.org. The latest version of POV-Ray may be found at this site.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. * Modifications by Hans-Detlev Fink, January 1999, used with permission
  23. *****************************************************************************/
  24. #include "frame.h"
  25. #include "povproto.h"
  26. #include "iff.h"
  27. #include "povray.h"
  28. /*****************************************************************************
  29. * Local preprocessor defines
  30. ******************************************************************************/
  31. #define FORM 0x464f524dL
  32. #define ILBM 0x494c424dL
  33. #define BMHD 0x424d4844L
  34. #define CAMG 0x43414d47L
  35. #define CMAP 0x434d4150L
  36. #define BODY 0x424f4459L
  37. #define CMPNONE 0
  38. #define HAM 0x800
  39. /*****************************************************************************
  40. * Local typedefs
  41. ******************************************************************************/
  42. /*****************************************************************************
  43. * Local variables
  44. ******************************************************************************/
  45. static IMAGE_COLOUR *iff_colour_map;
  46. static int colourmap_size;
  47. static CHUNK_HEADER Chunk_Header;
  48. /*****************************************************************************
  49. * Static functions
  50. ******************************************************************************/
  51. static void iff_error (void);
  52. static int read_byte (FILE * f);
  53. static int read_word (FILE * f);
  54. static long read_long (FILE * f);
  55. static void Read_Chunk_Header (FILE * f, CHUNK_HEADER * dest);
  56. /*****************************************************************************
  57. *
  58. * FUNCTION
  59. *
  60. * INPUT
  61. *
  62. * OUTPUT
  63. *
  64. * RETURNS
  65. *
  66. * AUTHOR
  67. *
  68. * POV-Ray Team
  69. *
  70. * DESCRIPTION
  71. *
  72. * -
  73. *
  74. * CHANGES
  75. *
  76. * -
  77. *
  78. ******************************************************************************/
  79. static void iff_error()
  80. {
  81. Error("Error reading IFF image.\n");
  82. }
  83. /*****************************************************************************
  84. *
  85. * FUNCTION
  86. *
  87. * INPUT
  88. *
  89. * OUTPUT
  90. *
  91. * RETURNS
  92. *
  93. * AUTHOR
  94. *
  95. * POV-Ray Team
  96. *
  97. * DESCRIPTION
  98. *
  99. * -
  100. *
  101. * CHANGES
  102. *
  103. * -
  104. *
  105. ******************************************************************************/
  106. static int read_byte(FILE *f)
  107. {
  108. int c;
  109. if ((c = getc(f)) == EOF)
  110. {
  111. iff_error();
  112. }
  113. return (c);
  114. }
  115. /*****************************************************************************
  116. *
  117. * FUNCTION
  118. *
  119. * INPUT
  120. *
  121. * OUTPUT
  122. *
  123. * RETURNS
  124. *
  125. * AUTHOR
  126. *
  127. * POV-Ray Team
  128. *
  129. * DESCRIPTION
  130. *
  131. * -
  132. *
  133. * CHANGES
  134. *
  135. * -
  136. *
  137. ******************************************************************************/
  138. static int read_word(FILE *f)
  139. {
  140. int result;
  141. result = read_byte(f) * 256;
  142. result += read_byte(f);
  143. return (result);
  144. }
  145. /*****************************************************************************
  146. *
  147. * FUNCTION
  148. *
  149. * INPUT
  150. *
  151. * OUTPUT
  152. *
  153. * RETURNS
  154. *
  155. * AUTHOR
  156. *
  157. * POV-Ray Team
  158. *
  159. * DESCRIPTION
  160. *
  161. * -
  162. *
  163. * CHANGES
  164. *
  165. * -
  166. *
  167. ******************************************************************************/
  168. static long read_long(FILE *f)
  169. {
  170. int i;
  171. long result;
  172. result = 0;
  173. for (i = 0; i < 4; i++)
  174. {
  175. result = result * 256 + read_byte(f);
  176. }
  177. return (result);
  178. }
  179. /*****************************************************************************
  180. *
  181. * FUNCTION
  182. *
  183. * INPUT
  184. *
  185. * OUTPUT
  186. *
  187. * RETURNS
  188. *
  189. * AUTHOR
  190. *
  191. * POV-Ray Team
  192. *
  193. * DESCRIPTION
  194. *
  195. * -
  196. *
  197. * CHANGES
  198. *
  199. * -
  200. *
  201. ******************************************************************************/
  202. static void Read_Chunk_Header(FILE *f, CHUNK_HEADER *dest)
  203. {
  204. dest->name = read_long(f);
  205. dest->size = read_long(f);
  206. }
  207. /*****************************************************************************
  208. *
  209. * FUNCTION
  210. *
  211. * INPUT
  212. *
  213. * OUTPUT
  214. *
  215. * RETURNS
  216. *
  217. * AUTHOR
  218. *
  219. * POV-Ray Team
  220. *
  221. * DESCRIPTION
  222. *
  223. * -
  224. *
  225. * CHANGES
  226. *
  227. * -
  228. *
  229. ******************************************************************************/
  230. void Read_Iff_Image(IMAGE *Image, char *filename)
  231. {
  232. unsigned char **row_bytes;
  233. int c, i, j, k, nBytes, nPlanes = 0, compression = 0;
  234. int mask, byte_index, count, viewmodes;
  235. int Previous_Red, Previous_Green, Previous_Blue;
  236. unsigned long creg;
  237. FILE *f;
  238. IMAGE_LINE *line;
  239. if ((f = Locate_File(filename, READ_BINFILE_STRING, ".iff", ".IFF",NULL,TRUE)) == NULL)
  240. {
  241. Error("Error opening IFF image.\n");
  242. return; /* -hdf99- */
  243. }
  244. Previous_Red = Previous_Green = Previous_Blue = 0;
  245. viewmodes = 0;
  246. iff_colour_map = NULL;
  247. while (1)
  248. {
  249. Read_Chunk_Header(f, &Chunk_Header);
  250. switch (IFF_SWITCH_CAST Chunk_Header.name)
  251. {
  252. case FORM:
  253. if (read_long(f) != ILBM)
  254. {
  255. iff_error();
  256. }
  257. break;
  258. case BMHD:
  259. Image->iwidth = read_word(f);
  260. Image->iheight = read_word(f);
  261. Image->width = (DBL)Image->iwidth;
  262. Image->height = (DBL)Image->iheight;
  263. read_word(f); /* x position ignored */
  264. read_word(f); /* y position ignored */
  265. nPlanes = read_byte(f);
  266. colourmap_size = 1 << nPlanes;
  267. read_byte(f); /* masking ignored */
  268. compression = read_byte(f); /* masking ignored */
  269. read_byte(f); /* pad */
  270. read_word(f); /* Transparent colour ignored */
  271. read_word(f); /* Aspect ratio ignored */
  272. read_word(f); /* page width ignored */
  273. read_word(f); /* page height ignored */
  274. break;
  275. case CAMG:
  276. viewmodes = (int)read_long(f); /* Viewmodes */
  277. if (viewmodes & HAM)
  278. {
  279. colourmap_size = 16;
  280. }
  281. break;
  282. case CMAP:
  283. colourmap_size = (int)Chunk_Header.size / 3;
  284. iff_colour_map = (IMAGE_COLOUR *)POV_MALLOC(sizeof(IMAGE_COLOUR) * colourmap_size, "IFF color map");
  285. for (i = 0; i < colourmap_size; i++)
  286. {
  287. iff_colour_map[i].Red = read_byte(f);
  288. iff_colour_map[i].Green = read_byte(f);
  289. iff_colour_map[i].Blue = read_byte(f);
  290. iff_colour_map[i].Filter = 0;
  291. iff_colour_map[i].Transmit = 0;
  292. }
  293. Previous_Red = iff_colour_map[0].Red;
  294. Previous_Green = iff_colour_map[0].Green;
  295. Previous_Blue = iff_colour_map[0].Blue;
  296. for (i = colourmap_size * 3; (long)i < Chunk_Header.size; i++)
  297. {
  298. read_byte(f);
  299. }
  300. break;
  301. case BODY:
  302. if ((iff_colour_map == NULL) || (viewmodes & HAM))
  303. {
  304. Image->Colour_Map_Size = 0;
  305. Image->Colour_Map = NULL;
  306. }
  307. else
  308. {
  309. Image->Colour_Map_Size = colourmap_size;
  310. Image->Colour_Map = iff_colour_map;
  311. }
  312. row_bytes = (unsigned char **)POV_MALLOC((size_t) (4 * nPlanes), "IFF decoder line");
  313. for (i = 0; i < nPlanes; i++)
  314. {
  315. row_bytes[i] = (unsigned char *)POV_MALLOC((size_t) (((Image->iwidth + 15) / 16) * 2), "IFF decoder line");
  316. }
  317. if (Image->Colour_Map == NULL)
  318. {
  319. Image->data.rgb_lines = (IMAGE_LINE *)POV_MALLOC(Image->iheight * sizeof(IMAGE_LINE), "IFF image");
  320. }
  321. else
  322. {
  323. Image->data.map_lines = (unsigned char **)POV_MALLOC(Image->iheight * sizeof(unsigned char *), "IFF image");
  324. }
  325. for (i = 0; i < Image->iheight; i++)
  326. {
  327. if (Image->Colour_Map == NULL)
  328. {
  329. Image->data.rgb_lines[i].red = (unsigned char *)POV_MALLOC((size_t) Image->iwidth, "IFF image line");
  330. Image->data.rgb_lines[i].green = (unsigned char *)POV_MALLOC((size_t) Image->iwidth, "IFF image line");
  331. Image->data.rgb_lines[i].blue = (unsigned char *)POV_MALLOC((size_t) Image->iwidth, "IFF image line");
  332. }
  333. else
  334. {
  335. Image->data.map_lines[i] = (unsigned char *)POV_MALLOC(Image->iwidth * sizeof(unsigned char), "IFF image line");
  336. }
  337. for (j = 0; j < nPlanes; j++)
  338. {
  339. if (compression == CMPNONE)
  340. {
  341. for (k = 0; k < (((Image->iwidth + 15) / 16) * 2); k++)
  342. {
  343. row_bytes[j][k] = (unsigned char)read_byte(f);
  344. }
  345. if ((k & 1) != 0)
  346. {
  347. read_byte(f);
  348. }
  349. }
  350. else
  351. {
  352. nBytes = 0;
  353. while (nBytes != ((Image->iwidth + 15) / 16) * 2)
  354. {
  355. c = read_byte(f);
  356. if ((c >= 0) && (c <= 127))
  357. {
  358. for (k = 0; k <= c; k++)
  359. {
  360. row_bytes[j][nBytes++] = (unsigned char)read_byte(f);
  361. }
  362. }
  363. else
  364. {
  365. if ((c >= 129) && (c <= 255))
  366. {
  367. count = 257 - c;
  368. c = read_byte(f);
  369. for (k = 0; k < count; k++)
  370. {
  371. row_bytes[j][nBytes++] = (unsigned char)c;
  372. }
  373. }
  374. }
  375. }
  376. }
  377. }
  378. mask = 0x80;
  379. byte_index = 0;
  380. for (j = 0; j < Image->iwidth; j++)
  381. {
  382. creg = 0;
  383. for (k = nPlanes - 1; k >= 0; k--)
  384. {
  385. if (row_bytes[k][byte_index] & mask)
  386. {
  387. creg = creg * 2 + 1;
  388. }
  389. else
  390. {
  391. creg *= 2;
  392. }
  393. }
  394. if (viewmodes & HAM)
  395. {
  396. line = &Image->data.rgb_lines[i];
  397. switch ((int)(creg >> 4))
  398. {
  399. case 0:
  400. Previous_Red = line->red[j] = (unsigned char)iff_colour_map[creg].Red;
  401. Previous_Green = line->green[j] = (unsigned char)iff_colour_map[creg].Green;
  402. Previous_Blue = line->blue[j] = (unsigned char)iff_colour_map[creg].Blue;
  403. break;
  404. case 1:
  405. line->red[j] = (unsigned char)Previous_Red;
  406. line->green[j] = (unsigned char)Previous_Green;
  407. line->blue[j] = (unsigned char)(((creg & 0xf) << 4) + (creg & 0xf));
  408. Previous_Blue = (int)line->blue[j];
  409. break;
  410. case 2:
  411. line->red[j] = (unsigned char)(((creg & 0xf) << 4) + (creg & 0xf));
  412. Previous_Red = (int)line->red[j];
  413. line->green[j] = (unsigned char)Previous_Green;
  414. line->blue[j] = (unsigned char)Previous_Blue;
  415. break;
  416. case 3:
  417. line->red[j] = (unsigned char)Previous_Red;
  418. line->green[j] = (unsigned char)(((creg & 0xf) << 4) + (creg & 0xf));
  419. Previous_Green = (int)line->green[j];
  420. line->blue[j] = (unsigned char)Previous_Blue;
  421. break;
  422. }
  423. }
  424. else
  425. {
  426. if (nPlanes == 24)
  427. {
  428. line = &Image->data.rgb_lines[i];
  429. line->red[j] = (unsigned char)((creg >> 16) & 0xFF);
  430. line->green[j] = (unsigned char)((creg >> 8) & 0xFF);
  431. line->blue[j] = (unsigned char)(creg & 0xFF);
  432. }
  433. else
  434. {
  435. if (creg > (unsigned long)Image->Colour_Map_Size)
  436. {
  437. Error("Error - IFF color out of range in image.\n");
  438. }
  439. Image->data.map_lines[i][j] = (char)creg;
  440. }
  441. }
  442. mask >>= 1;
  443. if (mask == 0)
  444. {
  445. mask = 0x80;
  446. byte_index++;
  447. }
  448. }
  449. }
  450. if (row_bytes != NULL)
  451. {
  452. for (i = 0; i < nPlanes; i++)
  453. {
  454. POV_FREE(row_bytes[i]);
  455. }
  456. POV_FREE(row_bytes);
  457. }
  458. if (f != NULL) /* -hdf99- */
  459. {
  460. fclose(f);
  461. }
  462. return;
  463. default:
  464. for (i = 0; (long)i < Chunk_Header.size; i++)
  465. {
  466. if (getc(f) == EOF)
  467. {
  468. iff_error();
  469. }
  470. }
  471. break;
  472. }
  473. }
  474. }