1 /*
2 * $Id: xvpic2.c,v 2.9.1.14 1995/04/24 15:34:15 ikeyan Exp $
3 * xvpic2.c - load and save routines for `PIC2' format pictures.
4 *
5 *
6 * Outline
7 * =======
8 * xvpic2.c supports the PIC2 format image file. It is used some
9 * Japanese personal computer users.
10 *
11 * The PIC2 format is designed by A.Yanagisawa. It is an excellent
12 * format except for its encode/decode speed. ;-)
13 *
14 * The features of the PIC2 format:
15 * - Powerful header information (included author, filename, title,
16 * saver, product number, created date and comment).
17 * - Reversible compression, and very high compression ratio (in many
18 * cases, a higher compression ratio than the JPEG compression;
19 * because of its compression method, PIC2 is especially good at
20 * pictures like cell animation).
21 * - Can handle full-color (24 bits) image.
22 * - Can include multi image blocks into one PIC2 file.
23 * - Have four different block format (P2SS, P2SF, P2BM and
24 * P2BI). P2SS format uses arithmetic compression for storing
25 * data. P2SF uses normal run-length compression. P2BM and P2BI is
26 * raw image format. Select any one according to the situation.
27 *
28 * Explanation of the PIC2 compression:
29
30 * - In the first place, try to record pixel color, uses color caches
31 * which keep some recent colors, and formed according to color's
32 * frequency. PIC2 has some color cache spaces that are switched by
33 * upper pixel value of current pixel. If cache is hit, record
34 * that.
35 * - Unfortunately, in the case of color cache didn't hit, record the
36 * difference from the value estimated with the value of upper and
37 * left pixel of current pixel (similar to PNG's AVG predictor).
38 * - And extract image's color chain if exist, and record that (it
39 * results in image's outline).
40 * - In all cases, arithmetic compression is used in the final stage
41 * before writing the file, which in theory produces the ideal
42 * compression ratio (P2SS).
43 *
44 * Features
45 * ========
46 * - Support 3,6,9,12,15,18,21,24bit PIC2 format (Load/Save).
47 * - Support all image block formats of PIC2 (Load/Save).
48 * - Support multi block PIC2 file (Load/Save).
49 *
50 *
51 * Bugs
52 * ====
53 * - Unsupport 8bit PIC2 image file.
54 *
55 * If you find other bugs (surely exist :-)), send me bug-report.
56 *
57 *
58 * Author
59 * ======
60 * IKEMOTO Masahiro <ikeyan@airlab.cs.ritsumei.ac.jp>
61 */
62
63 #define PIC2_IGNORE_UNUSED_FUNCTIONS
64 #define NEEDSDIR
65
66 #include "xv.h"
67 #include <setjmp.h>
68
69 #ifdef HAVE_PIC2
70
71 typedef unsigned long pixel;
72
73 #define pic2_cextoshort(addr) ( \
74 (((short) (((byte *) addr)[0])) << 8) | \
75 ( (short) (((byte *) addr)[1])) \
76 )
77 #define pic2_cextolong(addr) ( \
78 (((long) (((byte *) addr)[0])) << 24) | \
79 (((long) (((byte *) addr)[1])) << 16) | \
80 (((long) (((byte *) addr)[2])) << 8) | \
81 ( (long) (((byte *) addr)[3])) \
82 )
83 #define pic2_shorttocex(addr, n) { \
84 ((byte *) addr)[0] = (((unsigned short) (n) >> 8) & 0xff); \
85 ((byte *) addr)[1] = ( (unsigned short) (n) & 0xff); \
86 }
87 #define pic2_longtocex(addr, n) { \
88 ((byte *) addr)[0] = (((unsigned long) (n) >> 24) & 0xff); \
89 ((byte *) addr)[1] = (((unsigned long) (n) >> 16) & 0xff); \
90 ((byte *) addr)[2] = (((unsigned long) (n) >> 8) & 0xff); \
91 ((byte *) addr)[3] = ( (unsigned long) (n) & 0xff); \
92 }
93 #define pic2_shift_bits(b, n) (((n) > 0) ? ((b) << (n)) : ((b) >> -(n)))
94
95 #define PIC2_READ_MODE 0
96 #define PIC2_WRITE_MODE 1
97
98 #define PIC2_ARITH_CACHE 32
99 #define PIC2_ARITH_CONTEXT 128
100 #define PIC2_FAST_CACHE 64
101
102 #define PIC2_HEADER_SIZE 124
103 #define PIC2_BLOCK_HEADER_SIZE 26
104
105 struct pic2_header {
106 char magic[4];
107 char name[18];
108 char subtitle[8];
109 char crlf0[2];
110 char title[30];
111 char crlf1[2];
112 char saver[30];
113 char crlf2[2];
114 char eof[1];
115 char reserve0[1];
116 short flag;
117 short no;
118 long time;
119 long size;
120 short depth;
121 short x_aspect;
122 short y_aspect;
123 short x_max;
124 short y_max;
125 long reserve1;
126 };
127
128 struct pic2_block {
129 char id[4];
130 long size;
131 short flag;
132 short x_wid;
133 short y_wid;
134 short x_offset;
135 short y_offset;
136 long opaque;
137 long reserve;
138 };
139
140 struct pic2_info {
141 jmp_buf jmp;
142 FILE *fp;
143 struct {
144 int rest;
145 byte cur;
146 int bits;
147 char zero;
148 }bs;
149 long fsize;
150 struct pic2_header *header;
151 struct pic2_block *block;
152 int n_pal;
153 int pal_bits;
154 byte pal[256][3];
155 char *comment;
156 char mode;
157 long next_pos;
158 long block_pos;
159 short x_max;
160 short y_max;
161 int ynow;
162 byte *buf;
163 pixel *vram_prev;
164 pixel *vram_now;
165 pixel *vram_next;
166 short *flag_now;
167 short *flag_next;
168 short *flag2_now;
169 short *flag2_next;
170 short *flag2_next2;
171 pixel (*cache)[PIC2_ARITH_CACHE];
172 unsigned short *cache_pos;
173 unsigned short *mulu_tab;
174 long aa;
175 long cc;
176 long dd;
177 char cache_hit_c;
178 int (*next_line) PARM((struct pic2_info *, pixel **));
179 char writing_grey;
180 char pagebname[64];
181 int pnum;
182 };
183
184 static void pic2_open_file PARM((struct pic2_info*,char*));
185 static void pic2_read_header PARM((struct pic2_info*));
186 static void pic2_read_block_header1 PARM((struct pic2_info*));
187 static void pic2_read_block_header2 PARM((struct pic2_info*));
188 static short pic2_arith_decode_bit PARM((struct pic2_info*,int));
189 static short pic2_arith_decode_nn PARM((struct pic2_info*,int));
190 static void pic2_arith_expand_chain PARM((struct pic2_info*,int,int,pixel));
191 static short pic2_arith_get_number PARM((struct pic2_info*,int,int));
192 static pixel pic2_arith_read_color PARM((struct pic2_info*,int));
193 static int pic2_arith_expand_line PARM((struct pic2_info*,pixel**));
194 static int pic2_arith_loader_init PARM((struct pic2_info*));
195 static int pic2_fast_read_length PARM((struct pic2_info*));
196 static void pic2_fast_expand_chain PARM((struct pic2_info*,int,pixel));
197 static pixel pic2_fast_read_color PARM((struct pic2_info*,pixel));
198 static int pic2_fast_expand_line PARM((struct pic2_info*,pixel**));
199 static int pic2_fast_loader_init PARM((struct pic2_info*));
200 static int pic2_beta_expand_line PARM((struct pic2_info*,pixel**));
201 static int pic2_beta_loader_init PARM((struct pic2_info*));
202 static void pic2_make_xvpic PARM((struct pic2_info*,byte**,
203 byte*,byte*,byte*));
204 static void pic2_make_pagefile PARM((struct pic2_info*,char*,int));
205 static void pic2_setup_pic2_info PARM((struct pic2_info*,
206 char*,char*,char*,char*,
207 int,int,int,int,int,int,char *));
208 static void pic2_append PARM((struct pic2_info*));
209 static void pic2_write_header1 PARM((struct pic2_info*));
210 static void pic2_write_header2 PARM((struct pic2_info*));
211 static void pic2_write_block_header PARM((struct pic2_info*));
212 static void pic2_arith_write_zero_bit PARM((struct pic2_info*));
213 static void pic2_arith_flush_bit_buf PARM((struct pic2_info*));
214 static void pic2_arith_carry_bit PARM((struct pic2_info*));
215 static void pic2_arith_encode_bit PARM((struct pic2_info*,int,int));
216 static void pic2_arith_encode_nbyte PARM((struct pic2_info*,int,int,int));
217 static void pic2_arith_encode_nn PARM((struct pic2_info*,int,int));
218 static void pic2_arith_press_chain PARM((struct pic2_info*,int));
219 static void pic2_arith_put_number PARM((struct pic2_info*,int,int,int));
220 static void pic2_arith_write_color PARM((struct pic2_info*,int));
221 static void pic2_arith_press_line2 PARM((struct pic2_info*));
222 static int pic2_arith_press_line PARM((struct pic2_info*,pixel**));
223 static int pic2_arith_saver_init PARM((struct pic2_info*,pixel**));
224 static void pic2_fast_write_length PARM((struct pic2_info*,int));
225 static void pic2_fast_press_chain PARM((struct pic2_info*,int));
226 static void pic2_fast_press_chain2 PARM((struct pic2_info*,int));
227 static void pic2_fast_flush_chain PARM((struct pic2_info*));
228 static void pic2_fast_write_color PARM((struct pic2_info*,int));
229 static void pic2_fast_press_line2 PARM((struct pic2_info*));
230 static int pic2_fast_press_line PARM((struct pic2_info*,pixel**));
231 static int pic2_fast_saver_init PARM((struct pic2_info*,pixel**));
232 static int pic2_beta_press_line PARM((struct pic2_info*,pixel**));
233 static int pic2_beta_saver_init PARM((struct pic2_info*,pixel**));
234 static void pic2_write_data PARM((struct pic2_info*,byte*,
235 int,int,int,int,int,
236 byte*,byte*,byte*,int,int));
237 static int pic2_next_line PARM((struct pic2_info*,pixel**));
238 static int pic2_next_block PARM((struct pic2_info*));
239 static int pic2_find_block PARM((struct pic2_info*));
240 static int pic2_load_block PARM((struct pic2_info*));
241 static int pic2_save_block PARM((struct pic2_info*,pixel**,
242 int,int,int,int,char*,pixel));
243 #ifndef PIC2_IGNORE_UNUSED_FUNCTIONS
244 static void pic2_read_palette PARM((struct pic2_info*,
245 byte*,byte*,byte*));
246 static void pic2_write_palette PARM((struct pic2_info*,int,int,
247 byte*,byte*,byte*));
248 #endif /* !PIC2_IGNORE_UNUSED_FUNCTIONS */
249 static byte pic2_convert_color_bits PARM((int,int,int));
250 static byte pic2_pad_color_bits PARM((int,int,int));
251 static byte pic2_reduce_color_bits PARM((int,int,int));
252 static pixel pic2_exchange_rg PARM((pixel,int));
253 static void pic2_handle_para PARM((struct pic2_info*,int));
254 static int pic2_alloc_buffer PARM((struct pic2_info*));
255 static void pic2_free_buffer PARM((struct pic2_info*));
256 static long pic2_seek_file PARM((struct pic2_info*,long,int));
257 static long pic2_tell_file PARM((struct pic2_info*));
258 static int pic2_read_file PARM((struct pic2_info*,void*,size_t));
259 static long pic2_read_long PARM((struct pic2_info*));
260 static short pic2_read_short PARM((struct pic2_info*));
261 static char pic2_read_char PARM((struct pic2_info*));
262 static int pic2_write_file PARM((struct pic2_info*,void*,size_t));
263 static int pic2_write_long PARM((struct pic2_info*,long));
264 static int pic2_write_short PARM((struct pic2_info*,int));
265 static int pic2_write_char PARM((struct pic2_info*,int));
266 static unsigned long pic2_read_bits PARM((struct pic2_info*,int));
267 static void pic2_write_bits PARM((struct pic2_info*,
268 unsigned long,int));
269 static void pic2_flush_bits PARM((struct pic2_info*));
270 static void pic2_memory_error PARM((char*,char*));
271 static void pic2_error PARM((struct pic2_info*,int));
272 static void pic2_file_error PARM((struct pic2_info*,int));
273 static void pic2_init_info PARM((struct pic2_info*));
274 static void pic2_cleanup_pic2_info PARM((struct pic2_info*,int));
275 static void pic2_cleanup_pinfo PARM((PICINFO*));
276 static void pic2_show_pic2_info PARM((struct pic2_info*));
277 static char *pic2_strncpy PARM((char*,char*,size_t));
278 static void *pic2_malloc PARM((size_t,char*));
279 static void *pic2_new PARM((size_t,char*));
280
281 static int WritePIC2 PARM((FILE*,byte*,int,int,int,
282 byte*,byte*,byte*,int,int,char*,
283 int,int,int,int,int,char*));
284
285 static char *pic2_id = "P2DT";
286
287 /* Error Messages */
288 static char *pic2_msgs[] = {
289 NULL,
290 #define PIC2_OPEN 1
291 "can't open file.",
292 #define PIC2_CORRUPT 2
293 "file corrupted.",
294 #define PIC2_FORMAT 3
295 "not PIC2 format.",
296 #define PIC2_DEPTH 4
297 "bit depths not divisible by 3 are unsupported.",
298 #define PIC2_TMPFILE 5
299 "unable to create temporary filename???",
300 #define PIC2_PAGE 6
301 "couldn't load the page.",
302 #define PIC2_APPEND 7
303 "cannot append.",
304 #define PIC2_WRITE 8
305 "write failed.",
306 };
307
308 struct _form_tab {
309 char *id;
310 int (*loader_init) PARM((struct pic2_info *));
311 int (*saver_init) PARM((struct pic2_info *, pixel **));
312 } form_tab[] = {
313 { "P2SS", pic2_arith_loader_init, pic2_arith_saver_init},
314 { "P2SF", pic2_fast_loader_init, pic2_fast_saver_init},
315 { "P2BM", pic2_beta_loader_init, pic2_beta_saver_init},
316 { "P2BI", pic2_beta_loader_init, pic2_beta_saver_init},
317 };
318 #define n_form_tab (sizeof(form_tab) / sizeof(struct _form_tab))
319 #define P2SS 0
320 #define P2SF 1
321 #define P2BM 2
322 #define P2BI 3
323
324 /* The main routine to load a PIC2 file. */
LoadPIC2(fname,pinfo,quick)325 int LoadPIC2(fname, pinfo, quick)
326 char *fname;
327 PICINFO *pinfo;
328 int quick;
329 {
330 int e, i, block;
331 struct pic2_info pic2;
332
333 if (DEBUG)
334 fputs("LoadPIC2:\n", stderr);
335
336 pic2_init_info(&pic2);
337
338 if ((e = setjmp(pic2.jmp)) != 0){
339 /* When an error occurs, comes here. */
340 pic2_free_buffer(&pic2);
341 pic2_cleanup_pic2_info(&pic2, 0);
342 pic2_cleanup_pinfo(pinfo);
343 if (pic2split)
344 KillPageFiles(pic2.pagebname, pic2.pnum);
345 SetCursors(-1);
346 if (DEBUG)
347 fputs("\n", stderr);
348 return (0);
349 }
350 pic2_open_file(&pic2, fname);
351 pic2_read_header(&pic2);
352
353 if ((i = pic2_find_block(&pic2)) == 0)
354 pic2_file_error(&pic2, PIC2_CORRUPT);
355
356 block = 1;
357 while(i == 2) {
358 SetISTR(ISTR_WARNING, "unknown or invalid block #%d.", block);
359 i = pic2_next_block(&pic2);
360 block++;
361 }
362
363 if (pic2split && !quick) {
364 char firstpage[512];
365 struct stat st;
366 #ifndef USE_MKSTEMP
367 int tmpfd;
368 #endif
369
370 #ifndef VMS
371 sprintf(pic2.pagebname, "%s/xvpic2XXXXXX", tmpdir);
372 #else
373 sprintf(pic2.pagebname, "Sys$Scratch:xvpic2XXXXXX");
374 #endif
375 #ifdef USE_MKSTEMP
376 close(mkstemp(pic2.pagebname));
377 #else
378 mktemp(pic2.pagebname);
379 tmpfd = open(pic2.pagebname, O_WRONLY|O_CREAT|O_EXCL, S_IRWUSR);
380 if (tmpfd < 0) FatalError("LoadPIC2(): can't create temporary file");
381 close(tmpfd);
382 #endif
383 if (pic2.pagebname[0] == '\0')
384 pic2_error(&pic2, PIC2_TMPFILE);
385 strcat(pic2.pagebname, ".");
386
387 sprintf(firstpage, "%s%d", pic2.pagebname, 1);
388 if (stat(firstpage, &st)) {
389 for (pic2.pnum = 1; i >= 1; pic2.pnum++) {
390 pic2_load_block(&pic2);
391 pic2_make_pagefile(&pic2, pic2.pagebname, pic2.pnum);
392 while(block++, (i = pic2_next_block(&pic2)) == 2)
393 SetISTR(ISTR_WARNING,
394 "unknown or invalid block #%d.", block);
395 }
396 pinfo->numpages = --pic2.pnum;
397 if (!LoadPIC2(firstpage, pinfo, 1))
398 pic2_error(&pic2, PIC2_PAGE);
399 if (pic2.pnum == 1)
400 unlink(firstpage);
401 else
402 strcpy(pinfo->pagebname, pic2.pagebname);
403 } else
404 if (!LoadPIC2(fname, pinfo, 1))
405 pic2_error(&pic2, PIC2_PAGE);
406 } else {
407 char buf[128], format[64];
408 int j;
409
410 pinfo->w = pic2.x_max;
411 pinfo->h = pic2.y_max;
412 pinfo->normw = pinfo->w;
413 pinfo->normh = pinfo->h;
414 pinfo->type = PIC24;
415 for (j = 0; j < n_form_tab; j++) {
416 if (xvbcmp(pic2.block->id, form_tab[j].id, (size_t) 4) == 0)
417 break;
418 }
419 pinfo->frmType = F_PIC2;
420 pinfo->colType = F_FULLCOLOR;
421 pinfo->comment = pic2.comment;
422
423 if (pic2split) {
424 pic2_make_xvpic(&pic2, &pinfo->pic, pinfo->r, pinfo->g, pinfo->b);
425 strcpy(format, form_tab[j].id);
426 } else {
427 for (pic2.pnum = 1; i >= 1; pic2.pnum++) {
428 SetISTR(ISTR_INFO, "composing block #%d", block);
429 pic2_make_xvpic(&pic2, &pinfo->pic,
430 pinfo->r, pinfo->g, pinfo->b);
431 while(block++, (i = pic2_next_block(&pic2)) == 2)
432 SetISTR(ISTR_WARNING,
433 "unknown or invalid block #%d.", block);
434 }
435 if (--block > 1)
436 if (block != --pic2.pnum)
437 sprintf(format, "MultiBlock[%d/%d]", block, pic2.pnum);
438 else
439 sprintf(format, "MultiBlock[%d]", block);
440 else
441 strcpy(format, form_tab[j].id);
442 }
443 sprintf(buf, "PIC2(%s). %d colors (%ld bytes)", format,
444 (int) 1 << pic2.header->depth, pic2.fsize);
445 strcat(pinfo->fullInfo, buf);
446 sprintf(pinfo->shrtInfo, "%dx%d(aspect %4.2f) PIC2(%s).",
447 pinfo->w, pinfo->h,
448 (float) pic2.header->x_aspect / (float) pic2.header->y_aspect,
449 format);
450 if (!nopicadjust)
451 normaspect = (float) pic2.header->x_aspect
452 / (float) pic2.header->y_aspect;
453 }
454 pic2_cleanup_pic2_info(&pic2, 0);
455 SetCursors(-1);
456 if (DEBUG)
457 fputs("\n", stderr);
458 return (1);
459 }
460
461 /*
462 * This function opens the file, and set its size.
463 */
pic2_open_file(pi,fname)464 static void pic2_open_file(pi, fname)
465 struct pic2_info *pi;
466 char *fname;
467 {
468 if ((pi->fp = fopen(fname, "rb")) == NULL)
469 pic2_file_error(pi, PIC2_OPEN);
470 fseek(pi->fp, (size_t) 0, SEEK_END);
471 pi->fsize = ftell(pi->fp);
472 fseek(pi->fp, (size_t) 0, SEEK_SET);
473 }
474
475 /*
476 * These functions read the PIC2 header informations.
477 * pic2_read_header:
478 * reads the PIC2 header.
479 * pic2_read_block_header1:
480 * reads the id number of block header and the size of block.
481 * pic2_read_block_header2:
482 * reads the rest of block header.
483 */
pic2_read_header(pi)484 static void pic2_read_header(pi)
485 struct pic2_info *pi;
486 {
487 long s_comment;
488
489 pi->mode = PIC2_READ_MODE;
490
491 /* read header image */
492 pic2_read_file(pi, pi->header->magic, 4);
493 pic2_read_file(pi, pi->header->name, 18);
494 pic2_read_file(pi, pi->header->subtitle, 8);
495 pic2_read_file(pi, pi->header->crlf0, 2);
496 pic2_read_file(pi, pi->header->title, 30);
497 pic2_read_file(pi, pi->header->crlf1, 2);
498 pic2_read_file(pi, pi->header->saver, 30);
499 pic2_read_file(pi, pi->header->crlf2, 2);
500 pic2_read_file(pi, pi->header->eof, 1);
501 pic2_read_file(pi, pi->header->reserve0, 1);
502 pi->header->flag = pic2_read_short(pi);
503 pi->header->no = pic2_read_short(pi);
504 pi->header->time = pic2_read_long(pi);
505 pi->header->size = pic2_read_long(pi);
506 pi->header->depth = pic2_read_short(pi);
507 pi->header->x_aspect = pic2_read_short(pi);
508 pi->header->y_aspect = pic2_read_short(pi);
509 pi->header->x_max = pic2_read_short(pi);
510 pi->header->y_max = pic2_read_short(pi);
511 pi->header->reserve1 = pic2_read_long(pi);
512
513 /* check magic number */
514 if (strncmp(pi->header->magic, pic2_id, (size_t) 4) != 0)
515 pic2_error(pi, PIC2_FORMAT);
516
517 /* read palette data, if exists */
518 if (pi->header->flag & 1) {
519 pi->pal_bits = pic2_read_char(pi);
520 pi->n_pal = pic2_read_short(pi);
521 pic2_read_file(pi, pi->pal, (size_t) (pi->n_pal * 3));
522 }
523
524 /* read comments */
525 s_comment = pi->header->size - pic2_tell_file(pi);
526 pi->comment = pic2_new(s_comment + 1, "pic2_read_header");
527 pic2_read_file(pi, pi->comment, (size_t) s_comment);
528 pi->comment[s_comment] = '\0';
529
530 pi->x_max = pi->header->x_max;
531 pi->y_max = pi->header->y_max;
532
533 /* set initial block point */
534 pi->next_pos = pic2_tell_file(pi);
535 }
536
pic2_read_block_header1(pi)537 static void pic2_read_block_header1(pi)
538 struct pic2_info *pi;
539 {
540 pic2_read_file(pi, pi->block->id, 4);
541 pi->block->size = pic2_read_long(pi);
542 }
543
pic2_read_block_header2(pi)544 static void pic2_read_block_header2(pi)
545 struct pic2_info *pi;
546 {
547 pi->block->flag = pic2_read_short(pi);
548 pi->block->x_wid = pic2_read_short(pi);
549 pi->block->y_wid = pic2_read_short(pi);
550 pi->block->x_offset = pic2_read_short(pi);
551 pi->block->y_offset = pic2_read_short(pi);
552 pi->block->opaque = pic2_read_long(pi);
553 pi->block->reserve = pic2_read_long(pi);
554 }
555
556 /*
557 * These functions are arithmetic pic2 format extractor.
558 */
pic2_arith_decode_bit(pi,c)559 static short pic2_arith_decode_bit(pi, c)
560 struct pic2_info *pi;
561 int c;
562 {
563 unsigned short pp;
564
565 pp = pi->mulu_tab[(pi->aa & 0x7f00) / 2 + c];
566 if (pi->dd >= (int) pp) {
567 pi->dd -= pp;
568 pi->aa -= pp;
569
570 while ((short) pi->aa >= 0) {
571 pi->dd *= 2;
572 if (pic2_read_bits(pi, 1))
573 pi->dd++;
574 pi->aa *= 2;
575 }
576 return (1);
577 } else {
578 pi->aa = pp;
579
580 while ((short) pi->aa >= 0) {
581 pi->dd *= 2;
582 if (pic2_read_bits(pi, 1))
583 pi->dd++;
584 pi->aa *= 2;
585 }
586 return (0);
587 }
588 }
589
pic2_arith_decode_nn(pi,c)590 static short pic2_arith_decode_nn(pi, c)
591 struct pic2_info *pi;
592 int c;
593 {
594 int n;
595
596 if (pic2_arith_decode_bit(pi, c)) {
597 /* n < 1 */
598 n = 0;
599 } else if (pic2_arith_decode_bit(pi, c + 1)) {
600 /* n < 1 + 2 */
601 n = 1;
602 if (pic2_arith_decode_bit(pi, c + 8))
603 n += 1;
604 } else if (pic2_arith_decode_bit(pi, c + 2)) {
605 /* n < 1 + 2 + 4 */
606 n = 1 + 2;
607 if (pic2_arith_decode_bit(pi, c + 8))
608 n += 1;
609 if (pic2_arith_decode_bit(pi, c + 9))
610 n += 2;
611 } else if (pic2_arith_decode_bit(pi, c + 3)) {
612 /* n < 1 + 2 + 4 + 8 */
613 n = 1 + 2 + 4;
614 if (pic2_arith_decode_bit(pi, c + 8))
615 n += 1;
616 if (pic2_arith_decode_bit(pi, c + 9))
617 n += 2;
618 if (pic2_arith_decode_bit(pi, c + 10))
619 n += 4;
620 } else if (pic2_arith_decode_bit(pi, c + 4)) {
621 /* n < 1 + 2 + 4 + 8 + 16 */
622 n = 1 + 2 + 4 + 8;
623 if (pic2_arith_decode_bit(pi, c + 8))
624 n += 1;
625 if (pic2_arith_decode_bit(pi, c + 9))
626 n += 2;
627 if (pic2_arith_decode_bit(pi, c + 10))
628 n += 4;
629 if (pic2_arith_decode_bit(pi, c + 11))
630 n += 8;
631 } else if (pic2_arith_decode_bit(pi, c + 5)) {
632 /* n < 1 + 2 + 4 + 8 + 16 + 32 */
633 n = 1 + 2 + 4 + 8 + 16;
634 if (pic2_arith_decode_bit(pi, c + 8))
635 n += 1;
636 if (pic2_arith_decode_bit(pi, c + 9))
637 n += 2;
638 if (pic2_arith_decode_bit(pi, c + 10))
639 n += 4;
640 if (pic2_arith_decode_bit(pi, c + 11))
641 n += 8;
642 if (pic2_arith_decode_bit(pi, c + 12))
643 n += 16;
644
645 } else if (pic2_arith_decode_bit(pi, c + 6)) {
646 /* n < 1 + 2 + 4 + 8 + 16 + 32 + 64 */
647 n = 1 + 2 + 4 + 8 + 16 + 32;
648 if (pic2_arith_decode_bit(pi, c + 8))
649 n += 1;
650 if (pic2_arith_decode_bit(pi, c + 9))
651 n += 2;
652 if (pic2_arith_decode_bit(pi, c + 10))
653 n += 4;
654 if (pic2_arith_decode_bit(pi, c + 11))
655 n += 8;
656 if (pic2_arith_decode_bit(pi, c + 12))
657 n += 16;
658 if (pic2_arith_decode_bit(pi, c + 13))
659 n += 32;
660
661 } else if (pic2_arith_decode_bit(pi, c + 7)) {
662 /* n < 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 */
663 n = 1 + 2 + 4 + 8 + 16 + 32 + 64;
664 if (pic2_arith_decode_bit(pi, c + 8))
665 n += 1;
666 if (pic2_arith_decode_bit(pi, c + 9))
667 n += 2;
668 if (pic2_arith_decode_bit(pi, c + 10))
669 n += 4;
670 if (pic2_arith_decode_bit(pi, c + 11))
671 n += 8;
672 if (pic2_arith_decode_bit(pi, c + 12))
673 n += 16;
674 if (pic2_arith_decode_bit(pi, c + 13))
675 n += 32;
676 if (pic2_arith_decode_bit(pi, c + 14))
677 n += 64;
678
679 } else {
680 n = 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128;
681 }
682 return (n);
683 }
684
pic2_arith_expand_chain(pi,x,y,cc)685 static void pic2_arith_expand_chain(pi, x, y, cc)
686 struct pic2_info *pi;
687 int x, y;
688 pixel cc;
689 {
690 static const unsigned short c_tab[] = {
691 80 + 6 * 5, /* -5 */
692 80 + 6 * 4,
693 80 + 6 * 3,
694 80 + 6 * 2,
695 80 + 6 * 1,
696 80 + 6 * 0, /* 0 */
697 80 + 6 * 0, /* 1 */
698 };
699 unsigned short b;
700
701 b = c_tab[pi->flag_now[x] + 5];
702 if (!pic2_arith_decode_bit(pi, b++)) {
703 if (pic2_arith_decode_bit(pi, b++)) { /* down */
704 pi->vram_next[x ] = cc;
705 pi->flag_next[x ] = -1;
706 } else if (pic2_arith_decode_bit(pi, b++)) { /* left */
707 pi->vram_next[x - 1] = cc;
708 pi->flag_next[x - 1] = -2;
709 } else if (pic2_arith_decode_bit(pi, b++)) { /* right */
710 pi->vram_next[x + 1] = cc;
711 pi->flag_next[x + 1] = -3;
712 } else if (pic2_arith_decode_bit(pi, b++)) { /* left2 */
713 pi->vram_next[x - 2] = cc;
714 pi->flag_next[x - 2] = -4;
715 } else { /* right2 */
716 pi->vram_next[x + 2] = cc;
717 pi->flag_next[x + 2] = -5;
718 }
719 }
720 }
721
pic2_arith_get_number(pi,c,bef)722 static short pic2_arith_get_number(pi, c, bef)
723 struct pic2_info *pi;
724 int c, bef;
725 {
726 unsigned short n;
727 byte maxcol;
728
729 maxcol = 0xff >> (8 - pi->header->depth / 3);
730
731 n = pic2_arith_decode_nn(pi, c);
732 if (bef > ((int) maxcol >> 1)) {
733 if (n > ((int) maxcol - bef) * 2)
734 n = maxcol - n;
735 else if (n & 1)
736 n = n / 2 + bef + 1;
737 else
738 n = bef - n / 2;
739 } else {
740 if ((int) n > (bef * 2))
741 n = n;
742 else if (n & 1)
743 n = n / 2 + bef + 1;
744 else
745 n = bef - n / 2;
746 }
747 return (n);
748 }
749
pic2_arith_read_color(pi,x)750 static pixel pic2_arith_read_color(pi, x)
751 struct pic2_info *pi;
752 int x;
753 {
754 pixel c1, c2, cc;
755 unsigned short i, j, k, m;
756 short r, g, b, r0, g0, b0;
757 short colbits;
758 pixel rmask, gmask, bmask;
759 byte maxcol;
760
761 colbits = pi->header->depth / 3;
762 rmask = (0xff >> (8 - colbits)) << (colbits * 2);
763 gmask = (0xff >> (8 - colbits)) << colbits;
764 bmask = (0xff >> (8 - colbits));
765 maxcol = (byte) bmask;
766
767 c1 = pi->vram_prev[x];
768 k = ((c1 >> ((colbits - 3) * 3)) & 0x1c0)
769 | ((c1 >> ((colbits - 3) * 2)) & 0x038)
770 | ((c1 >> (colbits - 3) ) & 0x007);
771 if (colbits == 5)
772 k = pic2_exchange_rg(k, 3);
773
774 if (pic2_arith_decode_bit(pi, pi->cache_hit_c)) { /* ouch */
775 pi->cache_hit_c = 16;
776
777 c2 = pi->vram_now[x - 1];
778 r = ((c1 & rmask) + (c2 & rmask)) >> (colbits * 2 + 1);
779 g = ((c1 & gmask) + (c2 & gmask)) >> (colbits + 1);
780 b = ((c1 & bmask) + (c2 & bmask)) >> ( 1);
781
782 g0 = pic2_arith_get_number(pi, 32, g);
783 r = r + g0 - g;
784 if (r > (short) maxcol)
785 r = maxcol;
786 else if (r < 0)
787 r = 0;
788
789 b = b + g0 - g;
790 if (b > (short) maxcol)
791 b = maxcol;
792 else if (b < 0)
793 b = 0;
794
795 r0 = pic2_arith_get_number(pi, 48, r);
796 b0 = pic2_arith_get_number(pi, 64, b);
797
798 pi->cache_pos[k] = j = (pi->cache_pos[k] - 1) & (PIC2_ARITH_CACHE - 1);
799 pi->cache[k][j] = cc = (r0 << (colbits * 2)) | (g0 << colbits) | b0;
800 } else {
801 pi->cache_hit_c = 15;
802
803 j = pic2_arith_decode_nn(pi, 17);
804 m = pi->cache_pos[k];
805 i = (m + j / 2) & (PIC2_ARITH_CACHE - 1);
806 j = (m + j) & (PIC2_ARITH_CACHE - 1);
807
808 cc = pi->cache[k][j];
809 pi->cache[k][j] = pi->cache[k][i];
810 pi->cache[k][i] = pi->cache[k][m];
811 pi->cache[k][m] = cc;
812 }
813 return (cc);
814 }
815
pic2_arith_expand_line(pi,line)816 static int pic2_arith_expand_line(pi, line)
817 struct pic2_info *pi;
818 pixel **line;
819 {
820 int ymax;
821 int x, xw;
822 pixel cc;
823
824 pic2_handle_para(pi, 0);
825
826 xw = pi->block->x_wid;
827 ymax = pi->block->y_wid - 1;
828
829 if (pi->ynow > ymax)
830 return (-2); /* end */
831
832 /* set right end of previous line before left end of current line. */
833 if (pi->ynow == 0) {
834 cc = 0;
835 } else
836 cc = pi->vram_prev[xw - 1];
837 pi->vram_now[-1] = cc;
838
839 /* clear flag for change point */
840 xvbzero((char *) pi->flag_next, xw * sizeof(pi->flag_next[0]));
841
842 /* clear flag for position probability space */
843 xvbzero((char *) pi->flag2_next2, xw * sizeof(pi->flag2_next2[0]));
844
845 for (x = 0; x < xw; x++) {
846 if (pi->flag_now[x] < 0) {
847 cc = pi->vram_now[x];
848 if (pi->ynow < ymax)
849 pic2_arith_expand_chain(pi, x, pi->ynow, cc);
850 } else if (pic2_arith_decode_bit(pi, pi->flag2_now[x])) {
851 /* ajust probability space around of change point */
852 pi->flag2_now [x + 1]++;
853 pi->flag2_now [x + 2]++;
854 pi->flag2_next [x - 1]++;
855 pi->flag2_next [x ]++;
856 pi->flag2_next [x + 1]++;
857 pi->flag2_next2[x - 1]++;
858 pi->flag2_next2[x ]++;
859 pi->flag2_next2[x + 1]++;
860
861 pi->vram_now[x] = cc = pic2_arith_read_color(pi, x);
862 if (pi->ynow < ymax)
863 pic2_arith_expand_chain(pi, x, pi->ynow, cc);
864 } else
865 pi->vram_now[x] = cc;
866 }
867 if (line != NULL)
868 *line = pi->vram_now;
869 pi->ynow++;
870
871 pic2_handle_para(pi, 1);
872
873 return (pi->ynow - 1);
874 }
875
pic2_arith_loader_init(pi)876 static int pic2_arith_loader_init(pi)
877 struct pic2_info *pi;
878 {
879 unsigned short p2b[256];
880 int i, xw;
881
882 pi->ynow = 0;
883
884 /* check the color depth */
885 if (pi->header->depth % 3)
886 pic2_error(pi, PIC2_DEPTH);
887
888 /* set function for extract next line */
889 pi->next_line = pic2_arith_expand_line;
890
891 /* clear cache and flags */
892 xw = pi->block->x_wid;
893 xvbzero((char *) pi->cache, 8 * 8 * 8 * sizeof(pi->cache[0]));
894 xvbzero((char *) pi->cache_pos, 8 * 8 * 8 * sizeof(pi->cache_pos[0]));
895
896 xvbzero((char *) pi->flag_now, xw * sizeof(pi->flag_now[0]));
897 xvbzero((char *) pi->flag2_now, 8 + xw * sizeof(pi->flag2_now[0]));
898 xvbzero((char *) pi->flag2_next, 8 + xw * sizeof(pi->flag2_next[0]));
899
900 /* go to picture data field */
901 pic2_seek_file(pi, pi->block_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
902
903 /* clear bit field marker */
904 pi->bs.rest = 0;
905 pi->bs.cur = 0;
906
907 /* read probability table */
908 for (i = 0; i < PIC2_ARITH_CONTEXT; i++)
909 p2b[i] = pic2_read_short(pi);
910
911 /* make multiplication table */
912 for (i = 0; i < 16384; i++) {
913 pi->mulu_tab[i] = (long) (i / 128 + 128) * (int) p2b[i & 127] / 256;
914 if (pi->mulu_tab[i] == 0) pi->mulu_tab[i] = 1;
915 }
916 /* initialize some valuables */
917 pi->aa = 0xffff;
918 pi->dd = 0;
919 for (i = 0; i < 16; i++) {
920 pi->dd *= 2;
921 if (pic2_read_bits(pi, 1))
922 pi->dd |= 1;
923 }
924 pi->cache_hit_c = 16;
925
926 return (0);
927 }
928
929 /*
930 * These functions are fast pic2 compression extractor.
931 */
pic2_fast_read_length(pi)932 static int pic2_fast_read_length(pi)
933 struct pic2_info *pi;
934 {
935 int a;
936
937 a = 0;
938 while (pic2_read_bits(pi, 1)) {
939 a++;
940 }
941 if (a == 0)
942 return (0);
943 return (pic2_read_bits(pi, a) + (1 << a) - 1);
944 }
945
pic2_fast_expand_chain(pi,x,cc)946 static void pic2_fast_expand_chain(pi, x, cc)
947 struct pic2_info *pi;
948 int x;
949 pixel cc;
950 {
951 if (pic2_read_bits(pi, 1) != 0) {
952 if (pic2_read_bits(pi, 1) != 0) { /* down */
953 pi->vram_next[x] = cc;
954 pi->flag_next[x] = -1;
955 } else if (pic2_read_bits(pi, 1) != 0) {
956 if (pic2_read_bits(pi, 1) == 0) { /* left2down */
957 pi->vram_next[x - 2] = cc;
958 pi->flag_next[x - 2] = -1;
959 } else { /* left1down */
960 pi->vram_next[x - 1] = cc;
961 pi->flag_next[x - 1] = -1;
962 }
963 } else {
964 if (pic2_read_bits(pi, 1) == 0) { /* right2down */
965 pi->vram_next[x + 2] = cc;
966 pi->flag_next[x + 2] = -1;
967 } else { /* left1down */
968 pi->vram_next[x + 1] = cc;
969 pi->flag_next[x + 1] = -1;
970 }
971 }
972 }
973 }
974
pic2_fast_read_color(pi,bc)975 static pixel pic2_fast_read_color(pi, bc)
976 struct pic2_info *pi;
977 pixel bc;
978 {
979 pixel cc;
980 unsigned short j, k, m;
981 short depth, colbits;
982 pixel (*cache)[PIC2_FAST_CACHE];
983
984 depth = pi->header->depth;
985 colbits = depth / 3;
986 cache = (pixel (*)[PIC2_FAST_CACHE]) pi->cache;
987
988 bc = pic2_exchange_rg(bc, colbits);
989 k = pic2_shift_bits(bc, 8 - depth);
990 if (pic2_read_bits(pi, 1) == 0) {
991 pi->cache_pos[k] = m = (pi->cache_pos[k] - 1) & (PIC2_FAST_CACHE - 1);
992 cc = pic2_read_bits(pi, depth);
993 cc = pic2_exchange_rg(cc, colbits);
994 cache[k][m] = cc;
995 } else {
996 j = pic2_read_bits(pi, 6); /* 6= log2(PIC2_FAST_CACHE) */
997 m = pi->cache_pos[k];
998 cc = cache[k][(m + j) & (PIC2_FAST_CACHE - 1)];
999 }
1000 return (cc);
1001 }
1002
pic2_fast_expand_line(pi,line)1003 static int pic2_fast_expand_line(pi, line)
1004 struct pic2_info *pi;
1005 pixel **line;
1006 {
1007 int ymax;
1008 int x, xw;
1009 pixel cc;
1010
1011 pic2_handle_para(pi, 0);
1012
1013 xw = pi->block->x_wid;
1014 ymax = pi->block->y_wid - 1;
1015
1016 if (pi->ynow > ymax)
1017 return (-2);
1018
1019 if (pi->ynow == 0) {
1020 pi->dd = 0;
1021 pi->aa = pic2_fast_read_length(pi);
1022 if (pi->aa == 1023)
1023 pi->dd = 1023;
1024 else if (pi->aa > 1023)
1025 pi->aa--;
1026 cc = 0;
1027 } else
1028 cc = pi->vram_prev[xw - 1];
1029
1030 xvbzero((char *) pi->flag_next, xw * sizeof(pi->flag_next[0]));
1031
1032 for (x = 0; x < xw; x++) {
1033 if (pi->dd > 0) {
1034 if (pi->flag_now[x] < 0) { /* on chain ? */
1035 cc = pi->vram_now[x];
1036 pic2_fast_expand_chain(pi, x, cc);
1037 if (--pi->dd == 0) {
1038 pi->aa = pic2_fast_read_length(pi);
1039 if (pi->aa == 1023)
1040 pi->dd = 1023;
1041 else if (pi->aa > 1023)
1042 pi->aa--;
1043 }
1044 } else
1045 pi->vram_now[x] = cc;
1046 } else {
1047 if (pi->flag_now[x] < 0) { /* on chain ? */
1048 cc = pi->vram_now[x];
1049 pic2_fast_expand_chain(pi, x, cc);
1050 } else if (--pi->aa < 0) {
1051 cc = pi->vram_now[x] = pic2_fast_read_color(pi, cc);
1052 pic2_fast_expand_chain(pi, x, cc);
1053 pi->aa = pic2_fast_read_length(pi);
1054 if (pi->aa == 1023)
1055 pi->dd = 1023;
1056 else if (pi->aa > 1023)
1057 pi->aa--;
1058 } else
1059 pi->vram_now[x] = cc;
1060 }
1061 }
1062 if (line != NULL)
1063 *line = pi->vram_now;
1064 pi->ynow++;
1065
1066 pic2_handle_para(pi, 1);
1067
1068 return (pi->ynow - 1);
1069 }
1070
pic2_fast_loader_init(pi)1071 static int pic2_fast_loader_init(pi)
1072 struct pic2_info *pi;
1073 {
1074 int xw;
1075
1076 pi->ynow = 0;
1077
1078 /* check the color depth */
1079 if (pi->header->depth % 3)
1080 pic2_error(pi, PIC2_DEPTH);
1081
1082 /* set function for extract next line */
1083 pi->next_line = pic2_fast_expand_line;
1084
1085 /* clear cache and flags */
1086 xw = pi->block->x_wid;
1087 xvbzero((char *) pi->cache, sizeof(pi->cache[0]) * 256);
1088 xvbzero((char *) pi->cache_pos, sizeof(pi->cache_pos[0]) * 8 * 8 * 8);
1089 xvbzero((char *) pi->flag_now, (xw + 8) * sizeof(pi->flag_now[0]));
1090 xvbzero((char *) pi->flag_next, (xw + 8) * sizeof(pi->flag_next[0]));
1091
1092 /* go to picture data field */
1093 pic2_seek_file(pi, pi->block_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
1094
1095 /* clear bit field marker */
1096 pi->bs.rest = 0;
1097 pi->bs.cur = 0;
1098
1099 return (0);
1100 }
1101
1102 /*
1103 * These functions are beta pic2 format extractor.
1104 */
pic2_beta_expand_line(pi,line)1105 static int pic2_beta_expand_line(pi, line)
1106 struct pic2_info *pi;
1107 pixel **line;
1108 {
1109 int i, xw, ymax;
1110 byte a, b, c, *p;
1111 pixel *pc;
1112 short depth, pixbyte, colbits;
1113
1114 depth = pi->header->depth;
1115 pixbyte = depth / 8 + ((depth % 8) > 0);
1116 colbits = depth / 3;
1117
1118 xw = pi->block->x_wid;
1119 ymax = pi->block->y_wid - 1;
1120
1121 if (pi->ynow > ymax)
1122 return (-2); /* end */
1123
1124 pc = pi->vram_now;
1125 p = (byte *) pi->vram_prev;
1126 if (pixbyte == 3) {
1127 pic2_read_file(pi, pi->vram_prev, (size_t) (xw * pixbyte));
1128 for (i = 0; i < xw; i++, pc++) {
1129 a = *p++;
1130 b = *p++;
1131 c = *p++;
1132 *pc = ((pixel) a << 16) | ((pixel) b << 8) | (pixel) c;
1133 }
1134 } else if (pixbyte == 2) {
1135 pic2_read_file(pi, pi->vram_prev, (size_t) (xw * 2));
1136 if (strncmp(pi->block->id, "P2BM", 4) == 0) {
1137 for (i = 0; i < xw; i++, pc++) {
1138 a = *p++;
1139 b = *p++;
1140 *pc = ((pixel) a << 8) | (pixel) b;
1141 if (colbits == 5) {
1142 *pc >>= 1;
1143 *pc = pic2_exchange_rg(*pc, colbits);
1144 }
1145 }
1146 } else {
1147 for (i = 0; i < xw; i++, pc++) {
1148 a = *p++;
1149 b = *p++;
1150 *pc = ((pixel) b << 8) | (pixel) a;
1151 if (colbits == 5) {
1152 *pc >>= 1;
1153 *pc = pic2_exchange_rg(*pc, colbits);
1154 }
1155 }
1156 }
1157 } else {
1158 pic2_read_file(pi, pi->vram_prev, (size_t) xw);
1159 for (i = 0; i < xw; i++)
1160 *pc++ = *p++;
1161 }
1162 if (line != NULL)
1163 *line = pi->vram_now;
1164
1165 pc = pi->vram_prev;
1166 pi->vram_prev = pi->vram_now;
1167 pi->vram_now = pi->vram_next;
1168 pi->vram_next = pc;
1169
1170 pi->ynow++;
1171 return (pi->ynow - 1);
1172 }
1173
pic2_beta_loader_init(pi)1174 static int pic2_beta_loader_init(pi)
1175 struct pic2_info *pi;
1176 {
1177 pi->ynow = 0;
1178 pi->next_line = pic2_beta_expand_line;
1179 pic2_seek_file(pi, pi->block_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
1180 return (0);
1181 }
1182
1183 /*
1184 * Make a picture from the expanded data.
1185 */
pic2_make_xvpic(pi,xp,rp,gp,bp)1186 static void pic2_make_xvpic(pi, xp, rp, gp, bp)
1187 struct pic2_info *pi;
1188 byte **xp, *rp, *gp, *bp;
1189 {
1190 int line, i;
1191 pixel *linep, opaque;
1192 short colbits;
1193 byte colmask;
1194
1195 if (*xp == NULL)
1196 *xp = pic2_new((size_t) pi->x_max * pi->y_max * 3, "pic2_make_xvpic"); // GRR POSSIBLE OVERFLOW / FIXME
1197
1198 if (pi->block->flag & 1)
1199 opaque = pi->block->opaque;
1200 else
1201 opaque = 0xffffffff;
1202
1203 colbits = pi->header->depth / 3;
1204 colmask = 0xff >> (8 - colbits);
1205
1206 line = pic2_load_block(pi);
1207 for (;;) {
1208 int pic_idx;
1209
1210 line = pic2_next_line(pi, &linep);
1211 if (line < 0)
1212 break;
1213 pic_idx = ((line + pi->block->y_offset) * pi->x_max
1214 + pi->block->x_offset) * 3;
1215
1216 for (i = 0; i < pi->block->x_wid; i++, linep++) {
1217 byte r, g, b;
1218
1219 if (*linep != opaque) {
1220 r = ((*linep >> (colbits * 2)) & colmask);
1221 r = pic2_convert_color_bits(r, colbits, 8);
1222 g = ((*linep >> colbits ) & colmask);
1223 g = pic2_convert_color_bits(g, colbits, 8);
1224 b = ( *linep & colmask);
1225 b = pic2_convert_color_bits(b, colbits, 8);
1226 (*xp)[pic_idx++] = r;
1227 (*xp)[pic_idx++] = g;
1228 (*xp)[pic_idx++] = b;
1229 } else
1230 pic_idx += 3;
1231
1232 WaitCursor();
1233 }
1234 }
1235 }
1236
1237 /*
1238 * This function splits a multiblock PIC2 file into several pages.
1239 */
pic2_make_pagefile(pi,pagebname,pnum)1240 static void pic2_make_pagefile(pi, pagebname, pnum)
1241 struct pic2_info *pi;
1242 char *pagebname;
1243 int pnum;
1244 {
1245 struct pic2_info pic2;
1246 FILE *fp;
1247 char pagefile[64], *buf;
1248 size_t imagesize;
1249
1250 sprintf(pagefile, "%s%d", pagebname, pnum);
1251 if ((fp = fopen(pagefile, "wb")) == NULL)
1252 pic2_error(pi, PIC2_WRITE);
1253
1254 xvbcopy((char *) pi, (char *) &pic2, sizeof(struct pic2_info));
1255 pic2.fp = fp;
1256
1257 pic2_write_header1(&pic2);
1258
1259 pic2_write_block_header(&pic2);
1260
1261 imagesize = pi->block->size - PIC2_BLOCK_HEADER_SIZE;
1262 buf = (char *) pic2_malloc(imagesize, "pic2_make_pagefile");
1263
1264 pic2_seek_file(pi, pi->block_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
1265 if (fread(buf, (size_t) 1, imagesize, pi->fp) < imagesize) {
1266 free(buf);
1267 pic2_file_error(pi, PIC2_CORRUPT);
1268 }
1269 if (fwrite(buf, (size_t) 1, imagesize, fp) < imagesize) {
1270 free(buf);
1271 pic2_error(pi, PIC2_WRITE);
1272 }
1273 free(buf);
1274
1275 pic2.next_pos = pic2_tell_file(&pic2);
1276 pic2_write_header2(&pic2);
1277
1278 fclose(fp);
1279 }
1280
1281 /* The main routine to save a PIC2 file. */
WritePIC2(fp,pic0,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle,fname,type,depth,x_offset,y_offset,append,comment)1282 static int WritePIC2(fp, pic0, ptype, w, h, rmap, gmap, bmap, numcols,
1283 colorstyle, fname, type, depth, x_offset, y_offset,
1284 append, comment)
1285 FILE *fp;
1286 byte *pic0;
1287 int ptype, w, h;
1288 byte *rmap, *gmap, *bmap;
1289 int numcols, colorstyle;
1290 char *fname;
1291 int type, depth;
1292 int x_offset, y_offset;
1293 int append;
1294 char *comment;
1295 {
1296 struct pic2_info pic2;
1297 char creator[256], title[256], saver[256];
1298 int e;
1299
1300 if (DEBUG)
1301 fputs("WritePIC2:\n", stderr);
1302
1303 pic2_init_info(&pic2);
1304 pic2.fp = fp;
1305 pic2.writing_grey = (colorstyle == F_GREYSCALE);
1306
1307 if ((e = setjmp(pic2.jmp)) != 0){
1308 /* When an error occurs while writing, comes here. */
1309 pic2_free_buffer(&pic2);
1310 pic2_cleanup_pic2_info(&pic2, 1);
1311 SetCursors(-1);
1312 if (DEBUG)
1313 fputs("\n", stderr);
1314 return (-1);
1315 }
1316 sprintf(creator, "XV Version %s", VERSTR);
1317 pic2_strncpy(title, comment, 30);
1318 sprintf(saver, "XV %s/UNIX/Bradley", VERSTR);
1319
1320 if (!append) {
1321 pic2_setup_pic2_info(&pic2, creator, fname, title, saver,
1322 0, depth, 1, 1, w, h, comment);
1323 pic2_write_header1(&pic2);
1324 } else {
1325 pic2_read_header(&pic2);
1326 pic2_append(&pic2);
1327 free(pic2.comment);
1328 pic2_setup_pic2_info(&pic2, creator, fname, title, saver,
1329 0, depth, 1, 1, w, h, comment);
1330 }
1331
1332 pic2_write_data(&pic2, pic0, ptype, x_offset, y_offset, w, h,
1333 rmap, gmap, bmap, type, depth);
1334 pic2_write_header2(&pic2);
1335
1336 pic2_cleanup_pic2_info(&pic2, 1);
1337 SetCursors(-1);
1338 if (DEBUG)
1339 fputs("\n", stderr);
1340 return (0);
1341 }
1342
1343 /*
1344 * This function initializes pic2_info.
1345 */
pic2_setup_pic2_info(pi,name,fname,title,saver,no,depth,x_aspect,y_aspect,x_max,y_max,comment)1346 static void pic2_setup_pic2_info(pi, name, fname, title, saver, no, depth,
1347 x_aspect, y_aspect, x_max, y_max, comment)
1348 struct pic2_info *pi;
1349 char *name, *fname, *title, *saver;
1350 int no, depth;
1351 int x_aspect, y_aspect;
1352 int x_max, y_max;
1353 char *comment;
1354 {
1355 char basename[256], *suffix;
1356
1357 pi->mode = PIC2_WRITE_MODE;
1358
1359 /* set magic number */
1360 strncpy(pi->header->magic, pic2_id, 4);
1361
1362 /* set creator's name */
1363 pic2_strncpy(pi->header->name, (char *) name, 18);
1364
1365 /* set title and subtitle */
1366 pic2_strncpy(pi->header->title, (char *) title, 30);
1367 strcpy(basename, BaseName(fname));
1368 suffix = (char *) rindex(basename, '.');
1369 if (suffix) {
1370 suffix++;
1371 if (!strcmp(suffix, "p2") || !strcmp(suffix, "P2"))
1372 *(suffix - 1) = '\0';
1373 }
1374 pic2_strncpy(pi->header->subtitle, basename, 8);
1375
1376 /* set saver */
1377 pic2_strncpy(pi->header->saver, saver, 30);
1378
1379 /* set picture number */
1380 pi->header->no = no;
1381
1382 /* import comment */
1383 pi->comment = comment;
1384
1385 /* set some picture's info */
1386 pi->header->depth = depth;
1387 pi->header->x_aspect = x_aspect;
1388 pi->header->y_aspect = y_aspect;
1389 pi->header->x_max = x_max;
1390 pi->header->y_max = y_max;
1391
1392 /* set some gaps */
1393 pi->header->crlf0[0] = pi->header->crlf1[0] = pi->header->crlf2[0] = 0x0d;
1394 pi->header->crlf0[1] = pi->header->crlf1[1] = pi->header->crlf2[1] = 0x0a;
1395
1396 pi->header->eof[0] = 0x1a;
1397 pi->header->reserve0[0] = 0;
1398 pi->header->reserve1 = 0;
1399
1400 /* set palettes */
1401 if (pi->n_pal > 0)
1402 pi->header->flag = 1;
1403 else
1404 pi->header->flag = 0;
1405 }
1406
1407 /*
1408 * This function appends to existing pic2 file.
1409 */
pic2_append(pi)1410 static void pic2_append(pi)
1411 struct pic2_info *pi;
1412 {
1413 int block;
1414
1415 block = pic2_find_block(pi);
1416 while (block > 0)
1417 block = pic2_next_block(pi);
1418
1419 if (block != 0)
1420 pic2_error(pi, PIC2_APPEND);
1421 }
1422
1423 /*
1424 * These functions write the PIC2 header.
1425 * pic2_write_header1:
1426 * write palette data and comment.
1427 * pic2_write_header2:
1428 * write the terminate block and rest header.
1429 * pic2_write_block_header:
1430 * write the block header.
1431 */
pic2_write_header1(pi)1432 static void pic2_write_header1(pi)
1433 struct pic2_info *pi;
1434 {
1435 char *comment;
1436
1437 /* seek to block start position */
1438 pic2_seek_file(pi, PIC2_HEADER_SIZE, SEEK_SET);
1439
1440 /* write palette */
1441 if (pi->n_pal > 0) {
1442 pic2_write_char(pi, pi->pal_bits);
1443 pic2_write_short(pi, pi->n_pal);
1444 pic2_write_file(pi, pi->pal, (size_t) (pi->n_pal * 3));
1445 }
1446 /* save comment */
1447 comment = pi->comment;
1448 if (pi->comment != NULL) {
1449 for (comment = pi->comment; *comment; comment++) {
1450 if (*comment == '\n') {
1451 pic2_write_char(pi, '\r');
1452 pic2_write_char(pi, '\n');
1453 } else if (*comment != '\r')
1454 pic2_write_char(pi, *comment);
1455 }
1456 pic2_write_char(pi, 0);
1457 }
1458 /* set the next block position */
1459 pi->next_pos = pic2_tell_file(pi);
1460 pi->header->size = pi->next_pos;
1461 }
1462
pic2_write_header2(pi)1463 static void pic2_write_header2(pi)
1464 struct pic2_info *pi;
1465 {
1466 pic2_seek_file(pi, pi->next_pos, SEEK_SET);
1467
1468 /* write terminate block */
1469 pic2_write_long(pi, 0);
1470 pic2_write_long(pi, 0);
1471
1472 /* set some header information */
1473 if (pi->header->x_max < pi->x_max)
1474 pi->header->x_max = pi->x_max;
1475 if (pi->header->y_max < pi->x_max)
1476 pi->header->y_max = pi->y_max;
1477
1478 pi->header->time = time(NULL);
1479 pic2_seek_file(pi, 0, SEEK_SET);
1480
1481 /* write header image */
1482 pic2_write_file(pi, pi->header->magic, 4);
1483 pic2_write_file(pi, pi->header->name, 18);
1484 pic2_write_file(pi, pi->header->subtitle, 8);
1485 pic2_write_file(pi, pi->header->crlf0, 2);
1486 pic2_write_file(pi, pi->header->title, 30);
1487 pic2_write_file(pi, pi->header->crlf1, 2);
1488 pic2_write_file(pi, pi->header->saver, 30);
1489 pic2_write_file(pi, pi->header->crlf2, 2);
1490 pic2_write_file(pi, pi->header->eof, 1);
1491 pic2_write_file(pi, pi->header->reserve0, 1);
1492 pic2_write_short(pi, pi->header->flag);
1493 pic2_write_short(pi, pi->header->no);
1494 pic2_write_long(pi, pi->header->time);
1495 pic2_write_long(pi, pi->header->size);
1496 pic2_write_short(pi, pi->header->depth);
1497 pic2_write_short(pi, pi->header->x_aspect);
1498 pic2_write_short(pi, pi->header->y_aspect);
1499 pic2_write_short(pi, pi->header->x_max);
1500 pic2_write_short(pi, pi->header->y_max);
1501 pic2_write_long(pi, pi->header->reserve1);
1502 }
1503
pic2_write_block_header(pi)1504 static void pic2_write_block_header(pi)
1505 struct pic2_info *pi;
1506 {
1507 pic2_write_file(pi, pi->block->id, 4);
1508 pic2_write_long(pi, pi->block->size);
1509 pic2_write_short(pi, pi->block->flag);
1510 pic2_write_short(pi, pi->block->x_wid);
1511 pic2_write_short(pi, pi->block->y_wid);
1512 pic2_write_short(pi, pi->block->x_offset);
1513 pic2_write_short(pi, pi->block->y_offset);
1514 pic2_write_long(pi, pi->block->opaque);
1515 pic2_write_long(pi, pi->block->reserve);
1516 }
1517
1518 /*
1519 * These functions implement the arithmetic-format compressor.
1520 */
1521 #define pic2_arith_write_one_bit(pi) (pi->bs.bits++)
1522
pic2_arith_write_zero_bit(pi)1523 static void pic2_arith_write_zero_bit(pi)
1524 struct pic2_info *pi;
1525 {
1526 if (pi->bs.zero)
1527 pic2_write_bits(pi, 0, 1);
1528
1529 while (pi->bs.bits--)
1530 pic2_write_bits(pi, 1, 1);
1531
1532 pi->bs.bits = 0;
1533 pi->bs.zero = 1;
1534 }
1535
pic2_arith_flush_bit_buf(pi)1536 static void pic2_arith_flush_bit_buf(pi)
1537 struct pic2_info *pi;
1538 {
1539 int i;
1540
1541 for (i = 0; i < 16; i++) {
1542 if (pi->cc & 0x8000)
1543 pic2_arith_write_one_bit(pi);
1544 else
1545 pic2_arith_write_zero_bit(pi);
1546 pi->cc <<= 1;
1547 }
1548 pic2_arith_write_zero_bit(pi);
1549 pic2_flush_bits(pi);
1550 }
1551
pic2_arith_carry_bit(pi)1552 static void pic2_arith_carry_bit(pi)
1553 struct pic2_info *pi;
1554 {
1555 pic2_write_bits(pi, 1, 1);
1556
1557 if (pi->bs.bits == 0) {
1558 pi->bs.zero = 0;
1559 } else {
1560 while (--pi->bs.bits)
1561 pic2_write_bits(pi, 0, 1);
1562 pi->bs.zero = 1;
1563 }
1564 }
1565
pic2_arith_encode_bit(pi,n,c)1566 static void pic2_arith_encode_bit(pi, n, c)
1567 struct pic2_info *pi;
1568 int n, c;
1569 {
1570 int pp;
1571 long *c_sum, *c_0_sum;
1572
1573 c_sum = (long *) pi->mulu_tab;
1574 c_0_sum = c_sum + PIC2_ARITH_CONTEXT + 1;
1575
1576 if (pi->dd == 0) {
1577 c_sum[c]++;
1578 if (n == 0)
1579 c_0_sum[c]++;
1580 return;
1581 }
1582 pp = pi->mulu_tab[(pi->aa & 0x7f00) / 2 + c];
1583 if (n != 0) {
1584 pi->cc = pi->cc + pp;
1585 if (pi->cc > 0xffff) {
1586 pic2_arith_carry_bit(pi);
1587 pi->cc = pi->cc & 0xffff;
1588 }
1589 pi->aa = pi->aa - pp;
1590 while (pi->aa < 0x8000) {
1591 if (pi->cc & 0x8000)
1592 pic2_arith_write_one_bit(pi);
1593 else
1594 pic2_arith_write_zero_bit(pi);
1595 pi->cc = (pi->cc * 2) & 0xffff;
1596 pi->aa = pi->aa * 2;
1597 }
1598 } else {
1599 pi->aa = pp;
1600
1601 while (pi->aa < 0x8000) {
1602 if (pi->cc & 0x8000)
1603 pic2_arith_write_one_bit(pi);
1604 else
1605 pic2_arith_write_zero_bit(pi);
1606 pi->cc = (pi->cc * 2) & 0xffff;
1607 pi->aa = pi->aa * 2;
1608 }
1609 }
1610 }
1611
pic2_arith_encode_nbyte(pi,n,c,max)1612 static void pic2_arith_encode_nbyte(pi, n, c, max)
1613 struct pic2_info *pi;
1614 int n, c, max;
1615 {
1616 short i;
1617
1618 for (i = 0; i < n; i++) {
1619 pic2_arith_encode_bit(pi, 0, c + i);
1620 }
1621 if (n < max)
1622 pic2_arith_encode_bit(pi, 1, c + n);
1623 }
1624
pic2_arith_encode_nn(pi,n,c)1625 static void pic2_arith_encode_nn(pi, n, c)
1626 struct pic2_info *pi;
1627 int n, c;
1628 {
1629 if (n < 1) {
1630 pic2_arith_encode_bit(pi, 1, c);
1631 } else if (n < 1 + 2) {
1632 pic2_arith_encode_bit(pi, 0, c);
1633 pic2_arith_encode_bit(pi, 1, c + 1);
1634 n -= 1;
1635 pic2_arith_encode_bit(pi, n & 1, c + 8);
1636 } else if (n < 1 + 2 + 4) {
1637 pic2_arith_encode_bit(pi, 0, c);
1638 pic2_arith_encode_bit(pi, 0, c + 1);
1639 pic2_arith_encode_bit(pi, 1, c + 2);
1640 n -= 1 + 2;
1641 pic2_arith_encode_bit(pi, n & 1, c + 8);
1642 pic2_arith_encode_bit(pi, n & 2, c + 9);
1643 } else if (n < 1 + 2 + 4 + 8) {
1644 pic2_arith_encode_bit(pi, 0, c);
1645 pic2_arith_encode_bit(pi, 0, c + 1);
1646 pic2_arith_encode_bit(pi, 0, c + 2);
1647 pic2_arith_encode_bit(pi, 1, c + 3);
1648 n -= 1 + 2 + 4;
1649 pic2_arith_encode_bit(pi, n & 1, c + 8);
1650 pic2_arith_encode_bit(pi, n & 2, c + 9);
1651 pic2_arith_encode_bit(pi, n & 4, c + 10);
1652 } else if (n < 1 + 2 + 4 + 8 + 16) {
1653 pic2_arith_encode_bit(pi, 0, c);
1654 pic2_arith_encode_bit(pi, 0, c + 1);
1655 pic2_arith_encode_bit(pi, 0, c + 2);
1656 pic2_arith_encode_bit(pi, 0, c + 3);
1657 pic2_arith_encode_bit(pi, 1, c + 4);
1658 n -= 1 + 2 + 4 + 8;
1659 pic2_arith_encode_bit(pi, n & 1, c + 8);
1660 pic2_arith_encode_bit(pi, n & 2, c + 9);
1661 pic2_arith_encode_bit(pi, n & 4, c + 10);
1662 pic2_arith_encode_bit(pi, n & 8, c + 11);
1663 } else if (n < 1 + 2 + 4 + 8 + 16 + 32) {
1664 pic2_arith_encode_bit(pi, 0, c);
1665 pic2_arith_encode_bit(pi, 0, c + 1);
1666 pic2_arith_encode_bit(pi, 0, c + 2);
1667 pic2_arith_encode_bit(pi, 0, c + 3);
1668 pic2_arith_encode_bit(pi, 0, c + 4);
1669 pic2_arith_encode_bit(pi, 1, c + 5);
1670 n -= 1 + 2 + 4 + 8 + 16;
1671 pic2_arith_encode_bit(pi, n & 1, c + 8);
1672 pic2_arith_encode_bit(pi, n & 2, c + 9);
1673 pic2_arith_encode_bit(pi, n & 4, c + 10);
1674 pic2_arith_encode_bit(pi, n & 8, c + 11);
1675 pic2_arith_encode_bit(pi, n & 16, c + 12);
1676 } else if (n < 1 + 2 + 4 + 8 + 16 + 32 + 64) {
1677 pic2_arith_encode_bit(pi, 0, c);
1678 pic2_arith_encode_bit(pi, 0, c + 1);
1679 pic2_arith_encode_bit(pi, 0, c + 2);
1680 pic2_arith_encode_bit(pi, 0, c + 3);
1681 pic2_arith_encode_bit(pi, 0, c + 4);
1682 pic2_arith_encode_bit(pi, 0, c + 5);
1683 pic2_arith_encode_bit(pi, 1, c + 6);
1684 n -= 1 + 2 + 4 + 8 + 16 + 32;
1685 pic2_arith_encode_bit(pi, n & 1, c + 8);
1686 pic2_arith_encode_bit(pi, n & 2, c + 9);
1687 pic2_arith_encode_bit(pi, n & 4, c + 10);
1688 pic2_arith_encode_bit(pi, n & 8, c + 11);
1689 pic2_arith_encode_bit(pi, n & 16, c + 12);
1690 pic2_arith_encode_bit(pi, n & 32, c + 13);
1691 } else if (n < 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128) {
1692 pic2_arith_encode_bit(pi, 0, c);
1693 pic2_arith_encode_bit(pi, 0, c + 1);
1694 pic2_arith_encode_bit(pi, 0, c + 2);
1695 pic2_arith_encode_bit(pi, 0, c + 3);
1696 pic2_arith_encode_bit(pi, 0, c + 4);
1697 pic2_arith_encode_bit(pi, 0, c + 5);
1698 pic2_arith_encode_bit(pi, 0, c + 6);
1699 pic2_arith_encode_bit(pi, 1, c + 7);
1700 n -= 1 + 2 + 4 + 8 + 16 + 32 + 64;
1701 pic2_arith_encode_bit(pi, n & 1, c + 8);
1702 pic2_arith_encode_bit(pi, n & 2, c + 9);
1703 pic2_arith_encode_bit(pi, n & 4, c + 10);
1704 pic2_arith_encode_bit(pi, n & 8, c + 11);
1705 pic2_arith_encode_bit(pi, n & 16, c + 12);
1706 pic2_arith_encode_bit(pi, n & 32, c + 13);
1707 pic2_arith_encode_bit(pi, n & 64, c + 14);
1708 } else {
1709 pic2_arith_encode_bit(pi, 0, c);
1710 pic2_arith_encode_bit(pi, 0, c + 1);
1711 pic2_arith_encode_bit(pi, 0, c + 2);
1712 pic2_arith_encode_bit(pi, 0, c + 3);
1713 pic2_arith_encode_bit(pi, 0, c + 4);
1714 pic2_arith_encode_bit(pi, 0, c + 5);
1715 pic2_arith_encode_bit(pi, 0, c + 6);
1716 pic2_arith_encode_bit(pi, 0, c + 7);
1717 }
1718 }
1719
pic2_arith_press_chain(pi,x)1720 static void pic2_arith_press_chain(pi, x)
1721 struct pic2_info *pi;
1722 int x;
1723 {
1724 int b, d;
1725 pixel c;
1726
1727 b = -(pi->flag_now[x]);
1728 c = pi->vram_now[x];
1729 d = 0;
1730
1731 if (b < 0)
1732 b = 0;
1733
1734 if (pi->flag_next[x] == 1 && pi->vram_next[x] == c) {
1735 d = 1;
1736 pi->flag_next[x] = -1;
1737 } else if (pi->flag_next[x - 1] == 1 && pi->vram_next[x - 1] == c) {
1738 d = 2;
1739 pi->flag_next[x - 1] = -2;
1740 } else if (pi->flag_next[x + 1] == 1 && pi->vram_next[x + 1] == c) {
1741 d = 3;
1742 pi->flag_next[x + 1] = -3;
1743 } else if (pi->flag_next[x - 2] == 1 && pi->vram_next[x - 2] == c) {
1744 d = 4;
1745 pi->flag_next[x - 2] = -4;
1746 } else if (pi->flag_next[x + 2] == 1 && pi->vram_next[x + 2] == c) {
1747 if ((pi->flag_now[x + 2] != 0 && pi->vram_now[x + 2] == c)
1748 || (pi->flag_now[x + 1] != 0 && pi->vram_now[x + 1] == c)
1749 || (pi->flag_now[x + 3] != 0 && pi->vram_now[x + 3] == c)) {
1750 pic2_arith_encode_nbyte(pi, 0, 80 + 6 * b, 5);
1751 return;
1752 }
1753 d = 5;
1754 pi->flag_next[x + 2] = -5;
1755 }
1756 pic2_arith_encode_nbyte(pi, d, 80 + 6 * b, 5);
1757 }
1758
pic2_arith_put_number(pi,xn,xa,xb)1759 static void pic2_arith_put_number(pi, xn, xa, xb)
1760 struct pic2_info *pi;
1761 int xn, xa, xb;
1762 {
1763 short n;
1764 byte maxcol;
1765
1766 maxcol = 0xff >> (8 - pi->header->depth / 3);
1767
1768 if (xa > ((int) maxcol >> 1)) {
1769 if (xb > xa)
1770 n = (xb - xa) * 2 - 1;
1771 else if (xa - ((int) maxcol - xa) > xb)
1772 n = maxcol - xb;
1773 else
1774 n = (xa - xb) * 2;
1775 } else {
1776 if (xb <= xa)
1777 n = (xa - xb) * 2;
1778 else if (2 * xa < xb)
1779 n = xb;
1780 else
1781 n = (xb - xa) * 2 - 1;
1782 }
1783 pic2_arith_encode_nn(pi, n, xn);
1784 }
1785
pic2_arith_write_color(pi,x)1786 static void pic2_arith_write_color(pi, x)
1787 struct pic2_info *pi;
1788 int x;
1789 {
1790 pixel c1, c2, cc;
1791 short g0, r0, b0, r, g, b;
1792 int i, j;
1793 unsigned short k;
1794 pixel *p, *pp;
1795 short colbits;
1796 pixel rmask, gmask, bmask;
1797 byte maxcol;
1798
1799 colbits = pi->header->depth / 3;
1800 rmask = (0xff >> (8 - colbits)) << (colbits * 2);
1801 gmask = (0xff >> (8 - colbits)) << colbits;
1802 bmask = (0xff >> (8 - colbits));
1803 maxcol = (byte) bmask;
1804
1805 cc = pi->vram_now[x];
1806 c1 = pi->vram_prev[x];
1807 k = ((c1 >> ((colbits - 3) * 3)) & 0x1c0)
1808 | ((c1 >> ((colbits - 3) * 2)) & 0x038)
1809 | ((c1 >> (colbits - 3) ) & 0x007);
1810 if (colbits == 5)
1811 k = pic2_exchange_rg(k, 3);
1812
1813 p = pi->cache[k];
1814 for (i = 0; i < (PIC2_ARITH_CACHE - 1); i++) {
1815 if (cc == *p++)
1816 break;
1817 }
1818 if (i == (PIC2_ARITH_CACHE - 1)) {
1819 pp = p - 1;
1820 for (j = i; j > 0; j--) {
1821 *--p = *--pp;
1822 }
1823 pi->cache[k][0] = cc;
1824 pic2_arith_encode_bit(pi, 1, pi->cache_hit_c);
1825 pi->cache_hit_c = 16;
1826
1827 c2 = pi->vram_now[x - 1];
1828 r = ((c1 & rmask) + (c2 & rmask)) >> (colbits * 2 + 1);
1829 g = ((c1 & gmask) + (c2 & gmask)) >> (colbits + 1);
1830 b = ((c1 & bmask) + (c2 & bmask)) >> ( 1);
1831
1832 r0 = (cc >> (colbits * 2)) & maxcol;
1833 g0 = (cc >> colbits ) & maxcol;
1834 b0 = cc & maxcol;
1835
1836 r = r + g0 - g;
1837 if (r < 0)
1838 r = 0;
1839 else if (r > (short) maxcol)
1840 r = maxcol;
1841
1842 b = b + g0 - g;
1843 if (b < 0)
1844 b = 0;
1845 else if (b > (short) maxcol)
1846 b = maxcol;
1847
1848 pic2_arith_put_number(pi, 32, g, g0);
1849 pic2_arith_put_number(pi, 48, r, r0);
1850 pic2_arith_put_number(pi, 64, b, b0);
1851 } else {
1852 *--p = pi->cache[k][i / 2];
1853 pi->cache[k][i / 2] = pi->cache[k][0];
1854 pi->cache[k][0] = cc;
1855
1856 pic2_arith_encode_bit(pi, 0, pi->cache_hit_c);
1857 pi->cache_hit_c = 15;
1858 pic2_arith_encode_nn(pi, i, 17);
1859 }
1860 }
1861
pic2_arith_press_line2(pi)1862 static void pic2_arith_press_line2(pi)
1863 struct pic2_info *pi;
1864 {
1865 int x, xw, ymax;
1866 pixel cc;
1867
1868 xw = pi->block->x_wid;
1869 ymax = pi->block->y_wid -1;
1870 cc = pi->vram_now[xw - 1]; /* last color */
1871 pi->vram_next[-1] = cc;
1872
1873 /* mark change point */
1874 for (x = 0; x < xw; x++)
1875 if (cc != pi->vram_next[x]) {
1876 pi->flag_next[x] = 1;
1877 cc = pi->vram_next[x];
1878 } else
1879 pi->flag_next[x] = 0;
1880
1881 for (x = 0; x < xw; x++) {
1882 if (pi->flag_now[x] == 1) { /* change point */
1883 pi->flag2_now [x + 1]++;
1884 pi->flag2_now [x + 2]++;
1885 pi->flag2_next [x - 1]++;
1886 pi->flag2_next [x ]++;
1887 pi->flag2_next [x + 1]++;
1888 pi->flag2_next2[x - 1]++;
1889 pi->flag2_next2[x ]++;
1890 pi->flag2_next2[x + 1]++;
1891
1892 /* write change point */
1893 pic2_arith_encode_bit(pi, 1, pi->flag2_now[x]);
1894
1895 /* write color */
1896 pic2_arith_write_color(pi, x);
1897
1898 /* if not last line, write chain */
1899 if (pi->ynow - 1 < ymax)
1900 pic2_arith_press_chain(pi, x);
1901 } else if (pi->flag_now[x] == 0) /* not on chain */
1902 /* write change point */
1903 pic2_arith_encode_bit(pi, 0, pi->flag2_now[x]);
1904 else /* on chain */
1905 /* if not on last line, write next chain */
1906 if (pi->ynow - 1 < ymax)
1907 pic2_arith_press_chain(pi, x);
1908 }
1909 }
1910
pic2_arith_press_line(pi,line)1911 static int pic2_arith_press_line(pi, line)
1912 struct pic2_info *pi;
1913 pixel **line;
1914 {
1915 int i, xw, ymax;
1916 long *c_sum, *c_0_sum;
1917
1918 xw = pi->block->x_wid;
1919 ymax = pi->block->y_wid -1;
1920 c_sum = (long *) pi->mulu_tab;
1921 c_0_sum = c_sum + PIC2_ARITH_CONTEXT +1;
1922
1923 pic2_handle_para(pi, 0);
1924
1925 xvbzero((char *) pi->flag2_next2 - 4,
1926 (8 + xw) * sizeof(pi->flag2_next2[0]));
1927
1928 if (pi->ynow == 0) { /* first line */
1929 int x;
1930 pixel cc = 0;
1931
1932 if (pi->dd != 0) { /* compress pass */
1933 unsigned short c_tab[PIC2_ARITH_CONTEXT];
1934
1935 for (i = 0; i < PIC2_ARITH_CONTEXT; i++) {
1936 unsigned long a, b;
1937 a = c_0_sum[i];
1938 b = c_sum[i];
1939 while (a > 32767) {
1940 a /= 2;
1941 b /= 2;
1942 }
1943 if (a == b)
1944 c_tab[i] = 0xffff; /* b==0 here, too */
1945 else
1946 c_tab[i] = (65536 * a) / b; /* a < b, so less 65536 */
1947 }
1948 for (i = 0; i < 16384; i++) {
1949 pi->mulu_tab[i] = (long) (i / 128 + 128) * (int) c_tab[i & 127] / 256;
1950 if (pi->mulu_tab[i] == 0)
1951 pi->mulu_tab[i] = 1; /* 0 is wrong */
1952 }
1953 for (i = 0; i < PIC2_ARITH_CONTEXT; i++)
1954 pic2_write_short(pi, c_tab[i]);
1955
1956 xvbzero((char *) pi->vram_now, xw * sizeof(pi->vram_now[0]));
1957 } else { /* statistical pass */
1958 xvbzero((char *) c_0_sum, PIC2_ARITH_CONTEXT * sizeof(c_0_sum[0]));
1959 xvbzero((char *) c_sum, PIC2_ARITH_CONTEXT * sizeof(c_sum[0]));
1960 }
1961
1962 /* initialize flags */
1963 xvbzero((char *) pi->cache, 8 * 8 * 8 * sizeof(pi->cache[0]));
1964 xvbzero((char *) pi->cache_pos, 8 * 8 * 8 * sizeof(pi->cache_pos[0]));
1965
1966 xvbzero((char *) pi->flag2_next - 4,
1967 (8 + xw) * sizeof(pi->flag2_next[0]));
1968 xvbzero((char *) pi->flag2_next2 - 4,
1969 (8 + xw) * sizeof(pi->flag2_next2[0]));
1970
1971 pi->vram_next[-1] = cc;
1972 for (x = 0; x < xw; x++)
1973 if (cc != pi->vram_next[x]) {
1974 pi->flag_next[x] = 1;
1975 cc = pi->vram_next[x];
1976 } else
1977 pi->flag_next[x] = 0;
1978
1979 pi->aa = 0xffff;
1980 cc = 0;
1981 pi->cache_hit_c = 16;
1982 } else /* after second line */
1983 pic2_arith_press_line2(pi);
1984
1985 if (pi->ynow == ymax) {
1986 pi->ynow++;
1987 pic2_handle_para(pi, 1);
1988 pic2_handle_para(pi, 0);
1989 pic2_arith_press_line2(pi);
1990 }
1991 /* line buffer for next data */
1992 if (line != NULL)
1993 *line = pi->vram_prev;
1994
1995 pi->ynow++;
1996
1997 if (pi->ynow - 1 < ymax) {
1998 pic2_handle_para(pi, 1);
1999 return (pi->ynow);
2000 } else { /* end */
2001 if (pi->dd == 0) { /* statistical pass */
2002 pi->dd = 1;
2003 pi->ynow = 0;
2004 pic2_handle_para(pi, 1);
2005 return (0);
2006 } else {
2007 pic2_handle_para(pi, 1);
2008 pic2_arith_flush_bit_buf(pi);
2009 return (-2); /* end */
2010 }
2011 }
2012 }
2013
pic2_arith_saver_init(pi,line)2014 static int pic2_arith_saver_init(pi, line)
2015 struct pic2_info *pi;
2016 pixel **line;
2017 {
2018 pi->ynow = 0;
2019
2020 /* check the color depth */
2021 if (pi->header->depth % 3)
2022 pic2_error(pi, PIC2_DEPTH);
2023
2024 /* set next line function */
2025 pi->next_line = pic2_arith_press_line;
2026
2027 if (line != NULL)
2028 *line = pi->vram_next + 4;
2029
2030 pic2_seek_file(pi, pi->next_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
2031
2032 /* clear bit field marker */
2033 pi->bs.rest = 0;
2034 pi->bs.cur = 0;
2035 pi->bs.zero = 0;
2036 pi->bs.bits = 0;
2037
2038 return (0);
2039 }
2040
2041 /*
2042 * These functions are fast pic2 format compressor.
2043 */
pic2_fast_write_length(pi,n)2044 static void pic2_fast_write_length(pi, n)
2045 struct pic2_info *pi;
2046 int n;
2047 {
2048 int a, b;
2049 static const unsigned short len_data[8][2] = {
2050 {1, 0},
2051 {1, 0},
2052 {3, 4},
2053 {3, 5},
2054 {5, 24},
2055 {5, 25},
2056 {5, 26},
2057 {5, 27},
2058 };
2059
2060 n++;
2061 if (n < 8)
2062 pic2_write_bits(pi, len_data[n][1], len_data[n][0]);
2063 else {
2064 a = 0;
2065 b = 2;
2066 while (n > b - 1) {
2067 a = a + 1;
2068 b = b * 2;
2069 }
2070 pic2_write_bits(pi, 0xfffffffe, a + 1);
2071 if (a > 0)
2072 pic2_write_bits(pi, n - b / 2, a);
2073 }
2074 }
2075
pic2_fast_press_chain(pi,x)2076 static void pic2_fast_press_chain(pi, x)
2077 struct pic2_info *pi;
2078 int x;
2079 {
2080 int ymax;
2081 pixel cc;
2082
2083 ymax = pi->block->y_wid -1;
2084 cc = pi->vram_now[x];
2085
2086 if (pi->ynow - 1 == ymax) {
2087 pic2_write_bits(pi, 0, 1);
2088 return;
2089 }
2090 if (pi->flag_next[x] == 1 && pi->vram_next[x] == cc) {
2091 pi->flag_next[x] = -1;
2092 pic2_write_bits(pi, 3, 2);
2093 } else if (pi->flag_next[x - 1] == 1 && pi->vram_next[x - 1] == cc) {
2094 pi->flag_next[x - 1] = -1;
2095 pic2_write_bits(pi, 11, 4);
2096 } else if (pi->flag_next[x + 1] == 1 && pi->vram_next[x + 1] == cc) {
2097 pi->flag_next[x + 1] = -1;
2098 pic2_write_bits(pi, 9, 4);
2099 } else if (pi->flag_next[x - 2] == 1 && pi->vram_next[x - 2] == cc) {
2100 pi->flag_next[x - 2] = -1;
2101 pic2_write_bits(pi, 10, 4);
2102 } else if ((pi->flag_next[x + 2] == 1 && pi->vram_next[x + 2] == cc)
2103 && !(pi->flag_now[x + 2] != 0 && pi->vram_now[x + 2] == cc)) {
2104 pi->flag_next[x + 2] = -1;
2105 pic2_write_bits(pi, 8, 4);
2106 } else
2107 pic2_write_bits(pi, 0, 1);
2108 }
2109
pic2_fast_press_chain2(pi,x)2110 static void pic2_fast_press_chain2(pi, x)
2111 struct pic2_info *pi;
2112 int x;
2113 {
2114 int ymax;
2115 pixel cc;
2116 char *chain_buff;
2117
2118 ymax = pi->block->y_wid -1;
2119 chain_buff = (char *) pi->mulu_tab;
2120 cc = pi->vram_now[x];
2121
2122 if (pi->ynow - 1 == ymax) {
2123 chain_buff[pi->cc++] = 0;
2124 return;
2125 }
2126 if (pi->flag_next[x] == 1 && pi->vram_next[x] == cc) {
2127 pi->flag_next[x] = -1;
2128 chain_buff[pi->cc++] = 1;
2129 } else if (pi->flag_next[x - 1] == 1 && pi->vram_next[x - 1] == cc) {
2130 pi->flag_next[x - 1] = -1;
2131 chain_buff[pi->cc++] = 2;
2132 } else if (pi->flag_next[x + 1] == 1 && pi->vram_next[x + 1] == cc) {
2133 pi->flag_next[x + 1] = -1;
2134 chain_buff[pi->cc++] = 3;
2135 } else if (pi->flag_next[x - 2] == 1 && pi->vram_next[x - 2] == cc) {
2136 pi->flag_next[x - 2] = -1;
2137 chain_buff[pi->cc++] = 4;
2138 } else if ((pi->flag_next[x + 2] == 1 && pi->vram_next[x + 2] == cc)
2139 && !(pi->flag_now[x + 2] != 0 && pi->vram_now[x + 2] == cc)) {
2140 pi->flag_next[x + 2] = -1;
2141 chain_buff[pi->cc++] = 5;
2142 } else
2143 chain_buff[pi->cc++] = 0;
2144 }
2145
pic2_fast_flush_chain(pi)2146 static void pic2_fast_flush_chain(pi)
2147 struct pic2_info *pi;
2148 {
2149 int i;
2150 char *chain_buf;
2151
2152 chain_buf = (char *) pi->mulu_tab;
2153 for (i = 0; i < pi->cc; i++){
2154 switch (chain_buf[i]) {
2155 case 0:
2156 pic2_write_bits(pi, 0, 1);
2157 break;
2158 case 1:
2159 pic2_write_bits(pi, 3, 2);
2160 break;
2161 case 2:
2162 pic2_write_bits(pi, 11, 4);
2163 break;
2164 case 3:
2165 pic2_write_bits(pi, 9, 4);
2166 break;
2167 case 4:
2168 pic2_write_bits(pi, 10, 4);
2169 break;
2170 case 5:
2171 pic2_write_bits(pi, 8, 4);
2172 break;
2173 }
2174 }
2175 pi->cc = 0;
2176 }
2177
pic2_fast_write_color(pi,x)2178 static void pic2_fast_write_color(pi, x)
2179 struct pic2_info *pi;
2180 int x;
2181 {
2182 pixel cc, bc;
2183 unsigned short j, k, m;
2184 short depth, colbits;
2185 pixel (*cache)[PIC2_FAST_CACHE];
2186
2187 depth = pi->header->depth;
2188 colbits = depth / 3;
2189 cache = (pixel (*)[PIC2_FAST_CACHE]) pi->cache;
2190
2191 bc = pi->vram_now[x - 1];
2192 bc = pic2_exchange_rg(bc, colbits);
2193 k = pic2_shift_bits(bc, 8 - depth);
2194 cc = pi->vram_now[x];
2195 m = pi->cache_pos[k];
2196
2197 for (j = 0; j < PIC2_FAST_CACHE; j++)
2198 if (cache[k][(m + j) & (PIC2_FAST_CACHE - 1)] == cc)
2199 break;
2200
2201 if (j == PIC2_FAST_CACHE) {
2202 m = (m - 1) & (PIC2_FAST_CACHE - 1);
2203 pi->cache_pos[k] = m;
2204 cache[k][m] = cc;
2205
2206 cc = pic2_exchange_rg(cc, colbits);
2207 pic2_write_bits(pi, 0, 1);
2208 pic2_write_bits(pi, cc, depth);
2209 } else {
2210 pic2_write_bits(pi, 1, 1);
2211 pic2_write_bits(pi, j, 6);
2212 }
2213 }
2214
pic2_fast_press_line2(pi)2215 static void pic2_fast_press_line2(pi)
2216 struct pic2_info *pi;
2217 {
2218 int x, xw;
2219 pixel cc;
2220
2221 xw = pi->block->x_wid;
2222 cc = pi->vram_now[xw - 1]; /* last color */
2223 pi->vram_next[-1] = cc;
2224
2225 /* mark change point */
2226 for (x = 0; x < xw; x++)
2227 if (cc != pi->vram_next[x]) {
2228 pi->flag_next[x] = 1;
2229 cc = pi->vram_next[x];
2230 } else
2231 pi->flag_next[x] = 0;
2232
2233 for (x = 0; x < xw; x++)
2234 if (pi->flag_now[x] == 1) { /* change point */
2235 if (pi->aa >= 1023)
2236 pi->aa++;
2237 pic2_fast_write_length(pi, pi->aa);
2238 pic2_fast_flush_chain(pi);
2239 pi->aa = 0;
2240 pic2_fast_write_color(pi, x);
2241 pic2_fast_press_chain(pi, x);
2242 } else if (pi->flag_now[x] == 0) {
2243 pi->aa++;
2244 } else {
2245 pic2_fast_press_chain2(pi, x);
2246 if (pi->cc == 1023) {
2247 pic2_fast_write_length(pi, 1023);
2248 pic2_fast_flush_chain(pi);
2249 pi->aa = 0;
2250 }
2251 }
2252 }
2253
pic2_fast_press_line(pi,line)2254 static int pic2_fast_press_line(pi, line)
2255 struct pic2_info *pi;
2256 pixel **line;
2257 {
2258 int xw, ymax;
2259
2260 xw = pi->block->x_wid;
2261 ymax = pi->block->y_wid -1;
2262
2263 pic2_handle_para(pi, 0);
2264
2265 if (pi->ynow == 0) { /* first line */
2266 int x;
2267 pixel cc = 0;
2268
2269 /* initialize flags */
2270 xvbzero((char *) pi->cache, 256 * sizeof(pi->cache[0]));
2271 xvbzero((char *) pi->cache_pos,
2272 PIC2_FAST_CACHE * sizeof(pi->cache_pos[0]));
2273
2274 /* mark change point */
2275 pi->vram_next[-1] = cc;
2276 for (x = 0; x < xw; x++)
2277 if (cc != pi->vram_next[x]) {
2278 pi->flag_next[x] = 1;
2279 cc = pi->vram_next[x];
2280 } else
2281 pi->flag_next[x] = 0;
2282
2283 pi->cc = 0;
2284 pi->aa = 0;
2285 } else /* after second line */
2286 pic2_fast_press_line2(pi);
2287
2288 if (pi->ynow == ymax) {
2289 pi->ynow++;
2290 pic2_handle_para(pi, 1);
2291 pic2_handle_para(pi, 0);
2292 pic2_fast_press_line2(pi);
2293 }
2294 /* line buffer for next data */
2295 if (line != NULL)
2296 *line = pi->vram_prev;
2297
2298 pi->ynow++;
2299
2300 if (pi->ynow - 1 < ymax) {
2301 pic2_handle_para(pi, 1);
2302 return (pi->ynow);
2303 } else { /* end */
2304 pic2_handle_para(pi, 1);
2305 if (pi->aa >= 1023)
2306 pi->aa++;
2307 pic2_fast_write_length(pi, pi->aa);
2308 pic2_fast_flush_chain(pi);
2309 return (-2); /* end */
2310 }
2311 }
2312
pic2_fast_saver_init(pi,line)2313 static int pic2_fast_saver_init(pi, line)
2314 struct pic2_info *pi;
2315 pixel **line;
2316 {
2317 pi->ynow = 0;
2318
2319 /* check the color depth */
2320 if (pi->header->depth % 3)
2321 pic2_error(pi, PIC2_DEPTH);
2322
2323 /* set next line function */
2324 pi->next_line = pic2_fast_press_line;
2325 if (line != NULL)
2326 *line = pi->vram_next + 4;
2327
2328 pic2_seek_file(pi, pi->next_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
2329
2330 /* clear bit field marker */
2331 pi->bs.rest = 0;
2332 pi->bs.cur = 0;
2333
2334 return (0);
2335 }
2336
2337 /*
2338 * These functions are beta pic2 format compressor.
2339 */
pic2_beta_press_line(pi,line)2340 static int pic2_beta_press_line(pi, line)
2341 struct pic2_info *pi;
2342 pixel **line;
2343 {
2344 int i, xw, ymax;
2345 byte *p;
2346 pixel *pc;
2347 short depth, pixbyte, colbits;
2348
2349 depth = pi->header->depth;
2350 pixbyte = depth / 8 + ((depth % 8) > 0);
2351 colbits = depth / 3;
2352
2353 xw = pi->block->x_wid;
2354 ymax = pi->block->y_wid - 1;
2355
2356 pc = pi->vram_now;
2357 p = (byte *) pi->vram_prev;
2358 if (pixbyte == 3) {
2359 for (i = 0; i < xw; i++, pc++) {
2360 *p++ = *pc >> 16;
2361 *p++ = *pc >> 8;
2362 *p++ = *pc;
2363 }
2364 pic2_write_file(pi, pi->vram_prev, (size_t) (xw * 3));
2365 } else if (pixbyte == 2) {
2366 if (strncmp(pi->block->id, "P2BM", 4) == 0)
2367 for (i = 0; i < xw; i++, pc++) {
2368 if (colbits == 5) {
2369 *pc = pic2_exchange_rg(*pc, colbits);
2370 *pc <<= 1;
2371 }
2372 *p++ = *pc >> 8;
2373 *p++ = *pc;
2374 }
2375 else
2376 for (i = 0; i < xw; i++, pc++) {
2377 if (colbits == 5) {
2378 *pc = pic2_exchange_rg(*pc, colbits);
2379 *pc <<= 1;
2380 }
2381 *p++ = *pc;
2382 *p++ = *pc >> 8;
2383 }
2384 pic2_write_file(pi, pi->vram_prev, (size_t) (xw * 2));
2385 } else {
2386 for (i = 0; i < xw; i++, pc++)
2387 *p++ = *pc;
2388 pic2_write_file(pi, pi->vram_prev, (size_t) xw);
2389 }
2390 if (line != NULL)
2391 *line = pi->vram_now;
2392
2393 pi->ynow++;
2394 if (pi->ynow > ymax)
2395 return (-2);
2396 return (pi->ynow);
2397 }
2398
pic2_beta_saver_init(pi,line)2399 static int pic2_beta_saver_init(pi, line)
2400 struct pic2_info *pi;
2401 pixel **line;
2402 {
2403 pi->ynow = 0;
2404
2405 *line = pi->vram_now;
2406 pi->next_line = pic2_beta_press_line;
2407 pic2_seek_file(pi, pi->next_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
2408 return (0);
2409 }
2410
2411 /*
2412 * This function saves compressed data.
2413 */
pic2_write_data(pi,data,ptype,x_offset,y_offset,w,h,rmap,gmap,bmap,type,depth)2414 static void pic2_write_data(pi, data, ptype, x_offset, y_offset, w, h,
2415 rmap, gmap, bmap, type, depth)
2416 struct pic2_info *pi;
2417 byte *data;
2418 int ptype;
2419 int x_offset, y_offset;
2420 int w, h;
2421 byte *rmap, *gmap, *bmap;
2422 int type, depth;
2423 {
2424 int i, line;
2425 pixel *linep;
2426 short colbits;
2427
2428 colbits = pi->header->depth / 3;
2429
2430 line = pic2_save_block(pi, &linep, x_offset, y_offset, w, h,
2431 form_tab[type].id, 0xffffffff);
2432 while (line >= 0) {
2433 byte r, g, b;
2434 int pic_idx;
2435
2436 pic_idx = line * w * ((ptype == PIC24) ? 3 : 1);
2437
2438 for (i = 0; i < w; i++) {
2439 if (ptype != PIC24) {
2440 r = rmap[data[pic_idx]];
2441 g = gmap[data[pic_idx]];
2442 b = bmap[data[pic_idx]];
2443 pic_idx++;
2444 } else {
2445 r = data[pic_idx++];
2446 g = data[pic_idx++];
2447 b = data[pic_idx++];
2448 }
2449 if (pi->writing_grey)
2450 r = g = b = MONO(r, g, b);
2451
2452 r = pic2_convert_color_bits(r, 8, colbits);
2453 g = pic2_convert_color_bits(g, 8, colbits);
2454 b = pic2_convert_color_bits(b, 8, colbits);
2455
2456 linep[i] = ((pixel) r << (colbits * 2))
2457 | ((pixel) g << colbits )
2458 | ((pixel) b );
2459 }
2460 line = pic2_next_line(pi, &linep);
2461 WaitCursor();
2462 }
2463 }
2464
2465 /*
2466 * This function compresses/extracts one line buffer.
2467 */
pic2_next_line(pi,line)2468 static int pic2_next_line(pi, line)
2469 struct pic2_info *pi;
2470 pixel **line;
2471 {
2472 int res;
2473
2474 res = pi->next_line(pi, line);
2475 if (res == -2) {
2476 if (pi->mode == PIC2_WRITE_MODE) {
2477 long new_pos;
2478
2479 new_pos = pic2_tell_file(pi);
2480 pi->block->size = new_pos - pi->next_pos;
2481 pic2_seek_file(pi, pi->next_pos, SEEK_SET);
2482 pic2_write_block_header(pi);
2483 pi->next_pos = new_pos;
2484 if (DEBUG)
2485 pic2_show_pic2_info(pi);
2486 }
2487 pic2_free_buffer(pi);
2488 }
2489 return (res);
2490 }
2491
2492 /*
2493 * These functions find the pic2 image block.
2494 * pic2_next_block:
2495 * moves the file pointer to the next image block.
2496 * pic2_find_block:
2497 * finds the first image block and moves the file pointer there.
2498 */
pic2_next_block(pi)2499 static int pic2_next_block(pi)
2500 struct pic2_info *pi;
2501 {
2502 int i;
2503
2504 if (pi->mode != PIC2_READ_MODE)
2505 return (-1);
2506
2507 /* go to block for read */
2508 pic2_seek_file(pi, pi->next_pos, SEEK_SET);
2509
2510 /* read the head of block header */
2511 pic2_read_block_header1(pi);
2512
2513 /* end block ? */
2514 if (pi->block->id[0] == 0)
2515 return (0);
2516
2517 /* set current block */
2518 pi->block_pos = pi->next_pos;
2519
2520 /* set next block */
2521 pi->next_pos += pi->block->size;
2522
2523 /* check block id */
2524 for (i = 0; i < n_form_tab; i++) {
2525 if (xvbcmp(pi->block->id, form_tab[i].id, (size_t) 4) == 0)
2526 break;
2527 }
2528 if (i == n_form_tab)
2529 return (2);
2530
2531 /* read the rest of block header */
2532 pic2_read_block_header2(pi);
2533
2534 if (pi->block->x_offset + pi->block->x_wid > pi->x_max)
2535 pi->x_max = pi->block->x_offset + pi->block->x_wid;
2536
2537 if (pi->block->y_offset + pi->block->y_wid > pi->y_max)
2538 pi->y_max = pi->block->y_offset + pi->block->y_wid;
2539
2540 if (DEBUG)
2541 pic2_show_pic2_info(pi);
2542 return (1);
2543 }
2544
pic2_find_block(pi)2545 static int pic2_find_block(pi)
2546 struct pic2_info *pi;
2547 {
2548 if (pi->mode != PIC2_READ_MODE)
2549 return (-1);
2550
2551 pi->next_pos = pi->header->size;
2552 return (pic2_next_block(pi));
2553 }
2554
2555 /*
2556 * These functions load/save the pic2 image block.
2557 * pic2_load_block:
2558 * initializes loader information with current block information.
2559 * pic2_save_block:
2560 * initializes saver information.
2561 */
pic2_load_block(pi)2562 static int pic2_load_block(pi)
2563 struct pic2_info *pi;
2564 {
2565 int i;
2566
2567 for (i = 0; i < n_form_tab; i++) {
2568 if (xvbcmp(pi->block->id, form_tab[i].id, (size_t) 4) == 0)
2569 break;
2570 }
2571 if (i == n_form_tab)
2572 return (2);
2573
2574 pic2_alloc_buffer(pi);
2575 return (form_tab[i].loader_init(pi));
2576 }
2577
pic2_save_block(pi,line,x,y,xw,yw,id,opaque)2578 static int pic2_save_block(pi, line, x, y, xw, yw, id, opaque)
2579 struct pic2_info *pi;
2580 pixel **line;
2581 int x, y, xw, yw;
2582 char *id;
2583 pixel opaque;
2584 {
2585 int i;
2586
2587 for (i = 0; i < n_form_tab; i++) {
2588 if (xvbcmp(id, form_tab[i].id, (size_t) 4) == 0)
2589 break;
2590 }
2591 if (i == n_form_tab)
2592 return (2);
2593
2594 strncpy(pi->block->id, id, 4);
2595 pi->block->x_wid = xw;
2596 pi->block->y_wid = yw;
2597 pi->block->x_offset = x;
2598 pi->block->y_offset = y;
2599 pi->block->reserve = 0;
2600
2601 if (x < 0)
2602 x = 0;
2603 if (y < 0)
2604 y = 0;
2605 if (x + xw > pi->x_max)
2606 pi->x_max = x + xw;
2607 if (y + yw > pi->y_max)
2608 pi->y_max = y + yw;
2609
2610 if (opaque != 0xffffffff) {
2611 pi->block->flag = 1;
2612 pi->block->opaque = opaque;
2613 } else {
2614 pi->block->flag = 0;
2615 pi->block->opaque = 0;
2616 }
2617 pic2_alloc_buffer(pi);
2618
2619 return (form_tab[i].saver_init(pi, line));
2620 }
2621
2622 /*
2623 * These functions set/get palettes.
2624 * pic2_read_palette:
2625 * copy the palettes from pic2_info to PICINFO.
2626 * pic2_write_palette:
2627 * copy the palettes from PICINFO to pic2_info.
2628 */
2629 #ifndef PIC2_IGNORE_UNUSED_FUNCTIONS
pic2_read_palette(pi,r,g,b)2630 static void pic2_read_palette(pi, r, g, b)
2631 struct pic2_info *pi;
2632 byte *r, *g, *b;
2633 {
2634 int i;
2635
2636 if (pi->n_pal > 256)
2637 pi->n_pal = 256;
2638
2639 if (pi->pal_bits > 8)
2640 pi->pal_bits = 8;
2641
2642 for (i = 0; i < pi->n_pal; i++) {
2643 *r++ =pic2_convert_color_bits(pi->pal[i][0] >> (8 - pi->pal_bits),
2644 pi->pal_bits, 8);
2645 *g++ =pic2_convert_color_bits(pi->pal[i][1] >> (8 - pi->pal_bits),
2646 pi->pal_bits, 8);
2647 *b++ =pic2_convert_color_bits(pi->pal[i][2] >> (8 - pi->pal_bits),
2648 pi->pal_bits, 8);
2649 }
2650 }
2651
pic2_write_palette(pi,n_pal,pal_bits,r,g,b)2652 static void pic2_write_palette(pi, n_pal, pal_bits, r, g, b)
2653 struct pic2_info *pi;
2654 int n_pal, pal_bits;
2655 byte *r, *g, *b;
2656 {
2657 int i;
2658
2659 if (n_pal > 256)
2660 pi->n_pal = 256;
2661 else
2662 pi->n_pal = n_pal;
2663
2664 if (pal_bits > 8)
2665 pi->pal_bits = 8;
2666 else
2667 pi->pal_bits = pal_bits;
2668
2669 for (i = 0; i < n_pal; i++) {
2670 pi->pal[i][0] = pic2_convert_color_bits(*r++, 8, pal_bits)
2671 << (8 - pal_bits);
2672 pi->pal[i][1] = pic2_convert_color_bits(*g++, 8, pal_bits)
2673 << (8 - pal_bits);
2674 pi->pal[i][2] = pic2_convert_color_bits(*b++, 8, pal_bits)
2675 << (8 - pal_bits);
2676 }
2677 }
2678 #endif /* PIC2_IGNORE_UNUSED_FUNCTIONS */
2679
2680 /*
2681 * These functions handle color bits.
2682 * pic2_convert_color_bits:
2683 * converts color bits.
2684 * pic2_pad_color_bits:
2685 * pads color bits.
2686 * pic2_reduce_color_bits:
2687 * reduces color bits.
2688 * pic2_exchange_rg:
2689 * exchanges red and green values.
2690 */
pic2_convert_color_bits(c,from,to)2691 static byte pic2_convert_color_bits(c, from, to)
2692 int c, from, to;
2693 {
2694 if (from == to)
2695 return ((byte) c);
2696 else if (from < to)
2697 return (pic2_pad_color_bits(c, from, to));
2698 else
2699 return (pic2_reduce_color_bits(c, from, to));
2700 }
2701
pic2_pad_color_bits(c,from,to)2702 static byte pic2_pad_color_bits(c, from, to)
2703 int c, from, to;
2704 {
2705 byte p = 0;
2706
2707 do {
2708 to -= from;
2709 p |= pic2_shift_bits(c, to);
2710 } while (to >= 0);
2711 return (p);
2712 }
2713
pic2_reduce_color_bits(c,from,to)2714 static byte pic2_reduce_color_bits(c, from, to)
2715 int c, from, to;
2716 {
2717 return ((byte) (c >> (from - to)));
2718 }
2719
pic2_exchange_rg(p,colbits)2720 static pixel pic2_exchange_rg(p, colbits)
2721 pixel p;
2722 int colbits;
2723 {
2724 pixel rmask, gmask, bmask;
2725
2726 rmask = (0xff >> (8 - colbits)) << (colbits * 2);
2727 gmask = (0xff >> (8 - colbits)) << colbits;
2728 bmask = (0xff >> (8 - colbits));
2729
2730 p = ((p << colbits) & rmask)
2731 | ((p >> colbits) & gmask)
2732 | ( p & bmask);
2733 return (p);
2734 }
2735
2736 /*
2737 * This function handles work memory buffer.
2738 */
pic2_handle_para(pi,mode)2739 static void pic2_handle_para(pi, mode)
2740 struct pic2_info *pi;
2741 int mode;
2742 {
2743 static pixel *vram_prev, *vram_now, *vram_next;
2744 static short *flag_now, *flag_next;
2745 static short *flag2_now, *flag2_next, *flag2_next2;
2746
2747 switch (mode) {
2748 case 0:
2749 vram_prev = pi->vram_prev;
2750 vram_now = pi->vram_now;
2751 vram_next = pi->vram_next;
2752 flag_now = pi->flag_now;
2753 flag_next = pi->flag_next;
2754 flag2_now = pi->flag2_now;
2755 flag2_next = pi->flag2_next;
2756 flag2_next2 = pi->flag2_next2;
2757 pi->vram_prev += 4;
2758 pi->vram_now += 4;
2759 pi->vram_next += 4;
2760 pi->flag_now += 4;
2761 pi->flag_next += 4;
2762 pi->flag2_now += 4;
2763 pi->flag2_next += 4;
2764 pi->flag2_next2 += 4;
2765 break;
2766 case 1:
2767 pi->vram_prev = vram_now;
2768 pi->vram_now = vram_next;
2769 pi->vram_next = vram_prev;
2770 pi->flag_now = flag_next;
2771 pi->flag_next = flag_now;
2772 pi->flag2_now = flag2_next;
2773 pi->flag2_next = flag2_next2;
2774 pi->flag2_next2 = flag2_now;
2775 break;
2776 }
2777 }
2778
2779 /*
2780 * These functions alloc/free work memory.
2781 * pic2_alloc_buffer:
2782 * alloc work memory buffer.
2783 * pic2_free_buffer:
2784 * free work memory buffer.
2785 */
pic2_alloc_buffer(pi)2786 static int pic2_alloc_buffer(pi)
2787 struct pic2_info *pi;
2788 {
2789 int wid;
2790 byte *p;
2791
2792 if (pi->buf != NULL)
2793 return (-1);
2794
2795 wid = pi->block->x_wid;
2796
2797 p = pi->buf = (byte *) pic2_new((wid + 8) * sizeof(pixel) * 3 // GRR POSSIBLE OVERFLOW / FIXME
2798 + sizeof(pi->cache[0]) * 8 * 8 * 8
2799 + sizeof(pi->cache_pos[0]) * 8 * 8 * 8
2800 + sizeof(pi->mulu_tab[0]) * 16384
2801 + sizeof(pi->flag_now[0]) * ((wid+8) * 5),
2802 "pic2_alloc_buffer");
2803
2804 pi->vram_prev = (pixel *) p;
2805 p += (wid + 8) * sizeof(pixel);
2806 pi->vram_now = (pixel *) p;
2807 p += (wid + 8) * sizeof(pixel);
2808 pi->vram_next = (pixel *) p;
2809 p += (wid + 8) * sizeof(pixel);
2810 pi->cache = (pixel (*)[PIC2_ARITH_CACHE]) p;
2811 p += sizeof(pi->cache[0]) * 8 * 8 * 8;
2812 pi->cache_pos = (unsigned short *) p;
2813 p += sizeof(pi->cache_pos[0]) * 8 * 8 * 8;
2814 pi->mulu_tab = (unsigned short *) p;
2815 p += sizeof(pi->mulu_tab[0]) * 16384;
2816 pi->flag_now = (short *) p;
2817 p += sizeof(pi->flag_now[0]) * (wid + 8);
2818 pi->flag_next = (short *) p;
2819 p += sizeof(pi->flag_next[0]) * (wid + 8);
2820 pi->flag2_now = (short *) p;
2821 p += sizeof(pi->flag2_now[0]) * (wid + 8);
2822 pi->flag2_next = (short *) p;
2823 p += sizeof(pi->flag2_next[0]) * (wid + 8);
2824 pi->flag2_next2 = (short *) p;
2825 p += sizeof(pi->flag2_next2[0]) * (wid + 8);
2826 return (0);
2827 }
2828
pic2_free_buffer(pi)2829 static void pic2_free_buffer(pi)
2830 struct pic2_info *pi;
2831 {
2832 free(pi->buf);
2833 pi->buf = NULL;
2834 }
2835
2836 /*
2837 * These functions handle the file pointer.
2838 * pic2_seek_file:
2839 * moves the file pointer.
2840 * pic2_tell_file:
2841 * tells the location of the file pointer.
2842 */
pic2_seek_file(pi,offset,whence)2843 static long pic2_seek_file(pi, offset, whence)
2844 struct pic2_info *pi;
2845 long offset;
2846 int whence;
2847 {
2848 long n;
2849
2850 n = fseek(pi->fp, offset, whence);
2851 if (n < 0)
2852 pic2_file_error(pi, PIC2_CORRUPT);
2853
2854 return (n);
2855 }
2856
pic2_tell_file(pi)2857 static long pic2_tell_file(pi)
2858 struct pic2_info *pi;
2859 {
2860 return (ftell(pi->fp));
2861 }
2862
2863 /*
2864 * These functions handle file.
2865 * pic2_read_file:
2866 * reads data from the file.
2867 * pic2_read_long:
2868 * reads long word data from the file and converts to internal expression.
2869 * pic2_read_short:
2870 * reads word data from the file and converts to internal expression.
2871 * pic2_read_char:
2872 * reads byte data from the file.
2873 * pic2_write_file:
2874 * writes data to the file.
2875 * pic2_write_long:
2876 * converts long word data to common expression and writes to the file.
2877 * pic2_write_short:
2878 * converts word data to common expression and writes to the file.
2879 * pic2_write_char:
2880 * writes byte data to the file.
2881 */
pic2_read_file(pi,buf,size)2882 static int pic2_read_file(pi, buf, size)
2883 struct pic2_info *pi;
2884 void *buf;
2885 size_t size;
2886 {
2887 if (fread(buf, (size_t) 1, size, pi->fp) < size)
2888 pic2_file_error(pi, PIC2_CORRUPT);
2889 return (0);
2890 }
2891
pic2_read_long(pi)2892 static long pic2_read_long(pi)
2893 struct pic2_info *pi;
2894 {
2895 byte buf[4];
2896
2897 if (fread(buf, (size_t) 4, (size_t) 1, pi->fp) < 1)
2898 pic2_file_error(pi, PIC2_CORRUPT);
2899 return (pic2_cextolong(buf));
2900 }
2901
pic2_read_short(pi)2902 static short pic2_read_short(pi)
2903 struct pic2_info *pi;
2904 {
2905 byte buf[2];
2906
2907 if (fread(buf, (size_t) 2, (size_t) 1, pi->fp) < 1)
2908 pic2_file_error(pi, PIC2_CORRUPT);
2909 return (pic2_cextoshort(buf));
2910 }
2911
pic2_read_char(pi)2912 static char pic2_read_char(pi)
2913 struct pic2_info *pi;
2914 {
2915 int c;
2916
2917 if ((c = fgetc(pi->fp)) == EOF)
2918 pic2_file_error(pi, PIC2_CORRUPT);
2919 return ((char) c);
2920 }
2921
pic2_write_file(pi,buf,size)2922 static int pic2_write_file(pi, buf, size)
2923 struct pic2_info *pi;
2924 void *buf;
2925 size_t size;
2926 {
2927 if (fwrite(buf, (size_t) 1, size, pi->fp) < size)
2928 pic2_error(pi, PIC2_WRITE);
2929 return (0);
2930 }
2931
pic2_write_long(pi,n)2932 static int pic2_write_long(pi, n)
2933 struct pic2_info *pi;
2934 long n;
2935 {
2936 byte buf[4];
2937
2938 pic2_longtocex(buf, n);
2939 if (fwrite(buf, (size_t) 4, (size_t) 1, pi->fp) < 1)
2940 pic2_error(pi, PIC2_WRITE);
2941 return (0);
2942 }
2943
pic2_write_short(pi,n)2944 static int pic2_write_short(pi, n)
2945 struct pic2_info *pi;
2946 int n;
2947 {
2948 byte buf[2];
2949
2950 pic2_shorttocex(buf, n);
2951 if (fwrite(buf, (size_t) 2, (size_t) 1, pi->fp) < 1)
2952 pic2_error(pi, PIC2_WRITE);
2953 return (0);
2954 }
2955
pic2_write_char(pi,c)2956 static int pic2_write_char(pi, c)
2957 struct pic2_info *pi;
2958 int c;
2959 {
2960 if (fputc(c, pi->fp) == EOF)
2961 pic2_error(pi, PIC2_WRITE);
2962 return (0);
2963 }
2964
2965 /*
2966 * These functions access the bit stream.
2967 * pic2_read_bits:
2968 * reads the specified bits from the file.
2969 * pic2_write_bits:
2970 * writes the specified bits to the file.
2971 * pic2_flush_bits:
2972 * flushes bit buffer to the file.
2973 */
pic2_read_bits(pi,bits)2974 static unsigned long pic2_read_bits(pi, bits)
2975 struct pic2_info *pi;
2976 int bits;
2977 {
2978 unsigned long r = 0;
2979
2980 while (bits > 0) {
2981 while (pi->bs.rest > 0 && bits > 0) {
2982 r = (r << 1) | (pi->bs.cur & 0x80 ? 1 : 0);
2983 pi->bs.cur <<= 1;
2984 pi->bs.rest--;
2985 bits--;
2986 }
2987 if (bits > 0) {
2988 int c;
2989 if ((c = fgetc(pi->fp)) == EOF)
2990 pic2_file_error(pi, PIC2_CORRUPT);
2991 pi->bs.cur = (byte) c;
2992 pi->bs.rest = 8;
2993 }
2994 }
2995 return r;
2996 }
2997
pic2_write_bits(pi,dat,bits)2998 static void pic2_write_bits(pi, dat, bits)
2999 struct pic2_info *pi;
3000 unsigned long dat;
3001 int bits;
3002 {
3003 unsigned long dat_mask = 1 << (bits - 1);
3004
3005 while (bits > 0) {
3006 while (pi->bs.rest < 8 && bits > 0) {
3007 pi->bs.cur <<= 1;
3008 if (dat & dat_mask)
3009 pi->bs.cur |= 1;
3010 pi->bs.rest++;
3011 bits--;
3012 dat_mask >>= 1;
3013 }
3014 if (pi->bs.rest >= 8) {
3015 if ((fputc((int) pi->bs.cur, pi->fp)) == EOF)
3016 pic2_error(pi, PIC2_WRITE);
3017 pi->bs.cur = 0;
3018 pi->bs.rest = 0;
3019 }
3020 }
3021 }
3022
pic2_flush_bits(pi)3023 static void pic2_flush_bits(pi)
3024 struct pic2_info *pi;
3025 {
3026 if (pi->bs.rest < 8) {
3027 pi->bs.cur <<= 8 - pi->bs.rest;
3028 if (fputc((int) pi->bs.cur, pi->fp) == EOF)
3029 pic2_error(pi, PIC2_WRITE);
3030 pi->bs.cur = 0;
3031 pi->bs.rest = 0;
3032 }
3033 }
3034
3035 /*
3036 * These functions initialize or clean up structures.
3037 * pic2_init_info:
3038 * initializes a pic2_info structure.
3039 * pic2_cleanup_pic2_info:
3040 * cleans up a pic_info structure.
3041 * pic2_cleanup_pinfo:
3042 * cleans up a PICINFO structure.
3043 */
pic2_init_info(pi)3044 static void pic2_init_info(pi)
3045 struct pic2_info *pi;
3046 {
3047 xvbzero((char *) pi, sizeof(struct pic2_info));
3048 pi->header = pic2_new(sizeof(struct pic2_header), "pic2_init_info#1");
3049 pi->block = pic2_new(sizeof(struct pic2_block), "pic2_init_info#2");
3050 }
3051
pic2_cleanup_pic2_info(pi,writing)3052 static void pic2_cleanup_pic2_info(pi, writing)
3053 struct pic2_info *pi;
3054 int writing;
3055 {
3056 if (!writing && pi->fp)
3057 fclose(pi->fp);
3058 if (pi->header)
3059 free(pi->header);
3060 if (pi->block)
3061 free(pi->block);
3062 pi->fp = NULL;
3063 pi->header = NULL;
3064 pi->block = NULL;
3065 pi->comment = NULL;
3066 }
3067
pic2_cleanup_pinfo(pinfo)3068 static void pic2_cleanup_pinfo(pinfo)
3069 PICINFO *pinfo;
3070 {
3071 if (pinfo->pic){
3072 free(pinfo->pic);
3073 pinfo->pic = NULL;
3074 }
3075 if (pinfo->comment){
3076 free(pinfo->comment);
3077 pinfo->comment = NULL;
3078 }
3079 }
3080
3081 /*
3082 * Error Handlers.
3083 * pic2_memory_error:
3084 * shows an error message and terminates.
3085 * pic2_error:
3086 * shows a non-file error message and jumps to the entry for errors.
3087 * pic2_file_error:
3088 * shows a file error message and jumps to the entry for errors.
3089 */
pic2_memory_error(scm,fn)3090 static void pic2_memory_error(scm, fn)
3091 char *scm, *fn;
3092 {
3093 char buf[128];
3094 sprintf(buf, "%s: can't allocate memory. (%s)", scm, fn);
3095 FatalError(buf);
3096 }
3097
pic2_error(pi,mn)3098 static void pic2_error(pi, mn)
3099 struct pic2_info *pi;
3100 int mn;
3101 {
3102 SetISTR(ISTR_WARNING, "%s", pic2_msgs[mn]);
3103 longjmp(pi->jmp, 1);
3104 }
3105
pic2_file_error(pi,mn)3106 static void pic2_file_error(pi, mn)
3107 struct pic2_info *pi;
3108 int mn;
3109 {
3110 if (feof(pi->fp))
3111 SetISTR(ISTR_WARNING, "%s (end of file)", pic2_msgs[mn]);
3112 else
3113 SetISTR(ISTR_WARNING, "%s (%s)", pic2_msgs[mn], ERRSTR(errno));
3114 longjmp(pi->jmp, 1);
3115 }
3116
pic2_show_pic2_info(pi)3117 static void pic2_show_pic2_info(pi)
3118 struct pic2_info *pi;
3119 {
3120 fprintf(stderr, "file size: %ld.\n", pi->fsize);
3121 fprintf(stderr, "full image size: %dx%d\n", pi->x_max, pi->y_max);
3122 fprintf(stderr, "number of palettes: %d\n", pi->n_pal);
3123 fprintf(stderr, "depth of palettes: %d\n", pi->pal_bits);
3124 fprintf(stderr, "current block position: %ld\n", pi->block_pos);
3125 fprintf(stderr, "next block position: %ld\n\n", pi->next_pos);
3126
3127 fprintf(stderr, "header flag: %x\n", pi->header->flag);
3128 fprintf(stderr, "header size: %ld\n", pi->header->size);
3129 fprintf(stderr, "x_aspect: %d, y_aspect: %d\n",
3130 pi->header->x_aspect, pi->header->y_aspect);
3131 fprintf(stderr, "number of color bits: %d\n\n", pi->header->depth);
3132
3133 fprintf(stderr, "image block id: %s\n", pi->block->id);
3134 fprintf(stderr, "image block size: %ld\n", pi->block->size);
3135 fprintf(stderr, "block flag: %x\n", pi->block->flag);
3136
3137 fprintf(stderr, "block image size: %dx%d\n",
3138 pi->block->x_wid, pi->block->y_wid);
3139 fprintf(stderr, "x_offset: %d\n", pi->block->x_offset);
3140 fprintf(stderr, "y_offset: %d\n", pi->block->y_offset);
3141 fprintf(stderr, "opaque color: %lx\n\n", pi->block->opaque);
3142 }
3143
3144 /*
3145 * This function is similar to strncpy.
3146 * But this pads with whitespace after the null character.
3147 */
pic2_strncpy(dest,src,n)3148 static char *pic2_strncpy(dest, src, n)
3149 char *dest, *src;
3150 size_t n;
3151 {
3152 char *r;
3153
3154 r = dest;
3155 while (n--)
3156 if ((src != NULL) && (*src != '\r') && (*src != '\n') && *src)
3157 *dest++ = *src++;
3158 else
3159 *dest++ = ' ';
3160 return (r);
3161 }
3162
3163 /*
3164 * These functions create a memory block.
3165 */
pic2_malloc(size,fn)3166 static void *pic2_malloc(size, fn)
3167 size_t size;
3168 char *fn;
3169 {
3170 void *p;
3171
3172 p = (void *) malloc(size);
3173 if (p == NULL)
3174 pic2_memory_error("malloc", fn);
3175 return (p);
3176 }
3177
pic2_new(size,fn)3178 static void *pic2_new(size, fn)
3179 size_t size;
3180 char *fn;
3181 {
3182 void *p;
3183
3184 p = (void *) pic2_malloc(size, fn);
3185 xvbzero((char *) p, size);
3186 return (p);
3187 }
3188
3189
3190
3191
3192 /**** Stuff for PIC2Dialog box ****/
3193
3194 #define TWIDE 320
3195 #define THIGH 178
3196 #define T_NBUTTS 2
3197 #define T_BOK 0
3198 #define T_BCANC 1
3199 #define BUTTH 24
3200
3201 static void drawTD PARM((int,int,int,int));
3202 static void clickTD PARM((int,int));
3203 static void doCmd PARM((int));
3204 static void writePIC2 PARM((void));
3205
3206 /* local variables */
3207 static FILE *fp;
3208 static char *filename;
3209 static int colorType;
3210 static int append;
3211 static int x_offset;
3212 static int y_offset;
3213 static BUTT tbut[T_NBUTTS];
3214 static RBUTT *typeRB;
3215 static RBUTT *depthRB;
3216
3217
3218
3219 /***************************************************/
CreatePIC2W()3220 void CreatePIC2W()
3221 {
3222 int y;
3223
3224 pic2W = CreateWindow("xv pic2", "XVpic2", NULL,
3225 TWIDE, THIGH, infofg, infobg, 0);
3226 if (!pic2W)
3227 FatalError("can't create pic2 window!");
3228
3229 XSelectInput(theDisp, pic2W,
3230 ExposureMask | ButtonPressMask | KeyPressMask);
3231
3232 BTCreate(&tbut[T_BOK], pic2W, TWIDE-140-1, THIGH-10-BUTTH-1, 60, BUTTH,
3233 "Ok", infofg, infobg, hicol, locol);
3234
3235 BTCreate(&tbut[T_BCANC], pic2W, TWIDE-70-1, THIGH-10-BUTTH-1, 60, BUTTH,
3236 "Cancel", infofg, infobg, hicol, locol);
3237
3238 y = 55;
3239 typeRB = RBCreate(NULL, pic2W, 36, y, "P2SS",
3240 infofg, infobg,hicol,locol);
3241 RBCreate(typeRB, pic2W, 36, y+18, "P2SF",
3242 infofg, infobg,hicol,locol);
3243 RBCreate(typeRB, pic2W, 36, y+36, "P2BM",
3244 infofg, infobg, hicol, locol);
3245 RBCreate(typeRB, pic2W, 36, y+54, "P2BI",
3246 infofg, infobg, hicol, locol);
3247
3248 depthRB = RBCreate(NULL, pic2W, TWIDE/2-16, y, " 3bit",
3249 infofg, infobg,hicol,locol);
3250 RBCreate(depthRB, pic2W, TWIDE/2-16, y+18, " 6bit",
3251 infofg, infobg,hicol,locol);
3252 RBCreate(depthRB, pic2W, TWIDE/2-16, y+36, " 9bit",
3253 infofg, infobg, hicol, locol);
3254 RBCreate(depthRB, pic2W, TWIDE/2-16, y+54, "12bit",
3255 infofg, infobg, hicol, locol);
3256 RBCreate(depthRB, pic2W, TWIDE/4*3-16, y, "15bit",
3257 infofg, infobg, hicol, locol);
3258 RBCreate(depthRB, pic2W, TWIDE/4*3-16, y+18, "18bit",
3259 infofg, infobg, hicol, locol);
3260 RBCreate(depthRB, pic2W, TWIDE/4*3-16, y+36, "21bit",
3261 infofg, infobg, hicol, locol);
3262 RBCreate(depthRB, pic2W, TWIDE/4*3-16, y+54, "24bit",
3263 infofg, infobg, hicol, locol);
3264
3265 XMapSubwindows(theDisp, pic2W);
3266 }
3267
3268
3269 /***************************************************/
PIC2Dialog(vis)3270 void PIC2Dialog(vis)
3271 int vis;
3272 {
3273 if (vis) {
3274 CenterMapWindow(pic2W, tbut[T_BOK].x + tbut[T_BOK].w/2,
3275 tbut[T_BOK].y + tbut[T_BOK].h/2, TWIDE, THIGH);
3276 }
3277 else XUnmapWindow(theDisp, pic2W);
3278 pic2Up = vis;
3279 }
3280
3281
3282 /***************************************************/
PIC2CheckEvent(xev)3283 int PIC2CheckEvent(xev)
3284 XEvent *xev;
3285 {
3286 /* check event to see if it's for one of our subwindows. If it is,
3287 deal accordingly and return '1'. Otherwise, return '0'. */
3288
3289 int rv;
3290 rv = 1;
3291
3292 if (!pic2Up)
3293 return (0);
3294
3295 if (xev->type == Expose) {
3296 int x,y,w,h;
3297 XExposeEvent *e = (XExposeEvent *) xev;
3298 x = e->x; y = e->y; w = e->width; h = e->height;
3299
3300 if (e->window == pic2W) drawTD(x, y, w, h);
3301 else rv = 0;
3302 }
3303
3304 else if (xev->type == ButtonPress) {
3305 XButtonEvent *e = (XButtonEvent *) xev;
3306 int x,y;
3307 x = e->x; y = e->y;
3308
3309 if (e->button == Button1) {
3310 if (e->window == pic2W) clickTD(x,y);
3311 else rv = 0;
3312 } /* button1 */
3313 else rv = 0;
3314 } /* button press */
3315
3316
3317 else if (xev->type == KeyPress) {
3318 XKeyEvent *e = (XKeyEvent *) xev;
3319 char buf[128]; KeySym ks; XComposeStatus status;
3320 int stlen;
3321
3322 stlen = XLookupString(e,buf,128,&ks,&status);
3323 buf[stlen] = '\0';
3324
3325 if (e->window == pic2W) {
3326 if (stlen) {
3327 if (buf[0] == '\r' || buf[0] == '\n') { /* enter */
3328 FakeButtonPress(&tbut[T_BOK]);
3329 }
3330 else if (buf[0] == '\033') { /* ESC */
3331 FakeButtonPress(&tbut[T_BCANC]);
3332 }
3333 }
3334 }
3335 else rv = 0;
3336 }
3337 else rv = 0;
3338
3339 if (rv == 0 && (xev->type == ButtonPress || xev->type == KeyPress)) {
3340 XBell(theDisp, 50);
3341 rv = 1; /* eat it */
3342 }
3343
3344 return (rv);
3345 }
3346
3347
3348 /***************************************************/
PIC2SaveParams(fname,col)3349 int PIC2SaveParams(fname, col)
3350 char *fname;
3351 int col;
3352 {
3353 filename = fname;
3354 colorType = col;
3355
3356 /* see if we can open the output file before proceeding */
3357 fp = pic2_OpenOutFile(filename, &append);
3358 if (!fp)
3359 return (-1);
3360
3361 RBSetActive(typeRB,0,1);
3362 RBSetActive(typeRB,1,1);
3363 RBSetActive(typeRB,2,1);
3364 RBSetActive(typeRB,3,1);
3365 RBSelect(typeRB,0);
3366
3367
3368 if (append) {
3369 struct pic2_info pic2;
3370
3371 pic2_init_info(&pic2);
3372 pic2.fp = fp;
3373 pic2_read_header(&pic2);
3374
3375 RBSetActive(depthRB,0,0);
3376 RBSetActive(depthRB,1,0);
3377 RBSetActive(depthRB,2,0);
3378 RBSetActive(depthRB,3,0);
3379 RBSetActive(depthRB,4,0);
3380 RBSetActive(depthRB,5,0);
3381 RBSetActive(depthRB,6,0);
3382 RBSetActive(depthRB,7,0);
3383
3384 switch (pic2.header->depth) {
3385 case 3:
3386 RBSetActive(depthRB,0,1);
3387 RBSelect(depthRB,0);
3388 RBSetActive(typeRB,3,0);
3389 break;
3390 case 6:
3391 RBSetActive(depthRB,1,1);
3392 RBSelect(depthRB,1);
3393 RBSetActive(typeRB,3,0);
3394 break;
3395 case 9:
3396 RBSetActive(depthRB,2,1);
3397 RBSelect(depthRB,2);
3398 break;
3399 case 12:
3400 RBSetActive(depthRB,3,1);
3401 RBSelect(depthRB,3);
3402 break;
3403 case 15:
3404 RBSetActive(depthRB,4,1);
3405 RBSelect(depthRB,4);
3406 break;
3407 case 18:
3408 RBSetActive(depthRB,5,1);
3409 RBSelect(depthRB,5);
3410 RBSetActive(typeRB,3,0);
3411 break;
3412 case 21:
3413 RBSetActive(depthRB,6,1);
3414 RBSelect(depthRB,6);
3415 RBSetActive(typeRB,3,0);
3416 break;
3417 case 24:
3418 RBSetActive(depthRB,7,1);
3419 RBSelect(depthRB,7);
3420 RBSetActive(typeRB,3,0);
3421 break;
3422 default: {
3423 char str[512];
3424 sprintf(str, "unsupported PIC2 file '%s'.", filename);
3425 ErrPopUp(str, "\nBummer");
3426 CloseOutFile(fp, filename, 0);
3427 fp = OpenOutFile(fname);
3428 if (!fp)
3429 return (-1);
3430 break;
3431 }
3432 }
3433 pic2_seek_file(&pic2, 0, SEEK_SET);
3434 pic2_cleanup_pic2_info(&pic2, 1);
3435 } else {
3436 RBSetActive(depthRB,0,1);
3437 RBSetActive(depthRB,1,1);
3438 RBSetActive(depthRB,2,1);
3439 RBSetActive(depthRB,3,1);
3440 RBSetActive(depthRB,4,1);
3441 RBSetActive(depthRB,5,1);
3442 RBSetActive(depthRB,6,1);
3443 RBSetActive(depthRB,7,1);
3444 RBSelect(depthRB,7);
3445 RBSetActive(typeRB,3,0);
3446 }
3447 return (0);
3448 }
3449
3450
3451 /***************************************************/
drawTD(x,y,w,h)3452 static void drawTD(x,y,w,h)
3453 int x,y,w,h;
3454 {
3455 char *title = "Save PIC2 file...";
3456 int i;
3457 XRectangle xr;
3458
3459 xr.x = x; xr.y = y; xr.width = w; xr.height = h;
3460 XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
3461
3462 XSetForeground(theDisp, theGC, infofg);
3463 XSetBackground(theDisp, theGC, infobg);
3464
3465 for (i = 0; i < T_NBUTTS; i++)
3466 BTRedraw(&tbut[i]);
3467
3468 ULineString(pic2W, typeRB->x-16, typeRB->y-3-DESCENT, "FormatType");
3469 ULineString(pic2W, depthRB->x-16, depthRB->y-3-DESCENT, "ColorDepth");
3470 RBRedraw(typeRB, -1);
3471 RBRedraw(depthRB, -1);
3472
3473 DrawString(pic2W, 20, 29, title);
3474
3475 XSetClipMask(theDisp, theGC, None);
3476 }
3477
clickTD(x,y)3478 static void clickTD(x,y)
3479 int x,y;
3480 {
3481 int i;
3482 BUTT *bp;
3483
3484 /* check BUTTs */
3485
3486 /* check the RBUTTS first, since they don't DO anything */
3487 if ((i = RBClick(typeRB, x,y)) >= 0) {
3488 (void) RBTrack(typeRB, i);
3489 return;
3490 } else if ((i = RBClick(depthRB, x,y)) >= 0) {
3491 (void) RBTrack(depthRB, i);
3492 if ((2 <= i) && (i <= 4))
3493 RBSetActive(typeRB,3,1);
3494 else {
3495 RBSetActive(typeRB,3,0);
3496 if (RBWhich(typeRB) == 3)
3497 RBSelect(typeRB,0);
3498 return;
3499 }
3500 }
3501 for (i = 0; i < T_NBUTTS; i++) {
3502 bp = &tbut[i];
3503 if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h))
3504 break;
3505 }
3506 if (i < T_NBUTTS) /* found one */
3507 if (BTTrack(bp))
3508 doCmd(i);
3509 }
3510
3511
3512
3513 /***************************************************/
doCmd(cmd)3514 static void doCmd(cmd)
3515 int cmd;
3516 {
3517 switch (cmd) {
3518 case T_BOK: {
3519 char *fullname;
3520 char buf[64], *x_offsetp, *y_offsetp;
3521 static const char *labels[] = { "\nOk", "\033Cancel" };
3522 XEvent event;
3523 int i;
3524
3525 strcpy(buf, "0,0");
3526 i = GetStrPopUp("Enter offset (x,y):", labels, 2, buf, 64,
3527 "01234567890,", 1);
3528
3529 if (i)
3530 return;
3531 if (strlen(buf)==0)
3532 return;
3533
3534 x_offsetp = buf;
3535 y_offsetp = index(buf, ',');
3536 if (!y_offsetp)
3537 return;
3538 *(y_offsetp++) = '\0';
3539 if ((*x_offsetp == '\0') || (*y_offsetp == '\0'))
3540 return;
3541 x_offset = atoi(x_offsetp);
3542 y_offset = atoi(y_offsetp);
3543
3544 XNextEvent(theDisp, &event);
3545 HandleEvent(&event, &i);
3546
3547 writePIC2();
3548 PIC2Dialog(0);
3549
3550 fullname = GetDirFullName();
3551 if (!ISPIPE(fullname[0])) {
3552 XVCreatedFile(fullname);
3553 StickInCtrlList(0);
3554 }
3555 }
3556 break;
3557 case T_BCANC:
3558 pic2_KillNullFile(fp);
3559 PIC2Dialog(0);
3560 break;
3561 default:
3562 break;
3563 }
3564 }
3565
3566
3567 /*******************************************/
writePIC2()3568 static void writePIC2()
3569 {
3570 int w, h, nc, rv, type, depth, ptype, pfree;
3571 byte *inpix, *rmap, *gmap, *bmap;
3572
3573
3574 WaitCursor();
3575 inpix = GenSavePic(&ptype, &w, &h, &pfree, &nc, &rmap, &gmap, &bmap);
3576
3577 if (colorType == F_REDUCED)
3578 colorType = F_FULLCOLOR;
3579
3580 switch (RBWhich(typeRB)) {
3581 case 0: type = P2SS; break;
3582 case 1: type = P2SF; break;
3583 case 2: type = P2BM; break;
3584 case 3: type = P2BI; break;
3585 default: type = P2SS; break;
3586 }
3587 switch (RBWhich(depthRB)) {
3588 case 0: depth = 3; break;
3589 case 1: depth = 6; break;
3590 case 2: depth = 9; break;
3591 case 3: depth = 12; break;
3592 case 4: depth = 15; break;
3593 case 5: depth = 18; break;
3594 case 6: depth = 21; break;
3595 case 7: depth = 24; break;
3596 default: depth = 24; break;
3597 }
3598 rv = WritePIC2(fp, inpix, ptype, w, h,
3599 rmap, gmap, bmap, nc, colorType, filename,
3600 type, depth, x_offset, y_offset, append, picComments);
3601
3602 if (CloseOutFile(fp, filename, rv) == 0)
3603 DirBox(0);
3604
3605 if (pfree)
3606 free(inpix);
3607 }
3608 #endif /* HAVE_PIC2 */
3609