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