home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Graphics / graphics-16000.iso / msdos / raytrace / rayshade / src / picture.c < prev    next >
C/C++ Source or Header  |  1992-05-01  |  12KB  |  499 lines

  1. /*
  2.  * picture.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb, Rod G. Bogart
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * $Id: picture.c,v 4.0.1.2 92/02/07 09:22:20 cek Exp Locker: cek $
  17.  *
  18.  * $Log:    picture.c,v $
  19.  * Revision 4.0.1.2  92/02/07  09:22:20  cek
  20.  * patch6: Fixed typo in MTV error message.
  21.  * 
  22.  * Revision 4.0.1.1  92/01/10  16:28:28  cek
  23.  * patch3: Added check for nonexistent patial image file.
  24.  * patch3: Fixed declaration of nrow in count_rle_rows().
  25.  * patch3: Changed level of several error messages.
  26.  * 
  27.  * Revision 4.0  91/07/17  14:47:00  kolb
  28.  * Initial version.
  29.  * 
  30.  */
  31. #include "rayshade.h"
  32. #include "picture.h"
  33. #include "viewing.h"
  34. #include "options.h"
  35. #include "stats.h"
  36.  
  37. #if defined(__WATCOMC__) || defined(__BORLANDC__)
  38. #include <io.h>
  39. #include <fcntl.h>
  40. #undef URT
  41. #define TARGA
  42. #endif
  43.  
  44. #ifdef URT
  45. unsigned char **outptr;        /* Output buffer */
  46. static int count_rle_rows();
  47. #endif
  48.  
  49. /*
  50.  * Convert floating-point (0.-1.) to unsigned char (0-255), with no gamma
  51.  * correction.
  52.  */
  53. unsigned char
  54. correct(x)
  55. Float x;
  56. {
  57.     /*
  58.      * Truncate values < 0 or > 1.
  59.      */
  60.     if (x < 0)
  61.         return 0;
  62.     if (x > 1.)
  63.         return 255;
  64.     return (unsigned char)(x * 255.);
  65. }
  66.  
  67. #ifdef URT
  68. /*
  69.  * Open image file and write RLE header.
  70.  */
  71. void
  72. PictureStart(argv)
  73. char **argv;
  74. {
  75.     char gammacom[40];
  76.  
  77.     if (Options.framenum != Options.startframe) {
  78.         /*
  79.          * We've been here before;
  80.          * write a new header and return.
  81.          */
  82.         rle_put_setup(&rle_dflt_hdr);
  83.         return;
  84.     }
  85.     /*
  86.      * If Appending, then we know that outfile is valid, 'cause
  87.      * we've already read its header.
  88.      */
  89.     if (Options.appending) {
  90. #if defined(__WATCOMC__) || defined(__BORLANDC__)
  91.             Options.pictfile = fopen(Options.imgname, "ab");
  92. #else
  93.             Options.pictfile = fopen(Options.imgname, "a");
  94. #endif
  95.         if (Options.pictfile == (FILE *)0)
  96.             RLerror(RL_PANIC, "Cannot append to %s?!\n",
  97.                     Options.imgname);
  98.         rle_dflt_hdr.rle_file = Options.pictfile;
  99.         rle_put_init(&rle_dflt_hdr);
  100.     } else {
  101.         /*
  102.          * Starting image from scatch.
  103.          */
  104.         if (Options.imgname) {
  105. #if defined(__WATCOMC__) || defined(__BORLANDC__)
  106.             Options.pictfile = fopen(Options.imgname, "wb");
  107. #else
  108.             Options.pictfile = fopen(Options.imgname, "w");
  109. #endif
  110.             if (Options.pictfile == (FILE *)NULL)
  111.                 RLerror(RL_ABORT,"Cannot open %s for writing.",
  112.                     Options.imgname);
  113.         } else
  114.             Options.pictfile = stdout;
  115.  
  116.         rle_dflt_hdr.xmax = Screen.maxx;
  117.         rle_dflt_hdr.ymax = Screen.maxy;
  118.         rle_dflt_hdr.xmin = Screen.minx;
  119.         rle_dflt_hdr.ymin = Screen.miny;
  120.         rle_dflt_hdr.alpha = Options.alpha;
  121.         if (Options.alpha)
  122.             RLE_SET_BIT(rle_dflt_hdr, RLE_ALPHA);
  123.         if (Options.exp_output) {
  124.             RLE_SET_BIT(rle_dflt_hdr, RLE_BLUE + 1);
  125.             rle_dflt_hdr.ncolors = 4;
  126.             rle_putcom("exponential_data", &rle_dflt_hdr);
  127.         }
  128.         else
  129.             rle_dflt_hdr.ncolors = 3;
  130.         /*
  131.           * Document image gamma in RLE comment area.
  132.          * Options.gamma has been inverted.
  133.           */
  134.         (void)sprintf(gammacom, "display_gamma=%g", 1./Options.gamma);
  135.         rle_putcom(gammacom, &rle_dflt_hdr);
  136.         /*
  137.           * Document command line in RLE history.
  138.           */
  139.         rle_addhist(argv, (rle_hdr *)0, &rle_dflt_hdr);
  140.         rle_dflt_hdr.rle_file = Options.pictfile;
  141.         rle_put_setup(&rle_dflt_hdr);
  142.         /*
  143.          * Flush the header.  If we don't, and LINDA forks off
  144.           * a bunch of workers, strange things will happen (they'll
  145.           * all flush the buffer when they die, and you end up with
  146.           * lots of headers at the end of the file).
  147.           */
  148.         (void)fflush(rle_dflt_hdr.rle_file);
  149.     }
  150.  
  151.     if (rle_row_alloc(&rle_dflt_hdr, &outptr) < 0)
  152.         RLerror(RL_PANIC, "Unable to allocate image memory.\n");
  153. }
  154.  
  155. /*
  156.  * Read RLE header to which we are appending in order determine
  157.  * old resolution, window location, and the like.
  158.  */
  159. void
  160. PictureSetWindow()
  161. {
  162.     if (Options.imgname == (char *)NULL)
  163.         RLerror(RL_ABORT,
  164.             "No partially-completed image file specified.\n");
  165.  
  166.     /*
  167.      * Open image and read RLE header.
  168.      */
  169. #if defined(__WATCOMC__) || defined(__BORLANDC__)
  170.     Options.pictfile = fopen(Options.imgname, "rb");
  171. #else
  172.     Options.pictfile = fopen(Options.imgname, "r");
  173. #endif
  174.     if (Options.pictfile == (FILE *)NULL) {
  175.         RLerror(RL_ABORT, "Cannot open image file %s.\n",
  176.                     Options.imgname);
  177.     }
  178.     rle_dflt_hdr.rle_file = Options.pictfile;
  179.     rle_get_setup_ok(&rle_dflt_hdr, "rayshade", Options.imgname);
  180.  
  181.     /*
  182.      * If user specified a window that does not match what's in
  183.      * the header, complain.
  184.     if (Screen.minx != UNSET && Screen.minx != rle_dflt_hdr.xmin ||
  185.         Screen.miny != UNSET && Screen.miny != rle_dflt_hdr.ymin ||
  186.         Screen.maxx != UNSET && Screen.maxx != rle_dflt_hdr.xmax ||
  187.         Screen.maxy != UNSET && Screen.maxy != rle_dflt_hdr.ymax)
  188.         RLerror(RL_ADVISE, "Image window: %d - %d, %d - %d.\n",
  189.             rle_dflt_hdr.xmin, rle_dflt_hdr.xmax,
  190.             rle_dflt_hdr.ymin, rle_dflt_hdr.ymax);
  191.      */
  192.     /*
  193.      * Set window.
  194.      */
  195.     Screen.minx = rle_dflt_hdr.xmin;
  196.     Screen.miny = rle_dflt_hdr.ymin;
  197.     Screen.maxx = rle_dflt_hdr.xmax;
  198.     Screen.maxy = rle_dflt_hdr.ymax;
  199.  
  200.     /*
  201.      * Set alpha.  Warn the user if the alpha option doesn't reflect
  202.      * what's already been rendered.
  203.      */
  204.     if (Options.alpha != rle_dflt_hdr.alpha)
  205.         RLerror(RL_WARN, "Image %s %s an alpha channel.\n",
  206.             Options.imgname,
  207.             rle_dflt_hdr.alpha ? "has" : "does not have");
  208.  
  209.     Options.alpha = rle_dflt_hdr.alpha;
  210.  
  211.     /*
  212.      * Determine number of scanlines written to file.
  213.      */
  214.     Screen.miny += count_rle_rows(&rle_dflt_hdr);
  215.     if (Screen.miny >= Screen.maxy) {
  216.         fprintf(stderr, "\"%s\" is a complete image.\n",
  217.             Options.imgname);
  218.         exit(0);
  219.     }
  220.     fprintf(Stats.fstats,"Continuing \"%s\" at scanline #%d.\n",
  221.         Options.imgname, Screen.miny);
  222.     (void)fclose(Options.pictfile);
  223. }
  224.  
  225. static int
  226. count_rle_rows( hdr )
  227. rle_hdr *hdr;
  228. {
  229.     rle_op **raw;
  230.     int *nraw, y, ynext;
  231.  
  232.     if (rle_raw_alloc( hdr, &raw, &nraw ) < 0)  {
  233.         RLerror(RL_PANIC,
  234.             "Unable to allocate memory in count_rle_rows.\n");
  235.     }
  236.  
  237.     y = hdr->ymin;
  238.     while ((ynext = rle_getraw( hdr, raw, nraw )) != 32768) {
  239.         y = ynext+1;
  240.         rle_freeraw( hdr, raw, nraw );
  241.     }
  242.  
  243.     /* Free memory. */
  244.     rle_raw_free( hdr, raw, nraw );
  245.  
  246.     return y - hdr->ymin;
  247. }
  248.  
  249. /*
  250.  * Write a scanline of output.
  251.  * "buf" is an array of Color structures of size Screen.xsize.  Each color
  252.  * component is normalized to [0, 1.].
  253.  */
  254. void
  255. PictureWriteLine(buf)
  256. Pixel *buf;
  257. {
  258.     register int i, chan;
  259.     float floats[3];
  260.     rle_pixel pixels[4];
  261.  
  262.     for(i = 0; i < Screen.xsize; i++) {
  263.         if (!Options.exp_output) {
  264.             /*
  265.              * Scale colors to fit unsigned char and check for
  266.              * over/underflow.
  267.              */
  268.             outptr[0][i] = CORRECT(buf[i].r);
  269.             outptr[1][i] = CORRECT(buf[i].g);
  270.             outptr[2][i] = CORRECT(buf[i].b);
  271.         } else {
  272.             /*
  273.              * Convert 3 floats to 4 unsigned chars for
  274.              * 'exponential_data' RLE file.
  275.              */
  276.             floats[0] = GAMMACORRECT(buf[i].r);
  277.             floats[1] = GAMMACORRECT(buf[i].g);
  278.             floats[2] = GAMMACORRECT(buf[i].b);
  279.             float_to_exp( 3, floats, pixels );
  280.             for (chan = 0; chan <= 3; chan++)
  281.                 outptr[chan][i] = pixels[chan];
  282.         }
  283.         if (Options.alpha)
  284.             /*
  285.              * Don't gamma correct alpha channel.
  286.              */
  287.             outptr[-1][i] = correct(buf[i].alpha);
  288.     }
  289.     rle_putrow(outptr, Screen.xsize, &rle_dflt_hdr);
  290. }
  291.  
  292. /*
  293.  * End the frame.
  294.  */
  295. void
  296. PictureFrameEnd()
  297. {
  298.     rle_puteof(&rle_dflt_hdr);
  299. }
  300.  
  301. /*
  302.  * Close image file.
  303.  */
  304. void
  305. PictureEnd()
  306. {
  307.     (void)fclose(Options.pictfile);
  308. }
  309.  
  310. #else /* !URT */
  311.  
  312. #ifdef TARGA
  313.  
  314. #define STORE16(c,i)    *((unsigned short*)(&(c)))=(i)
  315.  
  316. #define HEADERSIZE 18
  317. #define O_COMMENTLEN 0
  318. #define O_MAPTYPE 1
  319. #define O_FILETYPE 2
  320. #define O_MAPORG 3
  321. #define O_MAPLEN 5
  322. #define O_MAPSIZE 7
  323. #define O_XORIGIN 8
  324. #define O_YORIGIN 10
  325. #define O_HSIZE 12
  326. #define O_VSIZE 14
  327. #define O_ESIZE 16
  328. #define O_FLAGS 17
  329. #define M_ORIGIN 0x20
  330. #define T_RAWRGB 2
  331.  
  332. #include <stdlib.h>
  333. #include <string.h>
  334.  
  335. char NameSave[256];
  336. char AnimImgName[256];
  337. static int AnimFrameNum=0;
  338.  
  339. char *AnimFrameName(char *name,int num) {
  340.  
  341.     static char tmp[256];
  342. #if defined(MSDOS) || defined(__MSDOS__)
  343.     static char path[_MAX_PATH],drive[_MAX_DRIVE],
  344.        dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT];
  345.     strcpy(path,name);
  346.     _splitpath(path,drive,dir,fname,ext);
  347.     if (strlen(fname)>5)
  348.         fname[5]='\0';
  349.     sprintf(tmp,"%s%03d",fname,num);
  350.     tmp[8]='\0';
  351.     strcpy(fname,tmp);
  352.     _makepath(path,drive,dir,fname,ext);
  353.     strcpy(tmp,path);
  354. #else
  355.     sprintf(tmp,"%s.%03d",name,num);
  356. #endif
  357.     return tmp;
  358.     }
  359.  
  360. void
  361. PictureStart(argv)
  362. char **argv;
  363. {
  364.     unsigned char header[HEADERSIZE];
  365.  
  366.  
  367.     if (Options.imgname) {
  368.  
  369.         strcpy(NameSave,Options.imgname);
  370.  
  371.         if (Options.endframe>Options.startframe) {
  372.             strcpy(AnimImgName,AnimFrameName(Options.imgname,AnimFrameNum));
  373.             AnimFrameNum++;
  374.             strcpy(Options.imgname,AnimImgName);
  375.             }
  376.  
  377.         if (Options.verbose)
  378.             fprintf(Stats.fstats,"Writing Targa to: %s\n",Options.imgname);
  379.  
  380. #if defined(__WATCOMC__) || defined(__BORLANDC__)
  381.         Options.pictfile = fopen(Options.imgname, "wb");
  382. #else
  383.         Options.pictfile = fopen(Options.imgname, "w");
  384. #endif
  385.         if (Options.pictfile == (FILE *)NULL)
  386.             RLerror(RL_PANIC, "Cannot open %s for writing.",
  387.                 Options.imgname);
  388.  
  389.         strcpy(Options.imgname,NameSave);
  390.  
  391.     } else {
  392.  
  393.         if (Options.endframe>Options.startframe) {
  394.             RLerror(RL_PANIC, "Cannot output animation to stdout.");
  395.             }
  396.  
  397.         Options.pictfile = stdout;
  398. #if defined(__WATCOMC__) || defined(__BORLANDC__)
  399. #ifdef __BORLANDC__
  400.         setmode(fileno(Options.pictfile),O_BINARY);
  401. #else
  402.         setmode(Options.pictfile->_handle,O_BINARY);
  403. #endif
  404. #endif
  405.         }
  406.  
  407.     memset(header, 0, HEADERSIZE);
  408.     header[O_COMMENTLEN]=0;
  409.     header[O_FILETYPE]=T_RAWRGB;
  410.     STORE16(header[O_HSIZE], Screen.xsize);
  411.     STORE16(header[O_VSIZE], Screen.ysize);
  412.     header[O_ESIZE]=24;
  413.     header[O_FLAGS]=M_ORIGIN;    /* Pic drawn from top to bottom */
  414.     fwrite(header, HEADERSIZE, 1, Options.pictfile);
  415.  
  416.     (void)fflush(Options.pictfile);
  417. }
  418.  
  419. void
  420. PictureWriteLine(buf)
  421. Pixel *buf;
  422. {
  423.     register int i;
  424.  
  425.     for (i = 0; i < Screen.xsize; i++) {
  426.         (void)fputc((int)CORRECT(buf[i].b), Options.pictfile);
  427.         (void)fputc((int)CORRECT(buf[i].g), Options.pictfile);
  428.         (void)fputc((int)CORRECT(buf[i].r), Options.pictfile);
  429.     }
  430.     (void)fflush(Options.pictfile);
  431. }
  432.  
  433. void
  434. PictureFrameEnd()
  435. {
  436.     (void)fclose(Options.pictfile);
  437. }
  438.  
  439. void
  440. PictureEnd()
  441. {
  442.     (void)fclose(Options.pictfile);
  443. }
  444.  
  445. #else
  446.  
  447. void
  448. PictureStart(argv)
  449. char **argv;
  450. {
  451.     if (Options.imgname) {
  452. #if defined(__WATCOMC__) || defined(__BORLANDC__)
  453.         Options.pictfile = fopen(Options.imgname, "wb");
  454. #else
  455.         Options.pictfile = fopen(Options.imgname, "w");
  456. #endif
  457.         if (Options.pictfile == (FILE *)NULL)
  458.             RLerror(RL_ABORT, "Cannot open %s for writing.",
  459.                 Options.imgname);
  460.     } else
  461.         Options.pictfile = stdout;
  462.  
  463.     fprintf(Options.pictfile,"%d %d\n",Screen.xsize, Screen.ysize);
  464.  
  465.     (void)fflush(Options.pictfile);
  466. }
  467.  
  468. void
  469. PictureWriteLine(buf)
  470. Pixel *buf;
  471. {
  472.     register int i;
  473.  
  474.     for (i = 0; i < Screen.xsize; i++) {
  475.         (void)fputc((int)CORRECT(buf[i].r), Options.pictfile);
  476.         (void)fputc((int)CORRECT(buf[i].g), Options.pictfile);
  477.         (void)fputc((int)CORRECT(buf[i].b), Options.pictfile);
  478.     }
  479.     (void)fflush(Options.pictfile);
  480. }
  481.  
  482. void
  483. PictureFrameEnd()
  484. {
  485.     /*
  486.      * Don't do anything -- generic format has no end-of-image marker.
  487.      */
  488. }
  489.  
  490. void
  491. PictureEnd()
  492. {
  493.     (void)fclose(Options.pictfile);
  494. }
  495.  
  496. #endif
  497.  
  498. #endif /* URT */
  499.