1 /*
2  * xvpcd.c - load routine for 'PhotoCD' format pictures
3  *
4  * LoadPCD(fname, pinfo, size)  -  loads a PhotoCD file
5  *
6  * This routine will popup a choice of which of the 5 available resolutions
7  * the user wants to choose, then load it as a 24 bit image.
8  *
9  * Copyright 1993 David Clunie, Melbourne, Australia.
10  *
11  * The outline of this is shamelessly derived from xvpbm.c to read the
12  * file, and xvtiffwr.c to handle the popup window and X stuff (X never
13  * has been my forte !), and the PhotoCD format information (though not
14  * the code) was found in Hadmut Danisch's (danisch@ira.uka.de) hpcdtoppm
15  * program in which he has reverse engineered the format by studying
16  * hex dumps of PhotoCDs ! After all who can afford the Kodak developer's
17  * kit, which none of us have seen yet ? Am I even allowed to mention these
18  * words (Kodak, PhotoCD) ? I presume they are registered trade marks.
19  *
20  * PS. I have no idea how Halmut worked out the YCC <-> RGB conversion
21  * factors, but I have calculated them from his tables and the results
22  * look good enough to me.
23  *
24  * Added size parameter to allow the schnautzer to create thumnails
25  * without requesting the size every time.
26  */
27 
28 #include "xv.h"
29 
30 #ifdef HAVE_PCD
31 
32 #include <memory.h>
33 #ifndef alloca
34 #  include <alloca.h> /* "not in POSIX or SUSv3" according to Linux man page */
35 #endif                /* ...but required for Sun C compiler (alloca = macro) */
36 
37 #define  TRACE  0
38 #if TRACE
39 #  define trace(x) fprintf x
40 #else
41 #  define trace(x)
42 #endif
43 
44 /* Comments on error-handling:
45    A truncated file is not considered a Major Error.  The file is loaded,
46    and the rest of the pic is filled with 0's.
47 
48    Not being able to malloc is a Fatal Error.  The program is aborted. */
49 
50 
51 #ifdef __STDC__
52 static void magnify(int, int, int, int, int, byte *);
53 static int pcdError(const char *, const char *);
54 static int gethuffdata(byte *, byte *, byte *, int, int);
55 #else
56 static void magnify();
57 static int pcdError();
58 static int gethuffdata();
59 #endif
60 
61 #define wcurfactor 16  /* Call WaitCursor() every n rows */
62 
63 static int  size;    /* Set by window routines */
64 static int  leaveitup;/* Cleared by docmd() when OK or CANCEL pressed */
65 static int  goforit;  /* Set to 1 if OK or 0 if CANCEL */
66 static FILE  *fp;
67 static CBUTT  lutCB;
68 
69 /*
70  * This "beyond 100%" table is taken from ImageMagick (gamma 2.2).
71  * Why there are 351 entries and not 346 as per Kodak documentation
72  * is a mystery.
73  */
74 static  double  rscale = 1.00,
75     gscale = 1.00,
76     bscale = 1.00;
77 
78 static  byte  Y[351] = {
79     0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
80    10,  11,  12,  13,  14,  15,  16,  17,  18,  19,
81    20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
82    30,  32,  33,  34,  35,  36,  37,  38,  39,  40,
83    41,  42,  43,  45,  46,  47,  48,  49,  50,  51,
84    52,  53,  54,  56,  57,  58,  59,  60,  61,  62,
85    63,  64,  66,  67,  68,  69,  70,  71,  72,  73,
86    74,  76,  77,  78,  79,  80,  81,  82,  83,  84,
87    86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
88    97,  98,  99, 100, 101, 102, 103, 104, 105, 106,
89   107, 108, 110, 111, 112, 113, 114, 115, 116, 117,
90   118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
91   129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
92   139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
93   149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
94   159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
95   169, 170, 171, 172, 173, 174, 175, 176, 176, 177,
96   178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
97   188, 189, 190, 191, 192, 193, 193, 194, 195, 196,
98   197, 198, 199, 200, 201, 201, 202, 203, 204, 205,
99   206, 207, 207, 208, 209, 210, 211, 211, 212, 213,
100   214, 215, 215, 216, 217, 218, 218, 219, 220, 221,
101   221, 222, 223, 224, 224, 225, 226, 226, 227, 228,
102   228, 229, 230, 230, 231, 232, 232, 233, 234, 234,
103   235, 236, 236, 237, 237, 238, 238, 239, 240, 240,
104   241, 241, 242, 242, 243, 243, 244, 244, 245, 245,
105   245, 246, 246, 247, 247, 247, 248, 248, 248, 249,
106   249, 249, 249, 250, 250, 250, 250, 251, 251, 251,
107   251, 251, 252, 252, 252, 252, 252, 253, 253, 253,
108   253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
109   254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
110   254, 254, 254, 254, 254, 254, 254, 254, 254, 255,
111   255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
112   255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
113   255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
114   255
115 };
116 
117 /*******************************************/
118 /* The size should be -1 for the popup to ask otherwise fast is assumed */
119 /* returns '1' on success */
120 /*******************************************/
121 int
LoadPCD(char * fname,PICINFO * pinfo,int theSize)122 LoadPCD(char *fname, PICINFO *pinfo, int theSize)
123 {
124   long   offset;
125   int    mag;
126   int   rotate;
127   byte   header[3*0x800];
128   byte  *pic24, *luma, *chroma1, *chroma2, *ptr, *lptr, *c1ptr, *c2ptr;
129   int   w, h, npixels, bufsize;
130   int   row, col;
131   int  huffplanes;
132   const char  *bname;
133 
134   bname    = BaseName(fname);
135   pinfo->pic  = NULL;
136   pinfo->comment  = NULL;
137 
138 
139   /*
140    *  open the file
141    */
142   if((fp=fopen(fname,"r")) == NULL)
143     return pcdError(bname, "can't open file");
144 
145   /*
146    * inspect the header
147    */
148   if(fread(&header[0], 1, sizeof(header), fp) != sizeof(header))
149     return pcdError(bname, "could not load PCD header");
150   if(strncmp((char *)&header[0x800], "PCD_", 4) != 0)
151     return pcdError(bname, "not a PCD file");
152   rotate = header[0x0E02] & 0x03;
153 
154 /* base/16
155   - plain data starts at sector 1+2+1=4
156     (numbered from 0, ie. the 5th sector)
157   - luma 192*128 = 24576 bytes (12 sectors)
158     + chroma1 96*64 = 6144 bytes (3 sectors)
159     + chroma2 96*64 = 6144 bytes (3 sectors)
160     = total 18 sectors
161 
162   - NB. "Plain" data is interleaved - 2 luma rows 192 wide,
163     then 1 of each of the chroma rows 96 wide !
164 
165    base/4
166   - plain data starts at sector 1+2+1+18+1=23
167   - luma 384*256 = 98304 bytes (48 sectors)
168     + chroma1 192*128 = 24576 bytes (12 sectors)
169     + chroma2 192*128 = 24576 bytes (12 sectors)
170     = total 72 sectors
171 
172   - NB. "Plain" data is interleaved - 2 luma rows 384 wide,
173     then 1 of each of the chroma rows 192 wide !
174 
175    base
176   - plain data starts at sector 1+2+1+18+1+72+1=96
177 
178   - luma 768*512 = 393216 bytes (192 sectors)
179     + chroma1 384*256 = 98304 bytes (48 sectors)
180     + chroma2 384*256 = 98304 bytes (48 sectors)
181     = total 288 sectors
182 
183   - NB. "Plain" data is interleaved - 2 luma rows 768 wide,
184     then 1 of each of the chroma rows 384 wide !
185 
186    4base
187   - plain data for base is read
188   - luma data interpolated *2
189   - chroma data interpolated *4
190 
191   - cd_offset is 1+2+1+18+1+72+1+288=384
192   - at cd_offset+4 (388) is huffman table
193   - at cd_offset+5 (389) is 4base luma plane
194 
195   (the sector at cd_offset+3 seems to contain 256 words each of
196   which is an offset presumably to the sector containing certain
197   rows ? rows/4 given 1024 possible rows. The rest of this sector
198   is filled with zeroes)
199 
200 
201    16base
202   - plain data for base is read
203   - luma data interpolated *2
204   - chroma data interpolated *4
205 
206   - cd_offset is 1+2+1+18+1+72+1+288=384
207   - at cd_offset+4 (388) is huffman table for 4 base
208   - at cd_offset+5 (389) is 4base luma plane
209   - luma plane interpolated *2
210 
211   - cd_offset is set to current position (should be start of sector)
212   - at cd_offset+12 is huffman table for 16 base
213   - at cd_offset+14 is 16 base luma & 2 chroma planes which are read
214           (note that the luma plane comes first, with a sync pattern
215            announcing each row from 0 to 2047, then the two chroma planes
216            are interleaved by row, the row # being even from 0 to 2046, with
217            each row containing 1536 values, the chroma1 row coming first,
218            finally followed by a sync pattern with a row of 2048 announcing
219            the end (its plane seems to be set to 3, ie. chroma2)
220   - chroma planes interpolated *2
221 
222   (the sector at cd_offset+10 & 11 seem to contain 1024 pairs of words
223         the first for luma and the second for chroma, each of
224   which is an offset presumably to the sector containing certain
225   rows ? rows/2 given 2048 possible rows)
226 
227 Not yet implemented:
228 
229 In order to do overskip for base and 4base, one has to reach the chroma
230 data for 16 base:
231 
232   - for 4base, after reading the 4base luma plane (and presumably
233     skipping the chroma planes) one sets cd_offset to the start of
234     the "current" sector
235 
236   - for base, one has to skip the 4base data first:
237   - cd_offset is set to 384
238   - at (cd_offset+3 sectors)[510] is a 16 bit word high byte 1st
239     containing an offset to the beginning of the 16base stuff
240     though there is then a loop until >30 0xff's start a sector !
241 
242   - being now positioned after the end of the 4base stuff,
243   - at (cd_offset+10 sectors)[2] is a 16 bit word high byte 1st
244     containing an offset to the chroma planes.
245   - at cd_offset+12 is the set of huffman tables
246 
247   - for base, the 16base chroma planes are then halved
248 */
249 
250   PCDSetParamOptions(bname);
251   if (theSize == -1)
252   {
253     PCDDialog(1);                   /* Open PCD Dialog box */
254     SetCursors(-1);                 /* Somebody has already set it to wait :( */
255     leaveitup=1;
256     goforit=0;
257   size = 1;
258     /* block until the popup window gets closed */
259     while (leaveitup) {
260       int i;
261       XEvent event;
262       XNextEvent(theDisp, &event);
263       HandleEvent(&event, &i);
264     }
265     /* At this point goforit and size will have been set */
266     if (!goforit) {
267       /* nothing allocated so nothing needs freeing */
268       return 0;
269     }
270     WaitCursor();
271   }
272   else
273   {
274     size = theSize;
275     goforit = 1;
276   }
277 
278   if(lutCB.val)
279     rscale = gscale = bscale = 255.0/346.0;
280   else
281     rscale = gscale = bscale = 1.0;
282 
283   switch (size) {
284   case 0:
285     pinfo->w = 192;
286     pinfo->h = 128;
287     offset=4*0x800;
288     mag=1;
289     huffplanes=0;
290     sprintf(pinfo->fullInfo, "PhotoCD, base/16 resolution");
291     break;
292 
293   case 1:
294     pinfo->w = 384;
295     pinfo->h = 256;
296     offset=23*0x800;
297     mag=1;
298     huffplanes=0;
299     sprintf(pinfo->fullInfo, "PhotoCD, base/4 resolution");
300     break;
301 
302   case 2:
303   default:
304     pinfo->w = 768;
305     pinfo->h = 512;
306     offset=96*0x800;
307     mag=1;
308     huffplanes=0;
309     sprintf(pinfo->fullInfo, "PhotoCD, base resolution");
310     break;
311 
312   case 3:
313     pinfo->w = 1536;
314     pinfo->h = 1024;
315     offset=96*0x800;
316     mag=2;
317     huffplanes=1;
318     sprintf(pinfo->fullInfo, "PhotoCD, 4base resolution");
319     break;
320 
321   case 4:
322     pinfo->w=3072;
323     pinfo->h=2048;
324     offset=96*0x800;
325     mag=4;
326     huffplanes=2;
327     sprintf(pinfo->fullInfo, "PhotoCD, 16base resolution");
328     break;
329   }
330 
331   /*
332    * rotate?
333    */
334   w = pinfo->w;
335   h = pinfo->h;
336   switch(rotate) {
337   case  0:
338     break;
339 
340   case  1:
341   case  3:
342     pinfo->w = h;
343     pinfo->h = w;
344     break;
345 
346   default:
347     fprintf(stderr, "unknown image rotate %d; assuming none\n",
348       rotate);
349     rotate = 0;
350   }
351 
352   /*
353    * allocate 24-bit image
354    */
355   npixels = pinfo->w * pinfo->h;
356   bufsize = 3 * npixels;
357   if (pinfo->w <= 0 || pinfo->h <= 0 || npixels/pinfo->w != pinfo->h ||
358       bufsize/3 != npixels)
359     FatalError("image dimensions out of range");
360 
361   pinfo->pic = (byte *)malloc((size_t) bufsize);
362   if(!pinfo->pic)
363     FatalError("couldn't malloc '24-bit RGB plane'");
364 
365   pinfo->type = PIC24;
366   sprintf(pinfo->shrtInfo, "%dx%d PhotoCD.", pinfo->w, pinfo->h);
367   pinfo->colType = F_FULLCOLOR;
368   pinfo->frmType = -1;
369 
370   if(fseek(fp, offset, SEEK_SET) == -1) {
371     free(pinfo->pic);
372     return pcdError(bname,"Can't find start of data.");
373   }
374 
375   pic24 = pinfo->pic;
376 
377   luma=(byte *)calloc(npixels,1);
378   if(!luma) {
379     free(pinfo->pic);
380     FatalError("couldn't malloc 'luma plane'");
381   }
382 
383   chroma1=(byte *)calloc(npixels/4,1);
384   if(!chroma1) {
385     free(pinfo->pic);
386     free(luma);
387     FatalError("couldn't malloc 'chroma1 plane'");
388   }
389 
390   chroma2=(byte *)calloc(npixels/4,1);
391   if(!chroma2) {
392     free(pinfo->pic);
393     free(luma);
394     free(chroma1);
395     FatalError("couldn't malloc 'chroma2 plane'");
396   }
397 
398   /* Read 2 luma rows length w, then one of each chroma rows w/2 */
399   /* If a mag factor is active, the small image is read into the */
400   /* top right hand corner of the larger allocated image */
401 
402   trace((stderr, "base image: start @ 0x%08lx (sector %ld.%ld)\n",
403         ftell(fp), ftell(fp)/0x800, ftell(fp) % 0x800));
404   for(row=0,lptr=luma,c1ptr=chroma1,c2ptr=chroma2; row <h/mag;
405         row+=2,lptr+=w*2,c1ptr+=w/2,c2ptr+=w/2) {
406     if(fread(lptr, 1, w/mag, fp) != w/mag) {
407       pcdError(bname, "Luma plane too short.");
408       break;
409     }
410     if(fread(lptr+w, 1, w/mag, fp) != w/mag) {
411       pcdError(bname, "Luma plane too short.");
412       break;
413     }
414     if(fread(c1ptr, 1, w/2/mag, fp) != w/2/mag) {
415       pcdError(bname, "Chroma1 plane too short.");
416       break;
417     }
418     if(fread(c2ptr, 1, w/2/mag, fp) != w/2/mag) {
419       pcdError(bname, "Chroma2 plane too short.");
420       break;
421     }
422     if(row%wcurfactor == 0)
423       WaitCursor();
424   }
425   trace((stderr, "base image: done @ 0x%08lx (sector %ld.%ld)\n",
426         ftell(fp), ftell(fp)/0x800, ftell(fp) % 0x800));
427 
428   if(huffplanes) {
429     if(fseek(fp, 388*0x800, SEEK_SET) == -1)
430       return pcdError(bname,
431           "Can't find start of huffman tables.");
432 
433     magnify(2, h/mag, w/mag, h, w, luma);
434     magnify(2, h/2/mag, w/2/mag, h/2, w/2, chroma1);
435     magnify(2, h/2/mag, w/2/mag, h/2, w/2, chroma2);
436 
437     /*
438      * doesn't really touch the chroma planes which aren't
439      * present in 4base
440      */
441     gethuffdata(luma, chroma1, chroma2, w, h/mag*2);
442 
443     /*
444      * if only doing 4base should probably fetch 16bases
445      * chroma planes here
446      */
447     if(huffplanes == 2) {
448       /*
449        * This depends on gethuffdata() having grabbed
450        * things in 0x800 sectors AND still being
451        * positioned in the "last" sector of the data
452        * (cf. Hadmut's code which is positioned at start
453        * of the next sector)
454        */
455       long  offset = ftell(fp)/0x800+12;
456 
457       if(fseek(fp, offset*0x800, SEEK_SET) == 0) {
458         magnify(2,h/2,w/2,h,w,luma);
459         magnify(2,h/4,w/4,h/2,w/2,chroma1);
460         magnify(2,h/4,w/4,h/2,w/2,chroma2);
461         gethuffdata(luma,chroma1,chroma2,w,h);
462       } else
463         fprintf(stderr, "can't seek to 2nd huffman tables\n");
464     }
465   }
466   fclose(fp);
467 
468   /*
469    * YCC -> R'G'B' and image rotate
470    */
471   ptr=pic24;
472   lptr=luma; c1ptr=chroma1; c2ptr=chroma2;
473   for(row = 0; row < h; ++row) {
474     byte  *rowc1ptr = c1ptr,
475       *rowc2ptr = c2ptr;
476     int  k = 0;
477 
478     switch(rotate) {
479     case  1:
480       ptr = &pic24[row*3 + (w - 1)*h*3];
481         k = -3*(h + 1);
482       break;
483 
484     case  3:
485       ptr = &pic24[(h - 1 - row)*3];
486         k =  3*(h - 1);
487       break;
488 
489     default:
490       ptr = &pic24[row*w*3];
491         k = 0;
492       break;
493     }
494     for(col = 0; col < w; ++col) {
495       double  L  = 1.3584*(double) *lptr++,
496         C1  = 2.2179*(double) (*c1ptr - 156),
497         C2  = 1.8215*(double) (*c2ptr - 137);
498       int  r  = rscale*(L + C2),
499         g  = gscale*(L - 0.194*C1 - 0.509*C2),
500         b  = bscale*(L + C1);
501 
502       if(lutCB.val) {
503         if(r < 0) r = 0; else if(r >= 255) r = 255;
504         if(g < 0) g = 0; else if(g >= 255) g = 255;
505         if(b < 0) b = 0; else if(b >= 255) b = 255;
506       } else {
507         if(r < 0) r = 0; else if(r >= 351) r = 350;
508         if(g < 0) g = 0; else if(g >= 351) g = 350;
509         if(b < 0) b = 0; else if(b >= 351) b = 350;
510         r = Y[r]; g = Y[g]; b = Y[b];
511       }
512       *ptr++ = r;
513       *ptr++ = g;
514       *ptr++ = b;
515       ptr   += k;
516       if(col & 1) {
517         ++c1ptr;
518         ++c2ptr;
519       }
520     }
521     if((row & 1) == 0) {
522       c1ptr = rowc1ptr;
523       c2ptr = rowc2ptr;
524     }
525     if(row%wcurfactor == 0)
526       WaitCursor();
527   }
528   free(luma); free(chroma1); free(chroma2);
529   return 1;
530 }
531 
532 /*
533  * derived from Hadmut Danisch's interpolate()
534  */
535 static void
magnify(int mag,int h,int w,int mh,int mw,byte * p)536 magnify(int mag,  /* power of 2 by which to magnify in place */
537   int h, int w,  /* the "start" unmag'd dimensions of the array */
538   int mh, int mw,  /* the real (maximum) dimensions of the array */
539   byte *p)  /* pointer to the data */
540 {
541   int x,y,yi;
542   byte *optr,*nptr,*uptr;  /* MUST be unsigned, else averaging fails */
543 
544   while (mag > 1) {
545 
546     /* create every 2nd new row from 0 */
547     /*  even pixels being equal to the old, odd ones averaged with successor */
548     /*  special case being the last column which is just set equal to the */
549     /*  second last) ... */
550 
551     for(y=0;y<h;y++) {
552       yi=h-1-y;
553       optr=p+  yi*mw + (w-1);            /* last pixel of an old row */
554       nptr=p+2*yi*mw + (2*w - 2);         /* last pixel of a new row */
555 
556       nptr[0]=nptr[1]=optr[0];            /* special cases */
557 
558       for(x=1;x<w;x++) {
559         optr--; nptr-=2;                  /* next lower pixel(s) */
560         nptr[0]=optr[0];                  /* even pixels duped */
561         nptr[1]=(((int)optr[0])+
562                  ((int)optr[1])+1)>>1;    /* odd averaged */
563       }
564     }
565 
566     /* Fill in odd rows, as average of prior & succeeding rows, with */
567     /* even pixels average of one column, odd pixels average of two */
568 
569     for(y=0;y<h-1;y++) {                  /* all but the last old row */
570       optr=p + 2*y*mw;                    /* start of the new "even" rows */
571       nptr=optr+mw;                       /* start of the next empty row */
572       uptr=nptr+mw;                       /* start of the next again (even) */
573 
574       for(x=0;x<w-1;x++) {                /* for all cols except the last */
575         nptr[0]=(((int)optr[0])+
576                  ((int)uptr[0])+1)>>1;    /* even pixels */
577         nptr[1]=(((int)optr[0])+
578                  ((int)optr[2])+
579                  ((int)uptr[0])+
580                  ((int)uptr[2])+2)>>2;    /* odd pixels */
581         nptr+=2; optr+=2; uptr+=2;
582       }
583       *(nptr++)=(((int)*(optr++))+
584                  ((int)*(uptr++))+1)>>1;  /* 2nd last pixel */
585       *(nptr++)=(((int)*(optr++))+
586                  ((int)*(uptr++))+1)>>1;  /* last pixel */
587     }
588 
589     xvbcopy((char *)(p + (2*h-2)*mw),     /* 2nd last row */
590             (char *)(p + (2*h-1)*mw),     /* the last row */
591             2*w);                         /* length of a new row */
592 
593     h*=2; w*=2;
594     mag>>=1;  /* Obviously mag must be a power of 2 ! */
595   }
596 }
597 
598 /*******************************************/
599 static int
pcdError(const char * fname,const char * st)600 pcdError(const char *fname, const char *st)
601 {
602   SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
603   return 0;
604 }
605 
606 
607 /**** Stuff for PCDDialog box ****/
608 
609 #define TWIDE 380
610 #define THIGH 160
611 #define T_NBUTTS 2
612 #define T_BOK    0
613 #define T_BCANC  1
614 #define BUTTH    24
615 
616 static void drawTD    PARM((int, int, int, int));
617 static void clickTD   PARM((int, int));
618 static void doCmd     PARM((int));
619 static void PCDSetParams PARM((void));
620 
621 /* local variables */
622 static BUTT  tbut[T_NBUTTS];
623 static RBUTT *resnRB;
624 
625 
626 
627 /***************************************************/
CreatePCDW()628 void CreatePCDW()
629 {
630   int       y;
631 
632   pcdW = CreateWindow("xv pcd", "XVpcd", NULL,
633            TWIDE, THIGH, infofg, infobg, 0);
634   if (!pcdW) FatalError("can't create pcd window!");
635 
636   XSelectInput(theDisp, pcdW, ExposureMask | ButtonPressMask | KeyPressMask);
637 
638   BTCreate(&tbut[T_BOK], pcdW, TWIDE-140-1, THIGH-10-BUTTH-1, 60, BUTTH,
639      "Ok", infofg, infobg, hicol, locol);
640 
641   BTCreate(&tbut[T_BCANC], pcdW, TWIDE-70-1, THIGH-10-BUTTH-1, 60, BUTTH,
642      "Cancel", infofg, infobg, hicol, locol);
643 
644   y = 55;
645   resnRB = RBCreate(NULL, pcdW, 36, y,   "192*128   Base/16",
646            infofg, infobg,hicol,locol);
647   RBCreate(resnRB, pcdW, 36, y+18,       "384*256   Base/4",
648            infofg, infobg,hicol,locol);
649   RBCreate(resnRB, pcdW, 36, y+36,       "768*512   Base",
650            infofg, infobg, hicol, locol);
651   RBCreate(resnRB, pcdW, TWIDE/2, y,     "1536*1024 4Base",
652            infofg, infobg, hicol, locol);
653   RBCreate(resnRB, pcdW, TWIDE/2, y+18,  "3072*2048 16Base",
654            infofg, infobg, hicol, locol);
655 
656   CBCreate(&lutCB, pcdW, TWIDE/2, y+36,  "Linear LUT",
657            infofg, infobg, hicol, locol);
658 
659   RBSelect(resnRB, 2);
660 
661   XMapSubwindows(theDisp, pcdW);
662 }
663 
664 
665 /***************************************************/
PCDDialog(vis)666 void PCDDialog(vis)
667 int vis;
668 {
669   if (vis) {
670     CenterMapWindow(pcdW, tbut[T_BOK].x + tbut[T_BOK].w/2,
671         tbut[T_BOK].y + tbut[T_BOK].h/2, TWIDE, THIGH);
672   }
673   else     XUnmapWindow(theDisp, pcdW);
674   pcdUp = vis;
675 }
676 
677 
678 /***************************************************/
PCDCheckEvent(xev)679 int PCDCheckEvent(xev)
680 XEvent *xev;
681 {
682   /* check event to see if it's for one of our subwindows.  If it is,
683      deal accordingly, and return '1'.  Otherwise, return '0' */
684 
685   int rv;
686   rv = 1;
687 
688   if (!pcdUp) return 0;
689 
690   if (xev->type == Expose) {
691     int x,y,w,h;
692     XExposeEvent *e = (XExposeEvent *) xev;
693     x = e->x;  y = e->y;  w = e->width;  h = e->height;
694 
695     if (e->window == pcdW)       drawTD(x, y, w, h);
696     else rv = 0;
697   }
698 
699   else if (xev->type == ButtonPress) {
700     XButtonEvent *e = (XButtonEvent *) xev;
701     int x,y;
702     x = e->x;  y = e->y;
703 
704     if (e->button == Button1) {
705       if      (e->window == pcdW)     clickTD(x,y);
706       else rv = 0;
707     }  /* button1 */
708     else rv = 0;
709   }  /* button press */
710 
711 
712   else if (xev->type == KeyPress) {
713     XKeyEvent *e = (XKeyEvent *) xev;
714     char buf[128];  KeySym ks;  XComposeStatus status;
715     int stlen;
716 
717     stlen = XLookupString(e,buf,128,&ks,&status);
718     buf[stlen] = '\0';
719 
720     RemapKeyCheck(ks, buf, &stlen);
721 
722     if (e->window == pcdW) {
723       if (stlen) {
724   if (buf[0] == '\r' || buf[0] == '\n') { /* enter */
725     FakeButtonPress(&tbut[T_BOK]);
726   }
727   else if (buf[0] == '\033') {            /* ESC */
728     FakeButtonPress(&tbut[T_BCANC]);
729   }
730       }
731     }
732     else rv = 0;
733   }
734   else rv = 0;
735 
736   if (rv==0 && (xev->type == ButtonPress || xev->type == KeyPress)) {
737     XBell(theDisp, 50);
738     rv = 1;   /* eat it */
739   }
740 
741   return rv;
742 }
743 
744 
745 /***************************************************/
746 void
PCDSetParamOptions(const char * fname)747 PCDSetParamOptions(const char *fname)
748 {
749   int cur;
750   cur = RBWhich(resnRB);
751 
752   RBSetActive(resnRB,0,1);
753   RBSetActive(resnRB,1,1);
754   RBSetActive(resnRB,2,1);
755   RBSetActive(resnRB,3,1);
756   RBSetActive(resnRB,4,1);
757   CBSetActive(&lutCB,1);
758 }
759 
760 
761 /***************************************************/
762 static void
drawTD(int x,int y,int w,int h)763 drawTD(int x, int y, int w, int h)
764 {
765   const char *title = "Load PhotoCD file...";
766   int         i;
767   XRectangle  xr;
768 
769   xr.x = x;  xr.y = y;  xr.width = w;  xr.height = h;
770   XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
771 
772   XSetForeground(theDisp, theGC, infofg);
773   XSetBackground(theDisp, theGC, infobg);
774 
775   for (i=0; i<T_NBUTTS; i++) BTRedraw(&tbut[i]);
776 
777   ULineString(pcdW, resnRB->x-16, resnRB->y-10-DESCENT, "Resolution");
778   RBRedraw(resnRB, -1);
779   CBRedraw(&lutCB);
780 
781   XDrawString(theDisp, pcdW, theGC, 20, 19, title, strlen(title));
782 
783   XSetClipMask(theDisp, theGC, None);
784 }
785 
786 
787 /***************************************************/
clickTD(x,y)788 static void clickTD(x,y)
789 int x,y;
790 {
791   int i;
792   BUTT *bp;
793 
794   /* check BUTTs */
795 
796   /* check the RBUTTS first, since they don't DO anything */
797   if ( (i=RBClick(resnRB, x,y)) >= 0) {
798     (void) RBTrack(resnRB, i);
799     return;
800   }
801 
802   if(CBClick(&lutCB, x, y)) {
803     (void) CBTrack(&lutCB);
804     return;
805   }
806 
807   for (i=0; i<T_NBUTTS; i++) {
808     bp = &tbut[i];
809     if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break;
810   }
811 
812   if (i<T_NBUTTS) {  /* found one */
813     if (BTTrack(bp)) doCmd(i);
814   }
815 }
816 
817 
818 
819 /***************************************************/
doCmd(cmd)820 static void doCmd(cmd)
821 int cmd;
822 {
823   leaveitup=0;
824   goforit=0;
825   switch (cmd) {
826   case T_BOK:    PCDSetParams();
827                 goforit=1;
828   case T_BCANC:  PCDDialog(0);
829                 break;
830 
831   default:  break;
832   }
833 }
834 
835 
836 /*******************************************/
PCDSetParams()837 static void PCDSetParams()
838 {
839   switch (RBWhich(resnRB)) {
840   case 0: size = 0;      break;
841   case 1: size = 1;      break;
842   case 2: size = 2;      break;
843   case 3: size = 3;      break;
844   case 4: size = 4;      break;
845   case 5: size = 0;      break;
846   default: size = 0;     break;
847   }
848 }
849 
850 /*
851  * Read the Huffman tables which consist of an unsigned byte # of entries
852  * (less 1) followed by up to 256 entries, each of which is a series of 4
853  * unsigned bytes - length, highseq, lowseq, and key.
854  *
855  * Store the huffman table into tree type structure:
856  *
857  *   int int[n of entries*2]
858  *
859  * Each entry consists of two words (the 1st for zero and the 2nd for one).
860  *
861  * If the word is negative, then subtract it from the current pointer to
862  * get the next entry (ie. it is the negative offset from the current
863  * position*2 in order to skip entries not words) with which to
864  * make a decision.
865  *
866  * If the word is not negative, then the low 8 bits contain the value (which
867  * is supposed to be a signed char) and the rest of the word is zero.
868  */
869 static void
dumphufftab(int n,const byte * h,int m,const int * t)870 dumphufftab(int n, const byte *h, int m, const int *t)
871 {
872   int  j;
873 
874   for(j = 0; j < n || j < m; ++j) {
875     if(j < m)
876       fprintf(stderr, "%04x %04x ::", 0xffff & t[2*j + 0],
877                0xffff & t[2*j + 1]);
878     else
879       fprintf(stderr, "%s %s ::", "    ", "    ");
880     if(j < n) {
881       int   k;
882       unsigned l = (h[4*j + 1] << 8) | h[4*j + 2];
883 
884       fprintf(stderr, " %02x %2d ", h[4*j + 3], h[4*j + 0]);
885       for(k = 0; k <= h[4*j + 0]; ++k, l *= 2)
886         fprintf(stderr, "%c", '0'+((l & 0x8000) != 0));
887     }
888     fprintf(stderr, "\n");
889   }
890 }
891 
892 static int *
gethufftable(void)893 gethufftable(void)
894 {
895   int  *hufftab, *h, i, j, N, num, bufsize, huffptr, hufftop;
896   byte  *huf;
897 
898   /*
899    * absorb the entirety of the table in one chunk (for better
900    * dumps in case of error)
901    */
902   trace((stderr, "hufftab 0x%08lx ", ftell(fp)));
903   num = 1 + fgetc(fp);   /* 256 max */
904   huf = (byte *)alloca(4*num*sizeof(byte));
905   if((i = fread(huf, 1, 4*num, fp)) != 4*num) {
906     fprintf(stderr, "unexpected EOF: got %d bytes, wanted %d\n",
907                 i, 4*num);
908     return NULL;
909   }
910 
911   /*
912    * guess an initial size and prepare the initial entry
913    */
914   trace((stderr, "length %u\n", num));
915   N = 2*num;   /* 512 max */
916   bufsize = N * sizeof(int);
917 /*  this case can't happen, but added for symmetry with loop below
918   if (N/2 != num || bufsize/N != sizeof(int)) {
919     SetISTR(ISTR_WARNING, "Huffman table size out of range");
920     return NULL;
921   }
922  */
923   if((hufftab = (int *)malloc(bufsize)) == NULL)
924     FatalError("couldn't malloc initial Huffman table");
925   hufftab[0] = hufftab[1] = 0;
926 
927   /*
928    * we check the table for reasonableness;  there is a lack of detailed
929    * documentation on this format.  in particular, for the base16,
930    * the position of the huffman tables is uncertain to within one
931    * "sector", and we have to detect his before trying to read
932    * bogusness.
933    */
934   hufftop = 0;
935   for(i = 0; i < num; ++i) {
936     unsigned length   =  huf[4*i + 0],
937        codeword = (huf[4*i + 1] << 8) | huf[4*i + 2];
938 
939     /*
940      * some sanity checks
941      */
942     if(length >= 16) {
943       fprintf(stderr,
944         "gethufftable: improbable length @ %d/%d\n",
945           i, num);
946       dumphufftab(num, huf, hufftop/2, hufftab);
947       free(hufftab);
948       return NULL;
949     }
950 
951     /*
952      * walk the whole set of codes
953      */
954     huffptr = 0;
955     for(j = 0; j < 16; ++j, codeword *= 2) {
956       /*
957        * choose the child node
958        */
959       if(codeword & 0x8000)
960         ++huffptr;
961 
962       /*
963        * store value at end-of-code
964        */
965       if(j == length) {
966         /*
967          * more sanity
968          */
969         if((codeword *= 2) & 0xffff) {
970           fprintf(stderr,
971             "gethufftable: "
972             ":probable invalid code @ %d\n",
973               i);
974           dumphufftab(num, huf,
975               hufftop/2, hufftab);
976           free(hufftab);
977           return NULL;
978         }
979         hufftab[huffptr] = 1 + (int) huf[4*i + 3];
980         break;
981       }
982 
983       /*
984        * otherwise, follow the tree to date
985        */
986       if(hufftab[huffptr] < 0) {
987         huffptr -= hufftab[huffptr];
988         continue;
989       } else if(hufftab[huffptr] > 0) {
990         fprintf(stderr, "duplicate code %d %d/%d\n",
991           huffptr, i, num);
992         dumphufftab(num, huf, hufftop/2, hufftab);
993         free(hufftab);
994         return NULL;
995       }
996 
997       /*
998        * and if necessary, make the tree bigger
999        */
1000       if((hufftop += 2) >= N) {
1001         int oldN = N;
1002 #if TRACE
1003         dumphufftab(num, huf, hufftop/2, hufftab);
1004 #endif
1005         N *= 2;
1006         bufsize = N*sizeof(int);
1007         if (N/2 != oldN || bufsize/N != sizeof(int)) {
1008           SetISTR(ISTR_WARNING,
1009             "new Huffman table is too large");
1010           free(hufftab);
1011           return NULL;
1012         }
1013         h = (int *)realloc(hufftab, bufsize);
1014         if(h == NULL) {
1015           fprintf(stderr,
1016             "Table overflow %d/%d\n",
1017                  i, num);
1018           dumphufftab(num, huf,
1019               hufftop/2, hufftab);
1020           free(hufftab);
1021           FatalError(
1022             "couldn't realloc Huffman table");
1023         }
1024         hufftab = h;
1025       }
1026 
1027       /*
1028        * then add new ptr
1029        */
1030       hufftab[huffptr] = huffptr - hufftop;
1031       huffptr = hufftop;
1032       hufftab[huffptr + 0] =
1033       hufftab[huffptr + 1] = 0;
1034     }
1035   }
1036   return hufftab;
1037 }
1038 
1039 /* WORDTYPE & char buffer must be unsigned else */
1040 /* fills with sign bit not 0 on right shifts */
1041 typedef unsigned int WORDTYPE;
1042 typedef int SWORDTYPE;
1043 #define WORDSIZE sizeof(WORDTYPE)
1044 #define NBYTESINBUF 0x800
1045 
1046 static byte buffer[NBYTESINBUF];
1047 static int bitsleft=0;
1048 static int bytesleft=0;
1049 static byte *bufptr;
1050 static WORDTYPE word;
1051 
1052 #if 0
1053 static void
1054 dumpbuffer(void)
1055 {
1056   int i,left;
1057   byte *ptr=buffer;
1058 
1059   fprintf(stderr,"dumpbuffer: bytesleft=%d bitsleft= %d word=0x%08lx\n",
1060     bytesleft,bitsleft,(unsigned long)word);
1061   for (left=NBYTESINBUF; left>0; left-=16) {
1062     fprintf(stderr,"%05d  ",left);
1063     for (i=0; i<8; i++) {
1064       fprintf(stderr,"%02x",*ptr++);
1065       fprintf(stderr,"%02x ",*ptr++);
1066     }
1067     fprintf(stderr,"\n");
1068   }
1069 }
1070 #endif /* 0 */
1071 
1072 static void
loadbuffer(void)1073 loadbuffer(void)
1074 {
1075   if ((bytesleft=fread(buffer,1,NBYTESINBUF,fp)) == 0) {
1076     fprintf(stderr,"Truncation error\n");
1077     exit(1);
1078   }
1079   bufptr=buffer;
1080   /* dumpbuffer(); */
1081 }
1082 
1083 static void
loadbyte(void)1084 loadbyte(void)
1085 {
1086   if (bytesleft <= 0) loadbuffer();
1087   --bytesleft;
1088   word|=(WORDTYPE)(*bufptr++)<<(sizeof(WORDTYPE)*8-8-bitsleft);
1089   bitsleft+=8;
1090 }
1091 
1092 static int
getbit(void)1093 getbit(void)
1094 {
1095   int bit;
1096 
1097   while (bitsleft <= 0) loadbyte();
1098   --bitsleft;
1099   bit=(SWORDTYPE)(word)<0;  /* assumes word is signed */
1100   /* bit=word>>(sizeof(WORDTYPE)*8-1); */
1101   word<<=1;
1102   return bit;
1103 }
1104 
1105 static WORDTYPE
getnn(int nn)1106 getnn(int nn)
1107 {
1108   WORDTYPE value;
1109 
1110   while (bitsleft <= nn) loadbyte();
1111   bitsleft-=nn;
1112   value=word>>(sizeof(WORDTYPE)*8-nn);
1113   word<<=nn;
1114   return value;
1115 }
1116 
1117 static WORDTYPE
isnn(int nn)1118 isnn(int nn)
1119 {
1120   WORDTYPE value;
1121 
1122   while (bitsleft <= nn) loadbyte();
1123   value=word>>(sizeof(WORDTYPE)*8-nn);
1124   return value;
1125 }
1126 
1127 static void
skipnn(int nn)1128 skipnn(int nn)
1129 {
1130   while (bitsleft <= nn) loadbyte();
1131   bitsleft-=nn;
1132   word<<=nn;
1133 }
1134 
1135 #define get1()    (getbit())
1136 #define get2()    (getnn(2))
1137 #define get8()    (getnn(8))
1138 #define get13()    (getnn(13))
1139 #define get16()    (getnn(16))
1140 #define get24()    (getnn(24))
1141 
1142 #define is24()    (isnn(24))
1143 
1144 #define skip1()    (skipnn(1))
1145 #define skip24()  (skipnn(24))
1146 
1147 static int
gethuffdata(byte * luma,byte * chroma1,byte * chroma2,int realrowwidth,int maxrownumber)1148 gethuffdata(  byte *luma,
1149     byte *chroma1,
1150     byte *chroma2,
1151     int realrowwidth,
1152     int maxrownumber)
1153 {
1154 static  byte  clip[3*256];
1155   int  *hufftable[3], *huffstart = NULL, *huffptr = NULL;
1156   int  row, col, plane, i, result = 1;
1157 #if TRACE
1158   int  uflow = 0, oflow = 0;
1159 #endif
1160   byte  *pixelptr = NULL;
1161 
1162   trace((stderr,"gethuffdata: start @ 0x%08lx (sector %ld.%ld)\n",
1163       ftell(fp), ftell(fp)/0x800, ftell(fp) % 0x800));
1164 
1165   /*
1166    * correction clipping
1167    */
1168   if(clip[256+255] == 0) {
1169     for(i = 0; i < 256; ++i)
1170       clip[i +   0] = 0x00,
1171       clip[i + 256] = (byte) i,
1172       clip[i + 512] = 0xff;
1173   }
1174 
1175   /*
1176    * should really only look for luma plane for 4base, but the
1177    * there are zeroes in the rest of the sector that give both
1178    * chroma tables 0 length
1179    */
1180   for(i = 0; i < 3; ++i)
1181     hufftable[i] = NULL;
1182   for(i = 0; i < 3; ++i) {
1183     if((hufftable[i] = gethufftable()) == NULL) {
1184       result = 0;
1185       break;
1186     }
1187   }
1188   if(result == 0)
1189     goto oops;
1190 
1191   /*
1192    * skip remainder of current sector
1193    */
1194   i = (ftell(fp) | 0x7ff) + 1;
1195   if(fseek(fp, i, SEEK_SET) < 0) {
1196     fprintf(stderr, "gethuffdata: sector skip failed\n");
1197     return 0;
1198   }
1199 
1200   /*
1201    * skip remainder of "sector"
1202    */
1203   i = 0;
1204   while (is24() != 0xfffffe) {
1205     (void)get24();
1206     if(++i == 1)
1207       trace((stderr,"gethuffdata: skipping for sync ..."));
1208   }
1209   if(i != 0)
1210     trace((stderr, " %d times\n", i));
1211 
1212   while(result) {
1213     if(is24() == 0xfffffe) {
1214       skip24();
1215       plane = get2();
1216       row = get13(); col = 0;
1217       skip1();
1218       if(row >= maxrownumber) {
1219         trace((stderr,
1220           "gethuffdata: stopping at row %d\n",
1221                 row));
1222         break;
1223       }
1224       switch (plane) {
1225       case  0:
1226         huffstart = hufftable[0];
1227         pixelptr  = luma + row*realrowwidth;
1228         break;
1229 
1230       case  2:
1231         huffstart = hufftable[1];
1232         pixelptr  = chroma1 + row/2*realrowwidth/2;
1233         break;
1234 
1235       case  3:
1236         huffstart = hufftable[2];
1237         pixelptr  = chroma2 + row/2*realrowwidth/2;
1238         break;
1239 
1240       default:
1241         fprintf(stderr, "gethuffdata: bad plane %d\n",
1242                   plane);
1243         result = 0;
1244         break;
1245       }
1246       WaitCursor();
1247       continue;
1248     }
1249 
1250     /*
1251      * locate correction in huffman tree
1252      */
1253     for(huffptr = huffstart;;) {
1254       huffptr += get1();
1255       if(*huffptr < 0) {
1256         huffptr -= *huffptr;
1257       } else if(*huffptr == 0) {
1258         fprintf(stderr,
1259           "gethuffdata: invalid code: "
1260             "image quality reduced\n");
1261         result = 0;
1262         break;
1263       } else
1264         break;
1265     }
1266     if(!result)
1267       break;
1268 
1269     /*
1270      * apply correction to the pixel
1271      *
1272      * eeeek!!  the corrections can sometimes over or underflow!
1273      * this strongly suggested that the 'magnify' method was in
1274      * some way wrong.  however, experiments showed that the
1275      * over/under flows even occured for the pixels that are
1276      * copied through magnify without change (ie, the even
1277      * row/even column case).  curiously, though, the odd
1278      * column and odd row cases were about 3x more likely to have
1279      * the over/underflow, and the odd row/odd column case was
1280      * about 5x higher, so maybe the use of a bi-linear
1281      * interpolation is not correct -- just *close*?
1282      *
1283      * the other clue in this area is that the overflows are
1284      * by far most frequenct along edges of very bright
1285      * areas -- rarely in the interior of such regions.
1286      */
1287     i = (int) *pixelptr + (signed char) (*huffptr - 1);
1288 #if TRACE
1289     if(i > 255)
1290       ++oflow;
1291 /*      trace((stderr,
1292         "gethuffdata: oflow %d %d %d\n", row, col, i));*/
1293     else if(i < 0)
1294       ++uflow;
1295 /*      trace((stderr,
1296         "gethuffdata: uflow %d %d %d\n", row, col, i));*/
1297     ++col;
1298 #endif
1299     *pixelptr++ = clip[i + 256];
1300   }
1301 
1302 oops:
1303   for(i = 0; i < 3; ++i)
1304     free(hufftable[i]);
1305   trace((stderr, "gethuffdata: uflow=%d oflow=%d\n", uflow, oflow));
1306   trace((stderr, "gethuffdata: done @ 0x%08lx (sector %ld.%d)\n",
1307         ftell(fp), ftell(fp)/0x800, 0x800 - bytesleft));
1308   return result;
1309 }
1310 
1311 #endif /* HAVE_PCD */
1312