Back to index

radiance  4R0+20100331
ra_pict.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: ra_pict.c,v 2.10 2004/03/28 20:33:14 schorsch Exp $";
00003 #endif
00004 /*            Convert an Radiance image to APPLE pict format.
00005  *
00006  *                   Orginally Iris to PICT by   Paul Haeberli - 1990
00007  *                   Hacked into Rad to PICT by Russell Street 1990
00008  *
00009  *     History:
00010  *         V 1                     -- Does basic conversion
00011  *         V 1.1 (2/11/91)  -- Added options for Gamma
00012  *                          -- verbose option
00013  *                          -- man page
00014  *                          -- better about allocating buffers
00015  *         V 1.2 (19/11/91) -- Revised to handle opening "The Radiance Way"
00016  *                          -- Added exposure level adjustment
00017  */
00018 
00019 #include <stdio.h>
00020 #include <math.h>
00021 #include  <time.h>
00022 
00023 #include "platform.h"
00024 #include "pict.h"
00025 #include "color.h"
00026 #include "resolu.h"
00027 
00028 int    outbytes;                /* This had better be 32 bits! */
00029 char   *progname;
00030 int    verbose = 0;
00031 float  gamcor = 2.0;
00032 int    bradj = 0;
00033 
00034 static void putrect(int xorg, int yorg, int xsize, int ysize);
00035 static void putfprect(int xorg, int yorg, int xsize, int ysize);
00036 static void putalong(long l);
00037 static void putashort(short s);
00038 static void putbyte(int b);
00039 static void putbytes(unsigned char *buf, int n );
00040 static void putpict(int xsize, int ysize);
00041 static void getrow(FILE *in, char *cbuf, int xsize);
00042 static int packbits(unsigned char *ibits, unsigned char *pbits, int nbits);
00043 static void usage(void);
00044 
00045 
00046        /* First some utility routines */
00047 static void
00048 putrect(
00049        int xorg,
00050        int yorg,
00051        int xsize,
00052        int ysize
00053 )
00054 {
00055     putashort(yorg);
00056     putashort(xorg);
00057     putashort(ysize);
00058     putashort(xsize);
00059 }
00060 
00061 static void
00062 putfprect(
00063        int xorg,
00064        int yorg,
00065        int xsize,
00066        int ysize
00067 )
00068 {
00069     putalong(yorg<<16);
00070     putalong(xorg<<16);
00071     putalong(ysize<<16);
00072     putalong(xsize<<16);
00073 }
00074 
00075 static void
00076 putalong(
00077        long l
00078 )
00079 {
00080     putbyte((l>>24)&0xff);
00081     putbyte((l>>16)&0xff);
00082     putbyte((l>>8)&0xff);
00083     putbyte((l>>0)&0xff);
00084 }
00085 
00086 static void
00087 putashort(
00088        short s
00089 )
00090 {
00091     putbyte((s>>8)&0xff);
00092     putbyte((s>>0)&0xff);
00093 }
00094 
00095 static void
00096 putbyte(
00097        int b
00098 )
00099 {
00100     if (putc(b,stdout) == EOF && ferror(stdout)) {
00101        fprintf(stderr,"%s: error on write\n", progname);
00102        exit(1);
00103     }
00104     outbytes++;
00105 }
00106 
00107 static void
00108 putbytes(
00109        unsigned char *buf,
00110        int n
00111 )
00112 {
00113     if(!fwrite(buf,n,1,stdout)) {
00114        fprintf(stderr,"%s: error on write\n", progname);
00115        exit(1);
00116     }
00117     outbytes+=n;
00118 }
00119 
00120 int
00121 main(
00122        int argc,
00123        char **argv
00124 )
00125 {
00126     int xsize, ysize;
00127     int i, picsize;
00128     int ssizepos, lsizepos;
00129        SET_DEFAULT_BINARY();
00130     SET_FILE_BINARY(stdin);
00131     SET_FILE_BINARY(stdout);
00132     progname = argv[0];
00133 
00134     for (i = 1; i < argc ; i++)
00135        if (argv[i][0] ==  '-')
00136            switch (argv[i][1]) {
00137               case 'g':     gamcor = atof(argv[++i]);
00138                             break;
00139 
00140               case 'e':     if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
00141                                usage();
00142                             else
00143                                 bradj = atoi(argv[++i]);
00144                             break;
00145 
00146               case 'v':     ;
00147                             verbose = 1;
00148                             break;
00149 
00150               case 'r':     fprintf(stderr, "Sorry. Get a Macintosh :-)\n");
00151                             exit(1);
00152 
00153               case '-':     i++;
00154                             goto outofparse;
00155                             break;            /* NOTREACHED */
00156 
00157               default:
00158                             usage();
00159                             break;
00160                }
00161        else
00162            break;
00163 
00164 outofparse:
00165 
00166     if (i < argc - 2)
00167        usage();
00168 
00169     if (i <= argc - 1 && freopen(argv[i], "r", stdin) == NULL) {
00170        fprintf(stderr, "%s: can not open input \"%s\"\n",
00171            progname, argv[i]);
00172        exit(1);
00173     }
00174 
00175     if (i <= argc - 2 && freopen(argv[i+1], "w", stdout) == NULL) {
00176        fprintf(stderr, "%s: can not open input \"%s\"\n",
00177            progname, argv[i+1]);
00178        exit(1);
00179     }
00180        
00181 #ifdef DEBUG
00182        fprintf(stderr, "Input file: %s\n", i <= argc - 1 ? argv[i] : "stdin");
00183        fprintf(stderr, "Outut file: %s\n", i <= argc - 2 ? argv[i+1] : "stdout" );
00184        fprintf(stderr, "Gamma: %f\n", gamcor);
00185        fprintf(stderr, "Brightness adjust: %d\n", bradj);
00186        fprintf(stderr, "Verbose: %s\n", verbose ? "on" : "off");
00187 #endif
00188 
00189 
00190             /* OK. Now we read the size of the Radiance picture */
00191     if (checkheader(stdin, COLRFMT, NULL) < 0 ||
00192            fgetresolu(&xsize, &ysize, stdin) < 0 /* != (YMAJOR|YDECR) */ ) {
00193        fprintf(stderr, "%s: not a radiance picture\n", progname);
00194        exit(1);
00195        }
00196 
00197            /* Set the gamma correction */
00198 
00199     setcolrgam(gamcor);
00200 
00201     for(i=0; i<HEADER_SIZE; i++) 
00202        putbyte(0);
00203 
00204     ssizepos = outbytes;
00205     putashort(0);           /* low 16 bits of file size less HEADER_SIZE */
00206     putrect(0,0,xsize,ysize);      /* bounding box of picture */
00207     putashort(PICT_picVersion);
00208     putashort(0x02ff);             /* version 2 pict */
00209     putashort(PICT_reservedHeader);       /* reserved header opcode */
00210 
00211     lsizepos = outbytes;
00212     putalong(0);            /* full size of the file */
00213     putfprect(0,0,xsize,ysize); /* fixed point bounding box of picture */
00214     putalong(0);            /* reserved */
00215 
00216     putashort(PICT_clipRgn);       /* the clip region */
00217     putashort(10);
00218     putrect(0,0,xsize,ysize);
00219 
00220     if (verbose)
00221        fprintf(stderr, "%s: The picture is %d by %d, with a gamma of %f\n",
00222            progname, xsize, ysize, gamcor);
00223 
00224 
00225     putpict(xsize, ysize);  /* Here is where all the work is done */
00226 
00227     putashort(PICT_EndOfPicture); /* end of pict */
00228 
00229     picsize = outbytes-HEADER_SIZE;
00230     fseek(stdout,ssizepos,0);
00231     putashort(picsize&0xffff);
00232     fseek(stdout,lsizepos,0);
00233     putalong(picsize);
00234 
00235     fclose(stdout);
00236     fclose(stdin);
00237     
00238     exit(0);
00239     return 0;     /* lint fodder */
00240 }
00241 
00242 static void
00243 putpict(
00244        int xsize,
00245        int ysize
00246 )
00247 {
00248     int           y;
00249     int           nbytes, rowbytes;
00250     char    *cbuf, *pbuf;
00251 
00252     cbuf = (char *)malloc(4 * xsize);
00253 
00254     if (cbuf == NULL) {
00255        fprintf(stderr, "%s: not enough memory\n", progname);
00256        exit(1);
00257        }
00258 
00259     pbuf = (char *)malloc(4 * xsize);
00260 
00261     if (pbuf == NULL) {
00262        fprintf(stderr, "%s: not enough memory\n", progname);
00263        exit(1);
00264        }
00265 
00266     putashort(PICT_Pack32BitsRect); /* 32 bit rgb */
00267     rowbytes = 4*xsize;
00268     putalong(0x000000ff);          /* base address */
00269 
00270 
00271     if(rowbytes&1)
00272        rowbytes++;
00273     putashort(rowbytes|0x8000); /* rowbytes */
00274     putrect(0,0,xsize,ysize);      /* bounds */
00275     putashort(0);           /* version */
00276 
00277     putashort(4);    /* packtype */
00278     putalong(0);     /* packsize */
00279     putalong(72<<16);       /* hres */
00280     putalong(72<<16);       /* vres */
00281 
00282     putashort(16);   /* pixeltype */
00283     putashort(32);   /* pixelsize */
00284     putashort(3);    /* cmpcount */
00285 
00286 
00287     putashort(8);    /* cmpsize */
00288     putalong(0);     /* planebytes */
00289     putalong(0);     /* pmtable */
00290     putalong(0);     /* pmreserved */
00291 
00292 
00293     putrect(0,0,xsize,ysize);      /* scr rect */
00294     putrect(0,0,xsize,ysize);      /* dest rect */
00295 
00296 
00297     putashort(0x40); /* transfer mode */
00298 
00299     for(y=0; y<ysize; y++) {
00300        getrow(stdin, cbuf, xsize);
00301 
00302        nbytes = packbits(cbuf,pbuf,24*xsize);
00303        if(rowbytes>250) 
00304            putashort(nbytes);
00305        else
00306            putbyte(nbytes);
00307        putbytes(pbuf,nbytes);
00308        }
00309 
00310     if(outbytes&1) 
00311        putbyte(0);
00312 
00313     free(cbuf);
00314     free(pbuf);
00315 }
00316 
00317 static void
00318 getrow(
00319        FILE *in,
00320        char *cbuf,
00321        int xsize
00322 )
00323 {
00324     extern char *tempbuffer();            /* defined in color.c */
00325     COLR    *scanin = NULL;
00326     int           x;
00327 
00328     if ((scanin = (COLR *)tempbuffer(xsize*sizeof(COLR))) == NULL) {
00329        fprintf(stderr, "%s: not enough memory\n", progname);
00330        exit(1);
00331     }
00332 
00333     if (freadcolrs(scanin, xsize, in) < 0) {
00334        fprintf(stderr, "%s: read error\n", progname);
00335        exit(1);
00336        }
00337 
00338     if (bradj)           /* Adjust exposure level */
00339        shiftcolrs(scanin, xsize, bradj);
00340 
00341 
00342     colrs_gambs(scanin, xsize);        /* Gamma correct it */
00343     
00344     for (x = 0; x < xsize; x++) {
00345        cbuf[x] = scanin[x][RED];
00346        cbuf[xsize + x] = scanin[x][GRN];
00347        cbuf[2*xsize + x] = scanin[x][BLU];
00348        }
00349 
00350 }
00351 
00352 
00353 static int
00354 packbits(
00355        unsigned char *ibits,
00356        unsigned char *pbits,
00357        int nbits
00358 )
00359 {
00360     unsigned char *sptr;
00361     unsigned char *ibitsend;
00362     unsigned char *optr = pbits;
00363     int nbytes, todo, cc, count;
00364 
00365     nbytes = ((nbits-1)/8)+1;
00366     ibitsend = ibits+nbytes;
00367     while(ibits<ibitsend) {
00368        sptr = ibits;
00369        ibits += 2;
00370        while((ibits<ibitsend)&&((ibits[-2]!=ibits[-1])||(ibits[-1]!=ibits[0])))
00371            ibits++;
00372        if(ibits != ibitsend) {
00373            ibits -= 2;
00374        }
00375        count = ibits-sptr;
00376        while(count) {
00377            todo = count>127 ? 127:count;
00378            count -= todo;
00379            *optr++ = todo-1;
00380            while(todo--)
00381               *optr++ = *sptr++;
00382        }
00383        if(ibits == ibitsend)
00384            break;
00385        sptr = ibits;
00386        cc = *ibits++;
00387        while( (ibits<ibitsend) && (*ibits == cc) )
00388            ibits++;
00389        count = ibits-sptr;
00390        while(count) {
00391            todo = count>128 ? 128:count;
00392            count -= todo;
00393            *optr++ = 257-todo;
00394            *optr++ = cc;
00395        }
00396     }
00397     return optr-pbits;
00398 }
00399 
00400 static void
00401 usage(void)
00402 {
00403     fprintf(stderr, "Usage: %s [-v] [-g gamma] [infile [outfile]]\n",
00404        progname);
00405     exit(2);
00406 }