TARGA.C 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358
  1. /****************************************************************************
  2. * targa.c
  3. *
  4. * This module contains the code to read and write the Targa output file
  5. * format.
  6. *
  7. * from Persistence of Vision(tm) Ray Tracer
  8. * Copyright 1996,1999 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. * NOTICE: This source code file is provided so that users may experiment
  11. * with enhancements to POV-Ray and to port the software to platforms other
  12. * than those supported by the POV-Ray Team. There are strict rules under
  13. * which you are permitted to use this file. The rules are in the file
  14. * named POVLEGAL.DOC which should be distributed with this file.
  15. * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. * Team Coordinator by email to team-coord@povray.org or visit us on the web at
  17. * http://www.povray.org. The latest version of POV-Ray may be found at this site.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. * Modifications by Hans-Detlev Fink, January 1999, used with permission.
  24. *
  25. *****************************************************************************/
  26. /****************************************************************************
  27. *
  28. * Explanation:
  29. *
  30. * -
  31. *
  32. * ---
  33. *
  34. * May 1994 : Support for 24-bit RLE Targa output files added: John Baily
  35. * and David Payne.
  36. *
  37. * Jul 1994 : Resume trace support and minor algorithm fix (one more still
  38. * needed, see comments in Write_Targa_Line); resume will force
  39. * Targa format to match the original trace format -- the T or C
  40. * format flag is adjusted as necessary: Charles Marslett,
  41. *
  42. * Jun 1995 : Added support for 32-bit Targa input and output files.
  43. * The alpha channel has a value of 0 for 100% transparency
  44. * and a value of 255 for 0% transparency. [DB]
  45. *
  46. *****************************************************************************/
  47. #include "frame.h"
  48. #include "povproto.h"
  49. #include "povray.h"
  50. #include "targa.h"
  51. /*****************************************************************************
  52. * Local preprocessor defines
  53. ******************************************************************************/
  54. #define boolean int
  55. /*****************************************************************************
  56. * Local typedefs
  57. ******************************************************************************/
  58. typedef struct pix
  59. {
  60. DBL blue, green, red, transm;
  61. } pix;
  62. /*****************************************************************************
  63. * Local variables
  64. ******************************************************************************/
  65. static int Targa_Line_Number;
  66. static unsigned char idbuf[256];
  67. /*****************************************************************************
  68. * Static functions
  69. ******************************************************************************/
  70. static void convert_targa_color (IMAGE_COLOUR *, unsigned, unsigned char *);
  71. static int Open_Targa_File (FILE_HANDLE *handle, char *name, int *width, int *height, int buffer_size, int mode);
  72. static void Write_Targa_Line (FILE_HANDLE *handle, COLOUR *line_data, int line_number);
  73. static int Read_Targa_Line (FILE_HANDLE *handle, COLOUR *line_data, int *line_number);
  74. static void Close_Targa_File (FILE_HANDLE *handle);
  75. static void Write_Targa_Pixel (FILE_HANDLE *handle, DBL b, DBL g, DBL r, DBL f);
  76. /*****************************************************************************
  77. *
  78. * FUNCTION
  79. *
  80. * Get_Targa_File_Handle
  81. *
  82. * INPUT
  83. *
  84. * OUTPUT
  85. *
  86. * RETURNS
  87. *
  88. * AUTHOR
  89. *
  90. * POV-Ray Team
  91. *
  92. * DESCRIPTION
  93. *
  94. * -
  95. *
  96. * CHANGES
  97. *
  98. * -
  99. *
  100. ******************************************************************************/
  101. FILE_HANDLE *Get_Targa_File_Handle()
  102. {
  103. FILE_HANDLE *handle;
  104. handle = (FILE_HANDLE *)POV_MALLOC(sizeof(FILE_HANDLE), "TGA file handle");
  105. handle->Open_File_p = Open_Targa_File;
  106. handle->Write_Line_p = Write_Targa_Line;
  107. handle->Read_Line_p = Read_Targa_Line;
  108. handle->Read_Image_p = Read_Targa_Image;
  109. handle->Close_File_p = Close_Targa_File;
  110. handle->file = NULL;
  111. handle->buffer = NULL;
  112. handle->buffer_size = 0;
  113. return(handle);
  114. }
  115. /*****************************************************************************
  116. *
  117. * FUNCTION
  118. *
  119. * Open_Targa_File
  120. *
  121. * INPUT
  122. *
  123. * OUTPUT
  124. *
  125. * RETURNS
  126. *
  127. * AUTHOR
  128. *
  129. * POV-Ray Team
  130. *
  131. * DESCRIPTION
  132. *
  133. * -
  134. *
  135. * CHANGES
  136. *
  137. * Jun 1995 : Added code for 32 bit Targa files. [DB]
  138. *
  139. * Sept 1995: Modified header output for Targa files. [AED]
  140. *
  141. ******************************************************************************/
  142. static int Open_Targa_File (FILE_HANDLE *handle, char *name, int *width, int *height, int buffer_size, int mode)
  143. {
  144. unsigned char tgaheader[18];
  145. handle->mode = mode;
  146. handle->filename = name;
  147. Targa_Line_Number = 0;
  148. switch (mode)
  149. {
  150. case READ_MODE:
  151. /* We can't resume from stdout. */
  152. if (opts.Options & TO_STDOUT ||
  153. (handle->file = fopen(name, READ_BINFILE_STRING)) == NULL)
  154. {
  155. Status_Info("\n");
  156. return(0);
  157. }
  158. /* Read targa header information. */
  159. if (fread(tgaheader, 18, 1, handle->file) != 1)
  160. {
  161. return(0);
  162. }
  163. /* Decipher the header information */
  164. switch (tgaheader[2])
  165. {
  166. case 2 : opts.OutputFormat = 'T'; break;
  167. case 10 : opts.OutputFormat = 'C'; break;
  168. default : return(0);
  169. }
  170. switch (tgaheader[16])
  171. {
  172. case 24 : break;
  173. case 32 : opts.Options |= OUTPUT_ALPHA; break;
  174. default : return(0);
  175. }
  176. /* First_Column set to x offset. Bytes 8, 9 */
  177. opts.First_Column = tgaheader[8] + (tgaheader[9] << 8);
  178. /* First line set to y offset. Bytes 10, 11 */
  179. opts.First_Line = Targa_Line_Number = tgaheader[10] + (tgaheader[11]<<8);
  180. handle->width = *width = tgaheader[12] + (tgaheader[13] << 8);
  181. handle->height = *height = tgaheader[14] + (tgaheader[15] << 8);
  182. handle->buffer_size = buffer_size;
  183. Status_Info("\nResuming interrupted trace from %s",handle->filename);
  184. break;
  185. case WRITE_MODE:
  186. if (opts.Options & TO_STDOUT)
  187. {
  188. buffer_size = 0;
  189. handle->file = stdout;
  190. }
  191. else if ((handle->file = fopen (name, WRITE_BINFILE_STRING)) == NULL)
  192. {
  193. return(0);
  194. }
  195. if (buffer_size != 0)
  196. {
  197. handle->buffer = (char *)POV_MALLOC((size_t)buffer_size, "TGA file buffer");
  198. setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
  199. }
  200. /* Output TGA file header info */
  201. putc(0, handle->file); /* Byte 0 - Length of Image ID field */
  202. putc(0, handle->file); /* Byte 1 - Color map type (0 is no color map) */
  203. switch(opts.OutputFormat) /* Byte 2 - TGA file type */
  204. {
  205. case 't': /* Uncompressed True-Color Image */
  206. case 'T':
  207. case 's':
  208. case 'S': putc(2, handle->file); break;
  209. case 'c': /* Run-length compressed True-Color Image */
  210. case 'C': putc(10, handle->file); break;
  211. }
  212. putc(0, handle->file); /* Byte 3 - Index of first color map entry LSB */
  213. putc(0, handle->file); /* Byte 4 - Index of first color map entry MSB */
  214. putc(0, handle->file); /* Byte 5 - Color map length LSB */
  215. putc(0, handle->file); /* Byte 6 - Color map legth MSB */
  216. putc(0, handle->file); /* Byte 7 - Color map size */
  217. /* x origin set to "First_Column" Bytes 8, 9 */
  218. putc(opts.First_Column % 256, handle->file);
  219. putc(opts.First_Column / 256, handle->file);
  220. /* y origin set to "First_Line" Bytes 10, 11 */
  221. putc(opts.First_Line % 256, handle->file);
  222. putc(opts.First_Line / 256, handle->file);
  223. /* write width and height Bytes 12 - 15 */
  224. putc(*width % 256, handle->file);
  225. putc(*width / 256, handle->file);
  226. putc(*height % 256, handle->file);
  227. putc(*height / 256, handle->file);
  228. /* We write 24 or 32 bits/pixel (16 million colors and alpha channel)
  229. * and also store the orientation and Alpha channel depth. Bytes 16, 17.
  230. */
  231. if (opts.Options & OUTPUT_ALPHA)
  232. {
  233. putc(32, handle->file); /* 32 bits/pixel (BGRA) */
  234. putc(0x28, handle->file); /* Data starts at top left, 8 bits Alpha */
  235. }
  236. else
  237. {
  238. putc(24, handle->file); /* 24 bits/pixel (BGR) */
  239. putc(0x20, handle->file); /* Data starts at top left, 0 bits Alpha */
  240. }
  241. /* TGA file Image ID field data would go here (up to 255 chars) */
  242. handle->width = *width;
  243. handle->height = *height;
  244. handle->buffer_size = buffer_size;
  245. break;
  246. case APPEND_MODE:
  247. if (opts.Options & TO_STDOUT)
  248. {
  249. buffer_size = 0;
  250. handle->file = stdout;
  251. }
  252. else if ((handle->file = fopen (name, APPEND_BINFILE_STRING)) == NULL)
  253. {
  254. return(0);
  255. }
  256. else if (buffer_size != 0)
  257. {
  258. handle->buffer = (char *)POV_MALLOC((size_t)buffer_size, "TGA file buffer");
  259. setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
  260. }
  261. break;
  262. }
  263. return(1);
  264. }
  265. /*****************************************************************************
  266. *
  267. * FUNCTION
  268. *
  269. * Write_Targa_Pixel
  270. *
  271. * INPUT
  272. *
  273. * handle - Current file handel
  274. * r, g, b, f - Color values to write
  275. *
  276. * OUTPUT
  277. *
  278. * RETURNS
  279. *
  280. * AUTHOR
  281. *
  282. * Dan Farmer
  283. *
  284. * DESCRIPTION :
  285. *
  286. * Moves redundant code to a single function. Adding 16 bit grayscale
  287. * conditional code to each occurance of writing a pixel was getting a bit
  288. * too wordy.
  289. *
  290. * CHANGES
  291. *
  292. * Jun 1995 : Added code for 32 bit Targa files. [DB]
  293. *
  294. * Sept 1995: Modified handling of Alpha channel to use only opts.Options
  295. * Sept 1995: Modified handling of grayscale to use only opts.Options
  296. *
  297. ******************************************************************************/
  298. static void Write_Targa_Pixel (FILE_HANDLE *handle, DBL b, DBL g, DBL r, DBL f)
  299. {
  300. unsigned int gray;
  301. if (opts.Options & HF_GRAY_16)
  302. {
  303. /* Ouput heightfield in POV red/green format */
  304. gray = ((0.30 * r) + (0.59 * g) + (0.11 * b)) * 65535;
  305. if ((putc(0 , handle->file) == EOF) ||
  306. (putc(gray & 0xFF, handle->file) == EOF) ||
  307. (putc((gray >> 8) & 0xFF, handle->file) == EOF))
  308. {
  309. Error("Error writing TGA output data to %s.\n",handle->filename);
  310. }
  311. }
  312. else
  313. {
  314. /* Normal 24/32 bit pixel coloring */
  315. if ((putc((int) floor(b * 255.0), handle->file) == EOF) ||
  316. (putc((int) floor(g * 255.0), handle->file) == EOF) ||
  317. (putc((int) floor(r * 255.0), handle->file) == EOF))
  318. {
  319. Error("Error writing TGA output data to %s.\n",handle->filename);
  320. }
  321. if (opts.Options & OUTPUT_ALPHA)
  322. {
  323. if (putc((int) floor((1.0 - f) * 255.0), handle->file) == EOF)
  324. {
  325. Error("Error writing TGA output data to %s.\n",handle->filename);
  326. }
  327. }
  328. }
  329. }
  330. /*****************************************************************************
  331. *
  332. * FUNCTION
  333. *
  334. * Write_Targa_Line
  335. *
  336. * INPUT
  337. *
  338. * OUTPUT
  339. *
  340. * RETURNS
  341. *
  342. * AUTHOR
  343. *
  344. * POV-Ray Team
  345. *
  346. * DESCRIPTION
  347. *
  348. * -
  349. *
  350. * CHANGES
  351. *
  352. * Jun 1995 : Added code for 32 bit Targa files. [DB]
  353. *
  354. ******************************************************************************/
  355. static void Write_Targa_Line (FILE_HANDLE *handle, COLOUR *line_data, int line_number)
  356. {
  357. register int x;
  358. int ptype, cnt, llen, startx;
  359. boolean writenow;
  360. pix curpix, nexpix;
  361. switch (opts.OutputFormat)
  362. {
  363. case 't':
  364. case 'T':
  365. case 's':
  366. case 'S':
  367. for (x = 0; x < handle->width; x++)
  368. {
  369. Write_Targa_Pixel (handle, line_data[x][BLUE], line_data[x][GREEN], line_data[x][RED], line_data[x][TRANSM]);
  370. }
  371. break;
  372. case 'c':
  373. case 'C':
  374. llen = handle->width;
  375. startx = 0;
  376. cnt = 1;
  377. curpix.blue = line_data[startx][BLUE];
  378. curpix.green = line_data[startx][GREEN];
  379. curpix.red = line_data[startx][RED];
  380. curpix.transm = line_data[startx][TRANSM];
  381. ptype = 0;
  382. writenow = FALSE;
  383. for (;;)
  384. {
  385. nexpix.blue = line_data[startx+cnt][BLUE];
  386. nexpix.green = line_data[startx+cnt][GREEN];
  387. nexpix.red = line_data[startx+cnt][RED];
  388. nexpix.transm = line_data[startx+cnt][TRANSM];
  389. if ((nexpix.red == curpix.red) && (nexpix.blue == curpix.blue) &&
  390. (nexpix.green == curpix.green) && (nexpix.transm == curpix.transm))
  391. {
  392. if (ptype == 0)
  393. {
  394. cnt++;
  395. if ((cnt >= 128) || ((startx + cnt) >= llen))
  396. {
  397. writenow = TRUE;
  398. }
  399. }
  400. else
  401. {
  402. cnt--;
  403. writenow = TRUE;
  404. }
  405. }
  406. else
  407. {
  408. if ((ptype == 1) || (cnt <= 1))
  409. {
  410. ptype = 1;
  411. curpix = nexpix;
  412. cnt++;
  413. if ((cnt >= 128) || ((startx + cnt) >= llen))
  414. {
  415. writenow = TRUE;
  416. }
  417. }
  418. else
  419. {
  420. writenow = TRUE;
  421. }
  422. }
  423. if (writenow)
  424. {
  425. /* This test SHOULD be unnecessary! However, it isn't! [CWM] */
  426. if (startx + cnt > llen)
  427. {
  428. cnt = llen - startx;
  429. }
  430. if (ptype == 0)
  431. {
  432. putc((int) ((cnt - 1) | 0x80), handle->file);
  433. Write_Targa_Pixel (handle, curpix.blue, curpix.green, curpix.red, curpix.transm);
  434. curpix = nexpix;
  435. }
  436. else
  437. {
  438. putc((int) cnt - 1, handle->file);
  439. for (x = 0; x < cnt; x++)
  440. {
  441. Write_Targa_Pixel (handle,
  442. line_data[startx+x][BLUE], line_data[startx+x][GREEN],
  443. line_data[startx+x][RED], line_data[startx+x][TRANSM]);
  444. }
  445. }
  446. startx = startx + cnt;
  447. writenow = FALSE;
  448. ptype = 0;
  449. cnt = 1;
  450. if (startx >= llen)
  451. {
  452. break; /* Exit while */
  453. }
  454. }
  455. }
  456. break; /* End of case */
  457. }
  458. if (handle->buffer_size == 0)
  459. {
  460. /* Close and reopen file (if not stdout) for integrity in case we crash */
  461. fflush(handle->file);
  462. if (!(opts.Options & TO_STDOUT))
  463. {
  464. handle->file = freopen(handle->filename, APPEND_BINFILE_STRING, handle->file);
  465. }
  466. }
  467. }
  468. /*****************************************************************************
  469. *
  470. * FUNCTION
  471. *
  472. * Read_Targa_Line
  473. *
  474. * INPUT
  475. *
  476. * OUTPUT
  477. *
  478. * RETURNS
  479. *
  480. * AUTHOR
  481. *
  482. * POV-Ray Team
  483. *
  484. * DESCRIPTION
  485. *
  486. * -
  487. *
  488. * CHANGES
  489. *
  490. * Jun 1995 : Added code for 32 bit Targa files. [DB]
  491. *
  492. ******************************************************************************/
  493. static int Read_Targa_Line (FILE_HANDLE *handle, COLOUR *line_data, int *line_number)
  494. {
  495. int x, data, cnt;
  496. DBL rdata, gdata, bdata, fdata;
  497. switch (opts.OutputFormat)
  498. {
  499. case 't':
  500. case 'T':
  501. case 's':
  502. case 'S':
  503. for (x = 0; x < handle->width; x++)
  504. {
  505. /* Read the BLUE data byte. If EOF is reached on the first
  506. * character read, then this line hasn't been rendered yet.
  507. * Return 0. If an EOF occurs somewhere within the line, this
  508. * is an error - return -1.
  509. */
  510. if ((data = getc(handle->file)) == EOF)
  511. {
  512. if (x == 0)
  513. {
  514. return(0);
  515. }
  516. else
  517. {
  518. return(-1);
  519. }
  520. }
  521. line_data[x][BLUE] = (DBL) data / 255.0;
  522. /* Read the GREEN data byte. */
  523. if ((data = getc(handle->file)) == EOF)
  524. {
  525. return(-1);
  526. }
  527. line_data[x][GREEN] = (DBL) data / 255.0;
  528. /* Read the RED data byte. */
  529. if ((data = getc(handle->file)) == EOF)
  530. {
  531. return(-1);
  532. }
  533. line_data[x][RED] = (DBL) data / 255.0;
  534. /* Read alpha channel. */
  535. if (opts.Options & OUTPUT_ALPHA)
  536. {
  537. if ((data = getc(handle->file)) == EOF)
  538. {
  539. return(-1);
  540. }
  541. line_data[x][TRANSM] = 1.0 - (DBL)data / 255.0;
  542. }
  543. else
  544. {
  545. line_data[x][TRANSM] = 0.0;
  546. }
  547. }
  548. break;
  549. case 'c':
  550. case 'C':
  551. cnt = 0;
  552. do
  553. {
  554. if ((data = getc(handle->file)) == EOF)
  555. {
  556. if (cnt == 0)
  557. {
  558. return(0);
  559. }
  560. else
  561. {
  562. return(-1);
  563. }
  564. }
  565. if (data & 0x80)
  566. {
  567. x = data & 0x7F;
  568. if ((data = getc(handle->file)) == EOF)
  569. {
  570. return(-1);
  571. }
  572. bdata = (DBL) data / 255.0;
  573. if ((data = getc(handle->file)) == EOF)
  574. {
  575. return(-1);
  576. }
  577. gdata = (DBL) data / 255.0;
  578. if ((data = getc(handle->file)) == EOF)
  579. {
  580. return(-1);
  581. }
  582. rdata = (DBL) data / 255.0;
  583. /* Read alpha channel if any. */
  584. if (opts.Options & OUTPUT_ALPHA)
  585. {
  586. if ((data = getc(handle->file)) == EOF)
  587. {
  588. return(-1);
  589. }
  590. fdata = 1.0 - (DBL)data / 255.0;
  591. }
  592. else
  593. {
  594. fdata = 0.0;
  595. }
  596. do
  597. {
  598. line_data[cnt][BLUE] = bdata;
  599. line_data[cnt][GREEN] = gdata;
  600. line_data[cnt][RED] = rdata;
  601. line_data[cnt][TRANSM] = fdata;
  602. cnt++;
  603. }
  604. while (--x != -1);
  605. }
  606. else
  607. {
  608. x = data & 0x7F;
  609. do
  610. {
  611. if ((data = getc(handle->file)) == EOF)
  612. {
  613. return(-1);
  614. }
  615. bdata = (DBL) data / 255.0;
  616. if ((data = getc(handle->file)) == EOF)
  617. {
  618. return(-1);
  619. }
  620. gdata = (DBL) data / 255.0;
  621. if ((data = getc(handle->file)) == EOF)
  622. {
  623. return(-1);
  624. }
  625. rdata = (DBL) data / 255.0;
  626. /* Read alpha channel if any. */
  627. if (opts.Options & OUTPUT_ALPHA)
  628. {
  629. if ((data = getc(handle->file)) == EOF)
  630. {
  631. return(-1);
  632. }
  633. fdata = 1.0 - (DBL)data / 255.0;
  634. }
  635. else
  636. {
  637. fdata = 0.0;
  638. }
  639. line_data[cnt][BLUE] = bdata;
  640. line_data[cnt][GREEN] = gdata;
  641. line_data[cnt][RED] = rdata;
  642. line_data[cnt][TRANSM] = fdata;
  643. cnt++;
  644. }
  645. while (--x != -1);
  646. }
  647. }
  648. while (cnt < handle->width);
  649. if (cnt != handle->width)
  650. {
  651. return(-1);
  652. }
  653. break;
  654. }
  655. *line_number = Targa_Line_Number++;
  656. return(1);
  657. }
  658. /*****************************************************************************
  659. *
  660. * FUNCTION
  661. *
  662. * Close_Targa_File
  663. *
  664. * INPUT
  665. *
  666. * OUTPUT
  667. *
  668. * RETURNS
  669. *
  670. * AUTHOR
  671. *
  672. * POV-Ray Team
  673. *
  674. * DESCRIPTION
  675. *
  676. * -
  677. *
  678. * CHANGES
  679. *
  680. * -
  681. *
  682. ******************************************************************************/
  683. static void Close_Targa_File (FILE_HANDLE *handle)
  684. {
  685. if (handle->file)
  686. {
  687. fflush(handle->file);
  688. if (!(opts.Options & TO_STDOUT))
  689. fclose (handle->file);
  690. }
  691. if (handle->buffer != NULL)
  692. {
  693. POV_FREE (handle->buffer);
  694. }
  695. handle->file = NULL;
  696. handle->buffer = NULL;
  697. }
  698. /*****************************************************************************
  699. *
  700. * FUNCTION
  701. *
  702. * convert_targa_color
  703. *
  704. * INPUT
  705. *
  706. * OUTPUT
  707. *
  708. * RETURNS
  709. *
  710. * AUTHOR
  711. *
  712. * POV-Ray Team
  713. *
  714. * DESCRIPTION
  715. *
  716. * -
  717. *
  718. * CHANGES
  719. *
  720. * -
  721. *
  722. ******************************************************************************/
  723. static void convert_targa_color(IMAGE_COLOUR *tcolor, unsigned pixelsize, unsigned char *bytes)
  724. {
  725. switch (pixelsize)
  726. {
  727. case 1:
  728. tcolor->Red = bytes[0];
  729. tcolor->Green = bytes[0];
  730. tcolor->Blue = bytes[0];
  731. tcolor->Filter = 0;
  732. tcolor->Transmit = 0;
  733. break;
  734. case 2:
  735. tcolor->Red = ((bytes[1] & 0x7c) << 1);
  736. tcolor->Green = (((bytes[1] & 0x03) << 3) | ((bytes[0] & 0xe0) >> 5)) << 3;
  737. tcolor->Blue = (bytes[0] & 0x1f) << 3;
  738. tcolor->Filter = 0;
  739. tcolor->Transmit = 255 - (bytes[1] & 0x80 ? 255 : 0);
  740. break;
  741. case 3:
  742. tcolor->Red = bytes[2];
  743. tcolor->Green = bytes[1];
  744. tcolor->Blue = bytes[0];
  745. tcolor->Filter = 0;
  746. tcolor->Transmit = 0;
  747. break;
  748. case 4:
  749. tcolor->Red = bytes[2];
  750. tcolor->Green = bytes[1];
  751. tcolor->Blue = bytes[0];
  752. tcolor->Filter = 0;
  753. tcolor->Transmit = 255 - bytes[3];
  754. break;
  755. default:
  756. Error("Bad pixelsize in TGA color.\n");
  757. }
  758. }
  759. /*****************************************************************************
  760. *
  761. * FUNCTION
  762. *
  763. * Read_Targa_Image
  764. *
  765. * INPUT
  766. *
  767. * OUTPUT
  768. *
  769. * RETURNS
  770. *
  771. * AUTHOR
  772. *
  773. * POV-Ray Team
  774. *
  775. * DESCRIPTION
  776. *
  777. * Reads a Targa image into an RGB image buffer. Handles 8, 16, 24, 32 bit
  778. * formats. Raw or color mapped. Simple raster and RLE compressed pixel
  779. * encoding. Right side up or upside down orientations.
  780. *
  781. * CHANGES
  782. *
  783. * Jun 1995 : Added code for 32 bit Targa files. [DB]
  784. *
  785. ******************************************************************************/
  786. void Read_Targa_Image(IMAGE *Image, char *name)
  787. {
  788. int h;
  789. int temp;
  790. unsigned i, j, k;
  791. unsigned char cflag = 0, *map_line = NULL, bytes[4], tgaheader[18];
  792. unsigned ftype, idlen, cmlen, cmsiz, psize, orien;
  793. unsigned width, height;
  794. FILE *filep;
  795. IMAGE_LINE *line_data = NULL;
  796. IMAGE_COLOUR *cmap, pixel;
  797. /* Start by trying to open the file */
  798. if ((filep = Locate_File(name, READ_BINFILE_STRING,".tga",".TGA",NULL,TRUE)) == NULL)
  799. {
  800. Error ("Error opening TGA image.\n");
  801. return; /* -hdf99- */
  802. }
  803. if (fread(tgaheader, 18, 1, filep) != 1)
  804. {
  805. Error ("Error reading header of TGA image.\n");
  806. return; /* -hdf99- */
  807. }
  808. /* Decipher the header information */
  809. idlen = tgaheader[ 0];
  810. ftype = tgaheader[ 2];
  811. cmlen = tgaheader[ 5] + (tgaheader[ 6] << 8);
  812. cmsiz = tgaheader[ 7] / 8;
  813. width = tgaheader[12] + (tgaheader[13] << 8);
  814. height = tgaheader[14] + (tgaheader[15] << 8);
  815. psize = tgaheader[16] / 8;
  816. orien = tgaheader[17] & 0x20; /* Right side up ? */
  817. Image->iwidth = width;
  818. Image->iheight = height;
  819. Image->width = (DBL)width;
  820. Image->height = (DBL)height;
  821. Image->Colour_Map_Size = cmlen;
  822. Image->Colour_Map = NULL;
  823. /* Determine if this is a supported Targa type */
  824. if (ftype == 9 || ftype == 10 || ftype == 11)
  825. {
  826. cflag = 1;
  827. }
  828. else
  829. {
  830. if (ftype == 1 || ftype == 2 || ftype == 3)
  831. {
  832. cflag = 0;
  833. }
  834. else
  835. {
  836. Error("Unsupported file type %d in TGA image.\n", ftype);
  837. }
  838. }
  839. /* Skip over the picture ID information */
  840. if (idlen > 0 && fread(idbuf, idlen, 1, filep) != 1)
  841. {
  842. Error ("Error reading header from TGA image.\n");
  843. }
  844. /* Read in the the color map (if any) */
  845. if (cmlen > 0)
  846. {
  847. if (psize != 1)
  848. {
  849. Error("Unsupported color map bit depth (%d bpp) in TGA image.\n",
  850. psize * 8);
  851. }
  852. cmap = (IMAGE_COLOUR *)POV_MALLOC(cmlen * sizeof(IMAGE_COLOUR), "TGA color map");
  853. for (i = 0; i < cmlen; i++)
  854. {
  855. for (j = 0; j < cmsiz; j++)
  856. {
  857. if ((temp = fgetc(filep)) == EOF)
  858. {
  859. Error("Error reading color map from TGA image.\n");
  860. }
  861. else
  862. {
  863. bytes[j] = (unsigned char)temp;
  864. }
  865. }
  866. convert_targa_color(&cmap[i], cmsiz, bytes);
  867. }
  868. Image->Colour_Map = cmap;
  869. }
  870. else
  871. {
  872. Image->Colour_Map = NULL;
  873. }
  874. /* Allocate the buffer for the image */
  875. if (cmlen > 0)
  876. {
  877. Image->data.map_lines = (unsigned char **)POV_MALLOC(height * sizeof(unsigned char *), "TGA image");
  878. }
  879. else
  880. {
  881. Image->data.rgb_lines = (IMAGE_LINE *)POV_MALLOC(height * sizeof(IMAGE_LINE), "TGA image");
  882. }
  883. for (i = 0; i < height; i++)
  884. {
  885. k = width * sizeof(unsigned char);
  886. if (cmlen > 0)
  887. {
  888. map_line = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
  889. Image->data.map_lines[i] = map_line;
  890. }
  891. else
  892. {
  893. line_data = &Image->data.rgb_lines[i];
  894. line_data->red = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
  895. line_data->green = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
  896. line_data->blue = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
  897. if (psize > 3)
  898. {
  899. line_data->transm = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
  900. }
  901. else
  902. {
  903. line_data->transm = (unsigned char *)NULL;
  904. }
  905. }
  906. }
  907. /* Read the image into the buffer */
  908. if (cflag)
  909. {
  910. /* RLE compressed images */
  911. if (cmlen > 0)
  912. {
  913. if (orien)
  914. {
  915. map_line = Image->data.map_lines[0];
  916. }
  917. else
  918. {
  919. map_line = Image->data.map_lines[height-1];
  920. }
  921. }
  922. else
  923. {
  924. if (orien)
  925. {
  926. line_data = &Image->data.rgb_lines[0];
  927. }
  928. else
  929. {
  930. line_data = &Image->data.rgb_lines[height-1];
  931. }
  932. }
  933. i = 0; /* row counter */
  934. j = 0; /* column counter */
  935. while (i < height)
  936. {
  937. /* Grab a header */
  938. if ((h = fgetc(filep)) == EOF)
  939. {
  940. Error("Error reading data from TGA image.\n");
  941. }
  942. if (h & 0x80)
  943. {
  944. /* Repeat buffer */
  945. h &= 0x7F;
  946. for (k = 0; k < psize; k++)
  947. {
  948. if ((temp = fgetc(filep)) == EOF)
  949. {
  950. Error("Error reading data from TGA image.\n");
  951. }
  952. else
  953. {
  954. bytes[k] = (unsigned char)temp;
  955. }
  956. }
  957. if (cmlen == 0)
  958. {
  959. convert_targa_color(&pixel, psize, bytes);
  960. }
  961. for (; h >= 0; h--)
  962. {
  963. if (cmlen > 0)
  964. {
  965. map_line[j] = bytes[0];
  966. }
  967. else
  968. {
  969. line_data->red[j] = (unsigned char)pixel.Red;
  970. line_data->green[j] = (unsigned char)pixel.Green;
  971. line_data->blue[j] = (unsigned char)pixel.Blue;
  972. if (psize > 3)
  973. {
  974. line_data->transm[j] = (unsigned char)pixel.Transmit;
  975. }
  976. }
  977. if (++j == width)
  978. {
  979. i++;
  980. if (cmlen > 0)
  981. {
  982. if (orien)
  983. {
  984. map_line = Image->data.map_lines[i];
  985. }
  986. else
  987. {
  988. map_line = Image->data.map_lines[height-i-1];
  989. }
  990. }
  991. else
  992. {
  993. line_data += (orien ? 1 : -1);
  994. }
  995. j = 0;
  996. }
  997. }
  998. }
  999. else
  1000. {
  1001. /* Copy buffer */
  1002. for (; h >= 0; h--)
  1003. {
  1004. for (k = 0; k < psize ; k++)
  1005. {
  1006. if ((temp = fgetc(filep)) == EOF)
  1007. {
  1008. Error("Error reading data from TGA image.\n");
  1009. }
  1010. else
  1011. {
  1012. bytes[k] = (unsigned char)temp;
  1013. }
  1014. }
  1015. if (cmlen > 0)
  1016. {
  1017. map_line[j] = bytes[0];
  1018. }
  1019. else
  1020. {
  1021. convert_targa_color(&pixel, psize, bytes);
  1022. line_data->red[j] = (unsigned char)pixel.Red;
  1023. line_data->green[j] = (unsigned char)pixel.Green;
  1024. line_data->blue[j] = (unsigned char)pixel.Blue;
  1025. if (psize > 3)
  1026. {
  1027. line_data->transm[j] = (unsigned char)pixel.Transmit;
  1028. }
  1029. }
  1030. if (++j == width)
  1031. {
  1032. i++;
  1033. if (cmlen > 0)
  1034. {
  1035. if (orien)
  1036. {
  1037. map_line = Image->data.map_lines[i];
  1038. }
  1039. else
  1040. {
  1041. map_line = Image->data.map_lines[height-i-1];
  1042. }
  1043. }
  1044. else
  1045. {
  1046. line_data += (orien ? 1 : -1);
  1047. }
  1048. j = 0;
  1049. }
  1050. }
  1051. }
  1052. }
  1053. }
  1054. else
  1055. {
  1056. /* Simple raster image file, read in all of the pixels */
  1057. if (cmlen == 0)
  1058. {
  1059. if (orien)
  1060. {
  1061. line_data = &Image->data.rgb_lines[0];
  1062. }
  1063. else
  1064. {
  1065. line_data = &Image->data.rgb_lines[height-1];
  1066. }
  1067. }
  1068. for (i = 0; i < height; i++)
  1069. {
  1070. if (cmlen > 0)
  1071. {
  1072. if (orien)
  1073. {
  1074. map_line = Image->data.map_lines[i];
  1075. }
  1076. else
  1077. {
  1078. map_line = Image->data.map_lines[height-i-1];
  1079. }
  1080. }
  1081. for (j = 0; j < width; j++)
  1082. {
  1083. for (k = 0; k < psize; k++)
  1084. {
  1085. if ((temp = fgetc(filep)) == EOF)
  1086. {
  1087. Error("Error reading data from TGA image.\n");
  1088. }
  1089. else
  1090. {
  1091. bytes[k] = (unsigned char)temp;
  1092. }
  1093. }
  1094. if (cmlen > 0)
  1095. {
  1096. map_line[j] = bytes[0];
  1097. }
  1098. else
  1099. {
  1100. convert_targa_color(&pixel, psize, bytes);
  1101. line_data->red[j] = (unsigned char)pixel.Red;
  1102. line_data->green[j] = (unsigned char)pixel.Green;
  1103. line_data->blue[j] = (unsigned char)pixel.Blue;
  1104. if (psize > 3)
  1105. {
  1106. line_data->transm[j] = (unsigned char)pixel.Transmit;
  1107. }
  1108. }
  1109. }
  1110. if (cmlen == 0)
  1111. {
  1112. line_data += (orien ? 1 : -1);
  1113. }
  1114. }
  1115. }
  1116. /* Any data following the image is ignored. */
  1117. /* Close the image file */
  1118. fclose(filep);
  1119. }