1 
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <assert.h>
7 #ifdef WIN32
8 #include <windows.h>
9 #else
10 #include <unistd.h>
11 #endif
12 
13 #include "toonz.h"
14 #include "tmsg.h"
15 #include "file.h"
16 #include "img.h"
17 #include "tmachine.h"
18 #include "../infoRegionP.h"
19 #include "ImageP/filetzr.h"
20 
21 #if !defined(TNZ_LITTLE_ENDIAN)
22   TNZ_LITTLE_ENDIAN undefined!!
23 #endif
24 
25 #if TNZ_LITTLE_ENDIAN
26 #define TZR_MAGIC ('T' | 'Z' << 8 | 'R' << 16 | 'A' << 24)
27 #else
28 #define TZR_MAGIC ('T' << 24 | 'Z' << 16 | 'R' << 8 | 'A')
29 #endif
30 
31 #ifdef NOTES
32 
33 numbers are always big endian (most significant byte first)
34 floats and doubles are IEEE, sign and exponent first (1+8+23 and 1+11+52)
35 
36 4 bytes: 'T' 'Z' 'R' 'A' (0x545a5241 big endian or 0x41525a54 little endian)
37 1 byte: type of file (0 is not valid)
38 1 byte: ST1 (subtype, must be 0 if not used)
39 1 byte: ST2 (")
40 1 byte: ST3 (")
41 (types form a tree, numbers should increase chronologically)
42 
43 type 1: fast
44   ST1 1: lineart CM (1 ink, 2 colors (transparent and opaque), 4 bits ramp)
45     ST2 1: RLE compression (see image section)
46 
47     3 bytes: image lx
48     3 bytes: image ly
49     3 bytes: image offset from start of file
50     tagged fields (fill up the space before the image):
51       1 byte field tag
52       if (tag >= 128)
53         2 bytes field length(=n)
54 	n bytes field value
55       else
56 	1 byte field length(=n)
57 	n bytes field value
58     image:
59       rle encoded 1 line at a time (to allow for subsampling)
60       rle encoding of 1 line:
61         2 or 3 bytes: length in bytes of encoded line
62 	(2 if image lx <= 8*1024, 3 otherwise)
63         1 nibble at a time, most significative nibble first:
64         if (0x0 <= nibble[0] <= 0xE)
65 	  nibble[0] is the tone value (0 is black)
66         if (nibble[0] == 0xF)
67           if (0x0 <= nibble[1] <= 0x7)
68             nibble[1] is the count of nibbles which follow (may be zero)
69             nibble[2...] number of white pixels in a run - 1, big endian
70           if (nibble[1] == 0x8)
71             toggle between transparent (0) and opaque (1) (starts with 0)
72           if (nibble[1] == 0xF)
73             if (nibble[2] == 0xE)
74               end of encoding
75             if (nibble[2] == 0xF)
76               nibble[3] is last pixel tone value, end of encoding
77         if line ends at odd nibble, a 0x0 nibble is appended
78 
79 
80 32:
81 
82         1 nibble at a time, most significative nibble first:
83 
84         if (0x0 <= nibble[1]|nibble[0] <= 0xFE)
85 	  nibble[1]|nibble[0] is the tone value (0 is black)
86         if (nibble[1]|nibble[0] == 0xFF)
87           if (0x0 <= nibble[2] <= 0x7)
88             nibble[2] is the count of nibbles which follow (may be zero)
89             nibble[3...] number of white pixels in a run - 1, big endian
90           if (nibble[2] == 0x8)
91             toggle between transparent (0) and opaque (1) (starts with 0)
92           if (nibble[2] == 0xF)
93             if (nibble[3] == 0xE)
94               end of encoding
95             if (nibble[3] == 0xF)
96               nibble[4]|nibble[5] is last pixel tone value, end of encoding
97         if line ends at odd nibble, a 0x0 nibble is appended
98 
99 #endif
100 
101 typedef enum
102   {
103   TAG_NONE = 0,
104 
105   TAG_DPI      = 1, /* size 16: double[2] (x_dpi, y_dpi) */
106       TAG_HPOS = 2, /* size  8: double */
107 
108       TAG_HOW_MANY = 256
109   }
110   TAG_TYPE;
111 
112 #define TAGS_BUFLEN 65536
113 
114 #define READ_BYTES_OR_ERROR(buf, n, file)                                      \
115   {                                                                            \
116     if (fread((buf), 1, (n), (file)) < (n)) goto error;                        \
117   }
118 
119 #define BYTES_TO_FLOAT(b, f)                                                   \
120   {                                                                            \
121     UCHAR *fr = (b);                                                           \
122     UCHAR *to = (UCHAR *)&(f);                                                 \
123     if (TNZ_LITTLE_ENDIAN) {                                                   \
124       to[0] = fr[3];                                                           \
125       to[1] = fr[2];                                                           \
126       to[2] = fr[1];                                                           \
127       to[3] = fr[0];                                                           \
128     } else {                                                                   \
129       to[0] = fr[0];                                                           \
130       to[1] = fr[1];                                                           \
131       to[2] = fr[2];                                                           \
132       to[3] = fr[3];                                                           \
133     }                                                                          \
134   }
135 
136 #define FLOAT_TO_BYTES(f, b)                                                   \
137   {                                                                            \
138     UCHAR *fr = (UCHAR *)&(f);                                                 \
139     UCHAR *to = (b);                                                           \
140     if (TNZ_LITTLE_ENDIAN) {                                                   \
141       to[0] = fr[3];                                                           \
142       to[1] = fr[2];                                                           \
143       to[2] = fr[1];                                                           \
144       to[3] = fr[0];                                                           \
145     } else {                                                                   \
146       to[0] = fr[0];                                                           \
147       to[1] = fr[1];                                                           \
148       to[2] = fr[2];                                                           \
149       to[3] = fr[3];                                                           \
150     }                                                                          \
151   }
152 
153 #define BYTES_TO_DOUBLE(b, d)                                                  \
154   {                                                                            \
155     UCHAR *fr = (b);                                                           \
156     UCHAR *to = (UCHAR *)&(d);                                                 \
157     if (TNZ_LITTLE_ENDIAN) {                                                   \
158       to[0] = fr[7];                                                           \
159       to[1] = fr[6];                                                           \
160       to[2] = fr[5];                                                           \
161       to[3] = fr[4];                                                           \
162       to[4] = fr[3];                                                           \
163       to[5] = fr[2];                                                           \
164       to[6] = fr[1];                                                           \
165       to[7] = fr[0];                                                           \
166     } else {                                                                   \
167       to[0] = fr[0];                                                           \
168       to[1] = fr[1];                                                           \
169       to[2] = fr[2];                                                           \
170       to[3] = fr[3];                                                           \
171       to[4] = fr[4];                                                           \
172       to[5] = fr[5];                                                           \
173       to[6] = fr[6];                                                           \
174       to[7] = fr[7];                                                           \
175     }                                                                          \
176   }
177 
178 #define DOUBLE_TO_BYTES(d, b)                                                  \
179   {                                                                            \
180     UCHAR *fr = (UCHAR *)&(d);                                                 \
181     UCHAR *to = (b);                                                           \
182     if (TNZ_LITTLE_ENDIAN) {                                                   \
183       to[0] = fr[7];                                                           \
184       to[1] = fr[6];                                                           \
185       to[2] = fr[5];                                                           \
186       to[3] = fr[4];                                                           \
187       to[4] = fr[3];                                                           \
188       to[5] = fr[2];                                                           \
189       to[6] = fr[1];                                                           \
190       to[7] = fr[0];                                                           \
191     } else {                                                                   \
192       to[0] = fr[0];                                                           \
193       to[1] = fr[1];                                                           \
194       to[2] = fr[2];                                                           \
195       to[3] = fr[3];                                                           \
196       to[4] = fr[4];                                                           \
197       to[5] = fr[5];                                                           \
198       to[6] = fr[6];                                                           \
199       to[7] = fr[7];                                                           \
200     }                                                                          \
201   }
202 
203 static void *Tzr_buffer;
204 static int   Tzr_buffer_bytes;
205 
206 static int Next_img_read_tzr_cmapped = FALSE;
207 static int Read_cmapped = FALSE;
208 #define SET_READ_CMAPPED                                                       \
209   {                                                                            \
210     Read_cmapped              = Next_img_read_tzr_cmapped;                     \
211     Next_img_read_tzr_cmapped = FALSE;                                         \
212   }
213 
214 /*---------------------------------------------------------------------------*/
215 
216 int tzr_safe_bytes_for_1_1_1_pixels (int n_pix)
217 {
218   /* un colore con cambio colore, un colore con cambio colore */
219   /* = 2 + 2 + 2 + 2 nibble = 4 bytes per 2 pixel */
220 
221   return 2 * n_pix + 2;
222 }
223 
224 /*---------------------------------------------------------------------------*/
225 
226 int tzr_safe_bytes_for_2_1_1_pixels (int n_pix)
227 {
228   /* un colore con cambio colore, un colore con cambio colore */
229   /* = 2 + 4 + 2 + 4 nibble = 6 bytes per 2 pixel */
230 
231   return 4 * n_pix + 2;
232 }
233 
234   /*---------------------------------------------------------------------------*/
235 
236 #define GET_INVAL                                                              \
237   {                                                                            \
238     inval = *in++;                                                             \
239     remain--;                                                                  \
240   }
241 #define PUT_OUTVAL                                                             \
242   { *out++ = (UCHAR)outval; }
243 
244 /*---------------------------------------------------------------------------*/
245 
246 int tzr_encode_cm16_1_1_1 (USHORT *buf_in, int buf_in_len,
247                            UCHAR  *buf_out)
248 {
249   int count, prevremain, remain;
250   UINT inval, outval;
251   UINT lastval, lastcol__;
252   UINT colmask, maxtone;
253   UINT incol__, tone;
254   USHORT *in, save;
255   UCHAR *out;
256 
257   maxtone = 0xF;
258   colmask = 0x07F0;
259 
260   remain    = buf_in_len;
261   lastval   = maxtone;
262   lastcol__ = 0;
263 
264   in  = buf_in;
265   out = buf_out;
266 
267   if (buf_in_len <= 1) {
268     if (buf_in_len < 0) return 0;
269     if (buf_in_len == 0) {
270       outval = 0xFF;
271       PUT_OUTVAL
272       outval = 0xE0;
273       PUT_OUTVAL
274     } else {
275       GET_INVAL
276       if (inval & colmask) {
277         outval = 0xF8;
278         PUT_OUTVAL
279       }
280       outval = 0xFF;
281       PUT_OUTVAL
282       outval = 0xF0 | inval & 0xF;
283       PUT_OUTVAL
284     }
285     return out - buf_out;
286   }
287 
288   save                   = buf_in[buf_in_len - 1];
289   buf_in[buf_in_len - 1] = buf_in[buf_in_len - 2] ^ colmask;
290 
291   GET_INVAL
292 
293 check_colpen_on_out0:
294   incol__              = inval & colmask;
295   if (incol__) incol__ = 0x10;
296   if (incol__ == lastcol__) goto check_tone_on_out0;
297   lastcol__ = incol__;
298   if (!remain) goto end_toonz1_encoding_on_out0;
299 
300   outval = (0xF << 4) | 0x8;
301   PUT_OUTVAL
302 
303 check_tone_on_out0:
304   tone = inval & maxtone;
305   if (tone == maxtone) {
306     lastval    = inval;
307     prevremain = remain;
308     do
309       GET_INVAL
310     while (inval == lastval);
311     count = prevremain - remain - 1;
312     if (count <= 0xF)
313       if (count == 0) {
314         outval = (0xF << 4) | 0x0;
315         PUT_OUTVAL
316         goto check_colpen_on_out0;
317       } else {
318         outval = (0xF << 4) | 0x1;
319         PUT_OUTVAL
320         outval = count << 4;
321         goto check_colpen_on_out1;
322       }
323     else if (count <= 0xFF) {
324       outval = (0xF << 4) | 0x2;
325       PUT_OUTVAL
326       outval = count;
327       PUT_OUTVAL
328       goto check_colpen_on_out0;
329     } else if (count <= 0xFFF) {
330       outval = (0xF << 4) | 0x3;
331       PUT_OUTVAL
332       outval = count >> 4;
333       PUT_OUTVAL
334       outval = count << 4;
335       goto check_colpen_on_out1;
336     } else if (count <= 0xFFFF) {
337       outval = (0xF << 4) | 0x4;
338       PUT_OUTVAL
339       outval = count >> 8;
340       PUT_OUTVAL
341       outval = count;
342       PUT_OUTVAL
343       goto check_colpen_on_out0;
344     } else if (count <= 0xFFFFF) {
345       outval = (0xF << 4) | 0x5;
346       PUT_OUTVAL
347       outval = count >> 12;
348       PUT_OUTVAL
349       outval = count >> 4;
350       PUT_OUTVAL
351       outval = count << 4;
352       goto check_colpen_on_out1;
353     } else if (count <= 0xFFFFFF) {
354       outval = (0xF << 4) | 0x6;
355       PUT_OUTVAL
356       outval = count >> 16;
357       PUT_OUTVAL
358       outval = count >> 8;
359       PUT_OUTVAL
360       outval = count;
361       PUT_OUTVAL
362       goto check_colpen_on_out0;
363     } else if (count <= 0xFFFFFFF) {
364       outval = (0xF << 4) | 0x7;
365       PUT_OUTVAL
366       outval = count >> 20;
367       PUT_OUTVAL
368       outval = count >> 12;
369       PUT_OUTVAL
370       outval = count >> 4;
371       PUT_OUTVAL
372       outval = count << 4;
373       goto check_colpen_on_out1;
374     } else {
375       buf_in[buf_in_len - 1] = save;
376       return 0;
377     }
378   } else {
379     outval = tone << 4;
380     GET_INVAL
381     /*goto check_colpen_on_out1;*/
382   }
383 
384 check_colpen_on_out1:
385   incol__              = inval & colmask;
386   if (incol__) incol__ = 0x10;
387   if (incol__ == lastcol__) goto check_tone_on_out1;
388   lastcol__ = incol__;
389   if (!remain) goto end_toonz1_encoding_on_out1;
390 
391   outval |= 0xF;
392   PUT_OUTVAL
393   outval = 0x8 << 4;
394 
395 check_tone_on_out1:
396   tone = inval & maxtone;
397   if (tone == maxtone) {
398     lastval    = inval;
399     prevremain = remain;
400     do
401       GET_INVAL
402     while (inval == lastval);
403     count = prevremain - remain - 1;
404     outval |= 0xF;
405     PUT_OUTVAL
406     if (count <= 0xF)
407       if (count == 0) {
408         outval = 0x0 << 4;
409         goto check_colpen_on_out1;
410       } else {
411         outval = (0x1 << 4) | count;
412         PUT_OUTVAL
413         goto check_colpen_on_out0;
414       }
415     else if (count <= 0xFF) {
416       outval = (0x2 << 4) | (count >> 4);
417       PUT_OUTVAL
418       outval = count << 4;
419       goto check_colpen_on_out1;
420     } else if (count <= 0xFFF) {
421       outval = (0x3 << 4) | (count >> 8);
422       PUT_OUTVAL
423       outval = count;
424       PUT_OUTVAL
425       goto check_colpen_on_out0;
426     } else if (count <= 0xFFFF) {
427       outval = (0x4 << 4) | (count >> 12);
428       PUT_OUTVAL
429       outval = count >> 4;
430       PUT_OUTVAL
431       outval = count << 4;
432       goto check_colpen_on_out1;
433     } else if (count <= 0xFFFFF) {
434       outval = (0x5 << 4) | (count >> 16);
435       PUT_OUTVAL
436       outval = count >> 8;
437       PUT_OUTVAL
438       outval = count;
439       PUT_OUTVAL
440       goto check_colpen_on_out0;
441     } else if (count <= 0xFFFFFF) {
442       outval = (0x6 << 4) | (count >> 20);
443       PUT_OUTVAL
444       outval = count >> 12;
445       PUT_OUTVAL
446       outval = count >> 4;
447       PUT_OUTVAL
448       outval = count << 4;
449       goto check_colpen_on_out1;
450     } else if (count <= 0xFFFFFFF) {
451       outval = (0x7 << 4) | (count >> 24);
452       PUT_OUTVAL
453       outval = count >> 16;
454       PUT_OUTVAL
455       outval = count >> 8;
456       PUT_OUTVAL
457       outval = count;
458       PUT_OUTVAL
459       goto check_colpen_on_out0;
460     } else {
461       buf_in[buf_in_len - 1] = save;
462       return 0;
463     }
464   } else {
465     outval |= tone;
466     PUT_OUTVAL
467     GET_INVAL
468     goto check_colpen_on_out0;
469   }
470 
471 end_toonz1_encoding_on_out0:
472   if ((save & colmask) != (in[-2] & colmask)) {
473     outval = 0xF8;
474     PUT_OUTVAL
475   }
476   outval = 0xFF;
477   PUT_OUTVAL
478   outval = 0xF0 | save & 0xF;
479   PUT_OUTVAL
480   buf_in[buf_in_len - 1] = save;
481   return out - buf_out;
482 
483 end_toonz1_encoding_on_out1:
484   if ((save & colmask) != (in[-2] & colmask)) {
485     outval |= 0xF;
486     PUT_OUTVAL
487     outval = 0x80;
488   }
489   outval |= 0xF;
490   PUT_OUTVAL
491   outval = 0xFF;
492   PUT_OUTVAL
493   outval = (save & 0xF) << 4;
494   PUT_OUTVAL
495   buf_in[buf_in_len - 1] = save;
496   return out - buf_out;
497 }
498 
499 /*---------------------------------------------------------------------------*/
500 
501 int tzr_encode_cm24_2_1_1 (ULONG *buf_in, int buf_in_len,
502                            UCHAR  *buf_out)
503 {
504   int count, prevremain, remain;
505   UINT inval, outval;
506   UINT lastval, lastcol__;
507   UINT colmask, maxtone;
508   UINT incol__, tone;
509   ULONG *in, save;
510   UCHAR *out;
511 
512   maxtone = 0xFF;
513   colmask = 0x0FF00;
514 
515   remain    = buf_in_len;
516   lastval   = maxtone;
517   lastcol__ = 0;
518 
519   in  = buf_in;
520   out = buf_out;
521 
522   if (buf_in_len <= 1) {
523     if (buf_in_len < 0) return 0;
524     if (buf_in_len == 0) {
525       outval = 0xFFFF;
526       PUT_OUTVAL
527       outval = 0xFE;
528       PUT_OUTVAL
529     } else {
530       GET_INVAL
531       if (inval & colmask) {
532         outval = 0xF8;
533         PUT_OUTVAL
534       }
535       outval = 0xFF;
536       PUT_OUTVAL
537       if ((inval & 0xF) == 0xF) inval--;
538       outval = 0xF0 | inval & 0xF;
539       PUT_OUTVAL
540       outval = (inval & 0xF0) >> 4;
541     }
542     return out - buf_out;
543   }
544 
545   save                   = buf_in[buf_in_len - 1];
546   buf_in[buf_in_len - 1] = buf_in[buf_in_len - 2] ^ colmask;
547 
548   GET_INVAL
549 
550 check_colpen_on_out0:
551   incol__              = inval & colmask;
552   if (incol__) incol__ = 0x100;
553   if (incol__ == lastcol__) goto check_tone_on_out0;
554   lastcol__ = incol__;
555   if (!remain) goto end_toonz1_encoding_and_save_on_out0;
556 
557   outval = 0xFF;
558   PUT_OUTVAL
559   outval = 0x8 << 4;
560   goto check_tone_on_out1;
561 
562 check_tone_on_out0:
563   tone = inval & maxtone;
564   if (tone == maxtone) {
565     lastval    = inval;
566     prevremain = remain;
567     do
568       GET_INVAL
569     while (inval == lastval);
570     count = prevremain - remain - 1;
571     if (count <= 0xF)
572       if (count == 0) {
573         outval = 0xFF;
574         PUT_OUTVAL
575         outval = 0x0 << 4;
576         goto check_colpen_on_out1;
577       } else {
578         outval = 0xFF;
579         PUT_OUTVAL
580         outval = (0x1 << 4) | count;
581         PUT_OUTVAL
582         goto check_colpen_on_out0;
583       }
584     else if (count <= 0xFF) {
585       outval = 0xFF;
586       PUT_OUTVAL
587       outval = (0x2 << 4) | (count >> 4);
588       PUT_OUTVAL
589       outval = (count & 0xF) << 4;
590       goto check_colpen_on_out1;
591     } else if (count <= 0xFFF) {
592       outval = 0xFF;
593       PUT_OUTVAL
594       outval = (0x3 << 4) | (count >> 8);
595       PUT_OUTVAL
596       outval = count & 0xFF;
597       PUT_OUTVAL
598       goto check_colpen_on_out0;
599     } else if (count <= 0xFFFF) {
600       outval = 0xFF;
601       PUT_OUTVAL
602       outval = (0x4 << 4) | (count >> 12);
603       PUT_OUTVAL
604       outval = (count & 0xFF0) >> 4;
605       PUT_OUTVAL
606       outval = (count & 0xF) << 4;
607       goto check_colpen_on_out1;
608     } else if (count <= 0xFFFFF) {
609       outval = 0xFF;
610       PUT_OUTVAL
611       outval = (0x5 << 4) | (count >> 16);
612       PUT_OUTVAL
613       outval = (count & 0xFF0) >> 4;
614       PUT_OUTVAL
615       outval = (count & 0xFF000) >> 12;
616       PUT_OUTVAL
617       goto check_colpen_on_out0;
618     } else if (count <= 0xFFFFFF) {
619       outval = 0xFF;
620       PUT_OUTVAL
621       outval = (0x6 << 4) | (count >> 20);
622       PUT_OUTVAL
623       outval = (count & 0xFF0) >> 4;
624       PUT_OUTVAL
625       outval = (count & 0xFF000) >> 12;
626       PUT_OUTVAL
627       outval = (count & 0xF00000) >> 16;
628       goto check_colpen_on_out1;
629     } else if (count <= 0xFFFFFFF) {
630       outval = 0xFF;
631       PUT_OUTVAL
632       outval = (0x7 << 4) | (count >> 24);
633       PUT_OUTVAL
634       outval = (count & 0xFF0) >> 4;
635       PUT_OUTVAL
636       outval = (count & 0xFF000) >> 12;
637       PUT_OUTVAL
638       outval = (count & 0xFF00000) >> 20;
639       PUT_OUTVAL
640       goto check_colpen_on_out0;
641     } else {
642       buf_in[buf_in_len - 1] = save;
643       return 0;
644     }
645   } else {
646     /*if ((tone & 0xF)==0xF) tone--;*/
647     outval = (((tone & 0xF) << 4) | ((tone & 0xF0)) >> 4);
648     PUT_OUTVAL
649     GET_INVAL
650     goto check_colpen_on_out0;
651   }
652 
653 check_colpen_on_out1:
654   incol__              = inval & colmask;
655   if (incol__) incol__ = 0x100;
656   if (incol__ == lastcol__) goto check_tone_on_out1;
657   lastcol__ = incol__;
658   if (!remain) goto end_toonz1_encoding_and_save_on_out1;
659 
660   outval |= 0xF;
661   PUT_OUTVAL
662   outval = (0xF << 4) | 0x8;
663   PUT_OUTVAL
664   goto check_tone_on_out0;
665 
666 check_tone_on_out1:
667   tone = inval & maxtone;
668   if (tone == maxtone) {
669     lastval    = inval;
670     prevremain = remain;
671     do
672       GET_INVAL
673     while (inval == lastval);
674     count = prevremain - remain - 1;
675     outval |= 0xF;
676     PUT_OUTVAL
677     outval = 0xF << 4;
678     if (count <= 0xF)
679       if (count == 0) {
680         outval |= 0x0;
681         PUT_OUTVAL
682         goto check_colpen_on_out0;
683       } else {
684         outval |= 0x1;
685         PUT_OUTVAL
686         outval = count << 4;
687         goto check_colpen_on_out1;
688       }
689     else if (count <= 0xFF) {
690       outval |= 0x2;
691       PUT_OUTVAL
692       outval = count;
693       PUT_OUTVAL
694       goto check_colpen_on_out0;
695     } else if (count <= 0xFFF) {
696       outval |= 0x3;
697       PUT_OUTVAL
698       outval = count >> 4;
699       PUT_OUTVAL
700       outval = (count & 0XF) << 4;
701       goto check_colpen_on_out1;
702     } else if (count <= 0xFFFF) {
703       outval |= 0x4;
704       PUT_OUTVAL
705       outval = count >> 8;
706       PUT_OUTVAL
707       outval = count & 0XFF;
708       PUT_OUTVAL
709       goto check_colpen_on_out0;
710     } else if (count <= 0xFFFFF) {
711       outval |= 0x5;
712       PUT_OUTVAL
713       outval = count >> 12;
714       PUT_OUTVAL
715       outval = (count & 0XFF0) >> 4;
716       PUT_OUTVAL
717       outval = (count & 0XF) << 4;
718       goto check_colpen_on_out1;
719     } else if (count <= 0xFFFFFF) {
720       outval |= 0x6;
721       PUT_OUTVAL
722       outval = count >> 16;
723       PUT_OUTVAL
724       outval = (count & 0XFF00) >> 8;
725       PUT_OUTVAL
726       outval = count & 0XFF;
727       PUT_OUTVAL
728       goto check_colpen_on_out0;
729     } else if (count <= 0xFFFFFFF) {
730       outval |= 0x7;
731       PUT_OUTVAL
732       outval = count >> 20;
733       PUT_OUTVAL
734       outval = (count & 0XFF000) >> 12;
735       PUT_OUTVAL
736       outval = (count & 0XFF0) >> 4;
737       PUT_OUTVAL
738       outval = (count & 0XF) << 4;
739       goto check_colpen_on_out1;
740     } else {
741       buf_in[buf_in_len - 1] = save;
742       return 0;
743     }
744   } else {
745     /*if ((tone & 0xF)==0xF) tone--;*/
746     outval |= tone & 0xF;
747     PUT_OUTVAL
748     outval = (tone & 0xF0);
749     /*PUT_OUTVAL*/
750     GET_INVAL
751     goto check_colpen_on_out1;
752   }
753 
754 end_toonz1_encoding_and_save_on_out0:
755   if ((save & colmask) != (in[-2] & colmask)) {
756     outval = 0xFF;
757     PUT_OUTVAL
758     outval = 0x8 << 4;
759     goto end_toonz1_encoding_on_out1;
760   }
761 
762 end_toonz1_encoding_on_out0:
763 
764   outval = 0xFF;
765   PUT_OUTVAL
766   outval = 0xFF;
767   PUT_OUTVAL
768   outval = (save & 0xF) << 4;
769   outval |= (save & 0xF0) >> 4;
770   PUT_OUTVAL
771   buf_in[buf_in_len - 1] = save;
772   return out - buf_out;
773 
774 end_toonz1_encoding_and_save_on_out1:
775   if ((save & colmask) != (in[-2] & colmask)) {
776     outval |= 0xF;
777     PUT_OUTVAL
778     outval = (0xF << 4) | 0x80;
779     PUT_OUTVAL
780     goto end_toonz1_encoding_on_out0;
781   }
782 end_toonz1_encoding_on_out1:
783 
784   outval |= 0xF;
785   PUT_OUTVAL
786   outval = 0xFF;
787   PUT_OUTVAL
788   outval = (0xF << 4) | (save & 0xF);
789   PUT_OUTVAL
790   outval = (save & 0xF0);
791   PUT_OUTVAL
792   buf_in[buf_in_len - 1] = save;
793   return out - buf_out;
794 
795 }
796 
797 /*---------------------------------------------------------------------------*/
798 
799 static TBOOL write_tzr_1_1_1 (char *filename, FILE *file, IMAGE *image)
800 {
801   int lx, ly, wrap, safe_bytes, enc, enclen_bytes, bytes, y;
802   USHORT *buffer, *line;
803   UCHAR *tzr_buf;
804 
805   lx           = image->pixmap.xsize;
806   ly           = image->pixmap.ysize;
807   wrap         = lx;
808   enclen_bytes = 2 + (lx > 8 * 1024);
809   safe_bytes   = enclen_bytes + tzr_safe_bytes_for_1_1_1_pixels(lx);
810   tzr_buf      = Tzr_buffer;
811   if (safe_bytes > Tzr_buffer_bytes) {
812     TREALLOC(tzr_buf, safe_bytes)
813     Tzr_buffer = tzr_buf;
814     if (Tzr_buffer)
815       Tzr_buffer_bytes = safe_bytes;
816     else {
817       Tzr_buffer_bytes = 0;
818       return FALSE;
819     }
820   }
821   buffer = image->pixmap.buffer;
822   for (line = buffer, y = 0; y < ly; line += wrap, y++) {
823     enc = tzr_encode_cm16_1_1_1(line, lx, tzr_buf + enclen_bytes);
824     if (enclen_bytes == 2) {
825       tzr_buf[0] = (enc >> 8) & 0xFF;
826       tzr_buf[1] = enc & 0xFF;
827     } else {
828       tzr_buf[0] = (enc >> 16) & 0xFF;
829       tzr_buf[1] = (enc >> 8) & 0xFF;
830       tzr_buf[2] = enc & 0xFF;
831     }
832     bytes = enclen_bytes + enc;
833     if (fwrite(tzr_buf, 1, bytes, file) != bytes) return FALSE;
834   }
835   return TRUE;
836 }
837 
838 /*---------------------------------------------------------------------------*/
839 
840 static TBOOL write_tzr_2_1_1 (char *filename, FILE *file, IMAGE *image)
841 {
842   int lx, ly, wrap, safe_bytes, enc, enclen_bytes, bytes, y;
843   ULONG *buffer, *line;
844   UCHAR *tzr_buf;
845 
846   lx           = image->pixmap.xsize;
847   ly           = image->pixmap.ysize;
848   wrap         = lx;
849   enclen_bytes = 2 + (lx > 8 * 1024);
850   safe_bytes   = enclen_bytes + tzr_safe_bytes_for_2_1_1_pixels(lx);
851   tzr_buf      = Tzr_buffer;
852   if (safe_bytes > Tzr_buffer_bytes) {
853     TREALLOC(tzr_buf, safe_bytes)
854     Tzr_buffer = tzr_buf;
855     if (Tzr_buffer)
856       Tzr_buffer_bytes = safe_bytes;
857     else {
858       Tzr_buffer_bytes = 0;
859       return FALSE;
860     }
861   }
862   buffer = (ULONG *)image->pixmap.buffer;
863   for (line = buffer, y = 0; y < ly; line += wrap, y++) {
864     int i;
865     enc = tzr_encode_cm24_2_1_1(line, lx, tzr_buf + enclen_bytes);
866     /*for (i=0; i<enc; i+=4)
867 printf("*** %x %x %x %x\n", tzr_buf[enclen_bytes+i],
868                     tzr_buf[enclen_bytes+i+1],
869                     tzr_buf[enclen_bytes+i+2],
870                     tzr_buf[enclen_bytes+i+3]); */
871     if (enclen_bytes == 2) {
872       tzr_buf[0] = (enc >> 8) & 0xFF;
873       tzr_buf[1] = enc & 0xFF;
874     } else {
875       tzr_buf[0] = (enc >> 16) & 0xFF;
876       tzr_buf[1] = (enc >> 8) & 0xFF;
877       tzr_buf[2] = enc & 0xFF;
878     }
879     bytes = enclen_bytes + enc;
880     if (fwrite(tzr_buf, 1, bytes, file) != bytes) return FALSE;
881   }
882   return TRUE;
883 }
884 
885 /*---------------------------------------------------------------------------*/
886 
887 static TBOOL write_tzr_header (char *filename, FILE *file, IMAGE *image,
888                                UINT tzr_type)
889 {
890   UCHAR buf[100 + TAGS_BUFLEN];
891   ULONG *buf32;
892   int lx, ly, img_offs = 0, img_offs_offs = 0, pos = 0;
893   double x_dpi, y_dpi, h_pos;
894 
895   switch (tzr_type) {
896     CASE 0x01010100 : __OR 0x02010100 : lx = image->pixmap.xsize;
897     ly                                     = image->pixmap.ysize;
898     buf32                                  = (ULONG *)buf;
899     *buf32                                 = TZR_MAGIC;
900     buf[4]                                 = (tzr_type >> 24) & 0xFF;
901     buf[5]                                 = (tzr_type >> 16) & 0xFF;
902     buf[6]                                 = (tzr_type >> 8) & 0xFF;
903     buf[7]                                 = tzr_type & 0xFF;
904     buf[8]                                 = (lx >> 16) & 0xFF;
905     buf[9]                                 = (lx >> 8) & 0xFF;
906     buf[10]                                = lx & 0xFF;
907     buf[11]                                = (ly >> 16) & 0xFF;
908     buf[12]                                = (ly >> 8) & 0xFF;
909     buf[13]                                = ly & 0xFF;
910     img_offs_offs                          = 14;
911     pos                                    = img_offs_offs + 3;
912 
913   DEFAULT:
914     assert(FALSE);
915   }
916   if (image->pixmap.x_dpi && image->pixmap.y_dpi) {
917     buf[pos]     = TAG_DPI;
918     buf[pos + 1] = 8 + 8;
919     x_dpi        = image->pixmap.x_dpi;
920     y_dpi        = image->pixmap.y_dpi;
921     DOUBLE_TO_BYTES(x_dpi, buf + pos + 2)
922     DOUBLE_TO_BYTES(y_dpi, buf + pos + 10)
923     pos += 1 + 1 + 8 + 8;
924   }
925   if (image->pixmap.h_pos) {
926     buf[pos]     = TAG_HPOS;
927     buf[pos + 1] = 8;
928     h_pos        = image->pixmap.h_pos;
929     DOUBLE_TO_BYTES(h_pos, buf + pos + 2)
930     pos += 1 + 1 + 8;
931   }
932   img_offs               = pos;
933   buf[img_offs_offs]     = (img_offs >> 16) & 0xFF;
934   buf[img_offs_offs + 1] = (img_offs >> 8) & 0xFF;
935   buf[img_offs_offs + 2] = img_offs & 0xFF;
936   if (fwrite(buf, 1, img_offs, file) != img_offs) return FALSE;
937 
938   return TRUE;
939 }
940 
941 /*---------------------------------------------------------------------------*/
942 
943 TBOOL img_write_tzr (char *filename, IMAGE *image)
944 {
945   FILE *file;
946   UCHAR buf[256];
947   UINT tzr_type;
948 
949   file = fopen(filename, "wb");
950   if (!file) return FALSE;
951   switch (image->type) {
952     CASE CMAPPED : tzr_type   = 0x01010100;
953     CASE CMAPPED24 : tzr_type = 0x02010100;
954   DEFAULT:
955     tmsg_error("bad image type for .tzr files");
956     goto error;
957   }
958   if (!write_tzr_header(filename, file, image, tzr_type)) goto error;
959   switch (tzr_type) {
960     CASE 0x01010100 : if (!write_tzr_1_1_1(filename, file, image)) goto error;
961     CASE 0x02010100 : if (!write_tzr_2_1_1(filename, file, image)) goto error;
962   DEFAULT:
963     goto error;
964   }
965   fclose(file);
966   return TRUE;
967 
968 error:
969   if (file) fclose(file);
970   return FALSE;
971 }
972 
973 /*---------------------------------------------------------------------------*/
974 
975 int tzr_decode_1_1_1_cm16 (UCHAR  *buf_in, int *buf_in_len,
976                            USHORT *buf_out)
977 {
978   UCHAR *in;
979   USHORT *out;
980   int count;
981   UINT inval, in0, in1;
982   UINT outval, maxtone, outval_maxtone;
983 
984 #define GET_IN0 (inval = *in++, in1 = inval & 0xF, in0 = inval >> 4)
985 
986   maxtone        = 0xF;
987   outval         = 0;
988   outval_maxtone = outval | maxtone;
989   count          = 0;
990 
991   in  = buf_in;
992   out = buf_out;
993 
994   goto start_from_in0;
995 
996 count_out_and_start_from_in0:
997   outval_maxtone         = outval | maxtone;
998   *out++                 = outval_maxtone;
999   while (count--) *out++ = outval_maxtone;
1000 
1001 start_from_in0:
1002   if (GET_IN0 == 0xF) {
1003     switch (in1) {
1004       CASE 0x0 : *out++ = outval | maxtone;
1005       goto start_from_in0;
1006 
1007       CASE 0x1 : count = GET_IN0;
1008       goto count_out_and_start_from_in1;
1009 
1010       CASE 0x2 : count = *in++;
1011       goto count_out_and_start_from_in0;
1012 
1013       CASE 0x3 : count = *in++ << 4;
1014       count += GET_IN0;
1015       goto count_out_and_start_from_in1;
1016 
1017       CASE 0x4 : count = *in++ << 8;
1018       count += *in++;
1019       goto count_out_and_start_from_in0;
1020 
1021       CASE 0x5 : count = *in++ << 12;
1022       count += *in++ << 4;
1023       count += GET_IN0;
1024       goto count_out_and_start_from_in1;
1025 
1026       CASE 0x6 : count = *in++ << 16;
1027       count += *in++ << 8;
1028       count += *in++;
1029       goto count_out_and_start_from_in0;
1030 
1031       CASE 0x7 : count = *in++ << 20;
1032       count += *in++ << 12;
1033       count += *in++ << 4;
1034       count += GET_IN0;
1035       goto count_out_and_start_from_in1;
1036 
1037       CASE 0x8 : outval ^= 0x10;
1038       goto start_from_in0;
1039 
1040       CASE 0xF : switch (GET_IN0) {
1041         CASE 0xE : CASE 0xF : *out++ = outval | in1;
1042       DEFAULT:
1043         goto rle_decoding_error;
1044       }
1045       goto end_rle_decoding;
1046 
1047     DEFAULT:
1048       goto rle_decoding_error;
1049     }
1050   } else {
1051     *out++ = outval | in0;
1052     goto start_from_in1;
1053   }
1054 
1055 count_out_and_start_from_in1:
1056   outval_maxtone         = outval | maxtone;
1057   *out++                 = outval_maxtone;
1058   while (count--) *out++ = outval_maxtone;
1059 
1060 start_from_in1:
1061   if (in1 == 0xF) {
1062     switch (GET_IN0) {
1063       CASE 0x0 : *out++ = outval | maxtone;
1064       goto start_from_in1;
1065 
1066       CASE 0x1 : count = in1;
1067       goto count_out_and_start_from_in0;
1068 
1069       CASE 0x2 : count = in1 << 4;
1070       count += GET_IN0;
1071       goto count_out_and_start_from_in1;
1072 
1073       CASE 0x3 : count = in1 << 8;
1074       count += *in++;
1075       goto count_out_and_start_from_in0;
1076 
1077       CASE 0x4 : count = in1 << 12;
1078       count += *in++ << 4;
1079       count += GET_IN0;
1080       goto count_out_and_start_from_in1;
1081 
1082       CASE 0x5 : count = in1 << 16;
1083       count += *in++ << 8;
1084       count += *in++;
1085       goto count_out_and_start_from_in0;
1086 
1087       CASE 0x6 : count = in1 << 20;
1088       count += *in++ << 12;
1089       count += *in++ << 4;
1090       count += GET_IN0;
1091       goto count_out_and_start_from_in1;
1092 
1093       CASE 0x7 : count = in1 << 24;
1094       count += *in++ << 16;
1095       count += *in++ << 8;
1096       count += *in++;
1097       goto count_out_and_start_from_in0;
1098 
1099       CASE 0x8 : outval ^= 0x10;
1100       goto start_from_in1;
1101 
1102       CASE 0xF : switch (in1) {
1103         CASE 0xE : CASE 0xF : *out++ = outval | *in++ >> 4;
1104       DEFAULT:
1105         goto rle_decoding_error;
1106       }
1107       goto end_rle_decoding;
1108 
1109     DEFAULT:
1110       return 0;
1111     }
1112   } else {
1113     *out++ = outval | in1;
1114     goto start_from_in0;
1115   }
1116 
1117 end_rle_decoding:
1118   if (buf_in_len) *buf_in_len = in - buf_in;
1119   return out - buf_out;
1120 
1121 rle_decoding_error:
1122   if (buf_in_len) *buf_in_len = 0;
1123   return 0;
1124 }
1125 
1126 /*---------------------------------------------------------------------------*/
1127 
1128 int tzr_decode_2_1_1_cm24 (UCHAR  *buf_in, int *buf_in_len,
1129                            ULONG *buf_out)
1130 {
1131   UCHAR *in;
1132   ULONG *out;
1133   int count;
1134   UINT inval, in0, in1, aux;
1135   UINT outval, maxtone, outval_maxtone;
1136 
1137 #define GET_IN0 (inval = *in++, in1 = inval & 0xF, in0 = inval >> 4)
1138 
1139   maxtone        = 0xFF;
1140   outval         = 0;
1141   outval_maxtone = outval | maxtone;
1142   count          = 0;
1143 
1144   in  = buf_in;
1145   out = buf_out;
1146 
1147   goto start_from_in0;
1148 
1149 count_out_and_start_from_in0:
1150   outval_maxtone         = outval | maxtone;
1151   *out++                 = outval_maxtone;
1152   while (count--) *out++ = outval_maxtone;
1153 start_from_in0:
1154   GET_IN0;
1155   if (inval == 0xFF) {
1156     GET_IN0;
1157     switch (in0) {
1158       CASE 0x0 : *out++ = outval | maxtone;
1159       goto start_from_in1;
1160 
1161       CASE 0x1 : count = in1;
1162       goto count_out_and_start_from_in0;
1163 
1164       CASE 0x2 : count = in1 << 4;
1165       count += GET_IN0;
1166       goto count_out_and_start_from_in1;
1167 
1168       CASE 0x3 : count = in1 << 8;
1169       count += *in++;
1170       goto count_out_and_start_from_in0;
1171 
1172       CASE 0x4 : count = in1 << 12;
1173       count += *in++ << 4;
1174       count += GET_IN0;
1175       goto count_out_and_start_from_in1;
1176 
1177       CASE 0x5 : count = in1 << 16;
1178       count += *in++ << 8;
1179       count += *in++;
1180       goto count_out_and_start_from_in0;
1181 
1182       CASE 0x6 : count = in1 << 20;
1183       count += *in++ << 12;
1184       count += *in++ << 4;
1185       count += GET_IN0;
1186       goto count_out_and_start_from_in1;
1187 
1188       CASE 0x7 : count = in1 << 24;
1189       count += *in++ << 16;
1190       count += *in++ << 8;
1191       count += *in++;
1192       goto count_out_and_start_from_in0;
1193 
1194       CASE 0x8 : outval ^= 0x100;
1195       goto start_from_in1;
1196 
1197       CASE 0xF : switch (in1) {
1198         CASE 0xE : CASE 0xF : GET_IN0;
1199         *out++ = outval | ((in1 << 4) | in0);
1200       DEFAULT:
1201         goto rle_decoding_error;
1202       }
1203       goto end_rle_decoding;
1204 
1205     DEFAULT:
1206       goto rle_decoding_error;
1207     }
1208   } else {
1209     *out++ = outval | ((in1 << 4) | in0);
1210     goto start_from_in0;
1211   }
1212 
1213 count_out_and_start_from_in1:
1214   outval_maxtone         = outval | maxtone;
1215   *out++                 = outval_maxtone;
1216   while (count--) *out++ = outval_maxtone;
1217 
1218 start_from_in1:
1219   aux = in1;
1220   GET_IN0;
1221   if (in0 == 0xF && aux == 0xF) {
1222     switch (in1) {
1223       CASE 0x0 : *out++ = outval | maxtone;
1224       goto start_from_in0;
1225 
1226       CASE 0x1 : GET_IN0;
1227       count = in0;
1228       goto count_out_and_start_from_in1;
1229 
1230       CASE 0x2 : count = *in++;
1231       goto count_out_and_start_from_in0;
1232 
1233       CASE 0x3 : count = *in++ << 4;
1234       count += GET_IN0;
1235       goto count_out_and_start_from_in1;
1236 
1237       CASE 0x4 : count = *in++ << 8;
1238       count += *in++;
1239       goto count_out_and_start_from_in0;
1240 
1241       CASE 0x5 : count = *in++ << 12;
1242       count += *in++ << 4;
1243       count += GET_IN0;
1244       goto count_out_and_start_from_in1;
1245 
1246       CASE 0x6 : count = *in++ << 16;
1247       count += *in++ << 8;
1248       count += *in++;
1249       goto count_out_and_start_from_in0;
1250 
1251       CASE 0x7 : count = *in++ << 20;
1252       count += *in++ << 12;
1253       count += *in++ << 4;
1254       count += GET_IN0;
1255       goto count_out_and_start_from_in1;
1256 
1257       CASE 0x8 : outval ^= 0x100;
1258       goto start_from_in0;
1259 
1260       CASE 0xF : switch (GET_IN0) {
1261         UINT aux;
1262         CASE 0xE : CASE 0xF : aux = in1;
1263         GET_IN0;
1264 
1265         *out++ = outval | (aux | (in0 << 4));
1266       DEFAULT:
1267         goto rle_decoding_error;
1268       }
1269       goto end_rle_decoding;
1270 
1271     DEFAULT:
1272       return 0;
1273     }
1274   } else {
1275     *out++ = outval | ((in0 << 4) | aux);
1276     goto start_from_in1;
1277   }
1278 
1279 end_rle_decoding:
1280   if (buf_in_len) *buf_in_len = in - buf_in;
1281   return out - buf_out;
1282 
1283 rle_decoding_error:
1284   if (buf_in_len) *buf_in_len = 0;
1285   return 0;
1286 }
1287 
1288 /*---------------------------------------------------------------------------*/
1289 
1290 static TBOOL read_tzr_1_1_1 (char *filename, FILE *file, IMAGE *image,
1291                              int img_offs, TBOOL cmapped)
1292 {
1293   int lx, ly, wrap, y, x;
1294   USHORT *buf_cm, *line_cm;
1295   LPIXEL *buf_rgbm, *line_rgbm;
1296   int safe_bytes, enclen_bytes, enclen, dec, tzr_dec;
1297   UCHAR *tzr_buf;
1298   UINT tone, color;
1299   LPIXEL val;
1300 
1301   if (fseek(file, img_offs, SEEK_SET)) {
1302     tmsg_error("inconsistent data in %s (seek failed)", filename);
1303     return FALSE;
1304   }
1305   lx           = image->pixmap.xsize;
1306   ly           = image->pixmap.ysize;
1307   wrap         = lx;
1308   enclen_bytes = 2 + (lx > 8 * 1024);
1309   safe_bytes   = enclen_bytes + tzr_safe_bytes_for_1_1_1_pixels(lx);
1310   tzr_buf      = Tzr_buffer;
1311   if (safe_bytes > Tzr_buffer_bytes) {
1312     TREALLOC(tzr_buf, safe_bytes)
1313     Tzr_buffer = tzr_buf;
1314     if (Tzr_buffer)
1315       Tzr_buffer_bytes = safe_bytes;
1316     else {
1317       Tzr_buffer_bytes = 0;
1318       return FALSE;
1319     }
1320   }
1321   if (cmapped) {
1322     buf_cm = image->pixmap.buffer;
1323     for (line_cm = buf_cm, y = 0; y < ly; line_cm += wrap, y++) {
1324       READ_BYTES_OR_ERROR(tzr_buf, enclen_bytes, file)
1325       if (enclen_bytes == 2)
1326         enclen = tzr_buf[0] << 8 | tzr_buf[1];
1327       else
1328         enclen = tzr_buf[0] << 16 | tzr_buf[1] << 8 | tzr_buf[2];
1329       READ_BYTES_OR_ERROR(tzr_buf, enclen, file)
1330       dec = tzr_decode_1_1_1_cm16(tzr_buf, &tzr_dec, line_cm);
1331       assert(dec == lx);
1332       assert(tzr_dec == enclen);
1333     }
1334   } else {
1335     buf_rgbm = (LPIXEL *)image->pixmap.buffer;
1336     for (line_rgbm = buf_rgbm, y = 0; y < ly; line_rgbm += wrap, y++) {
1337       READ_BYTES_OR_ERROR(tzr_buf, enclen_bytes, file)
1338       if (enclen_bytes == 2)
1339         enclen = tzr_buf[0] << 8 | tzr_buf[1];
1340       else
1341         enclen = tzr_buf[0] << 16 | tzr_buf[1] << 8 | tzr_buf[2];
1342       READ_BYTES_OR_ERROR(tzr_buf, enclen, file)
1343       line_cm = (USHORT *)line_rgbm;
1344       dec     = tzr_decode_1_1_1_cm16(tzr_buf, &tzr_dec, line_cm);
1345       assert(dec == lx);
1346       assert(tzr_dec == enclen);
1347       for (x = lx - 1; x >= 0; x--) {
1348         tone  = line_cm[x] & 0xF;
1349         color = line_cm[x] & 0x10;
1350         if (color) {
1351           val.r = val.g = val.b = tone * 8;
1352           val.m                 = 255;
1353         } else {
1354           val.r = val.g = val.b = 0;
1355           val.m                 = ~(tone * 17);
1356         }
1357         line_rgbm[x] = val;
1358       }
1359     }
1360   }
1361   return TRUE;
1362 
1363 error:
1364   return FALSE;
1365 }
1366 
1367 /*---------------------------------------------------------------------------*/
1368 void vaffa(void)
1369 {}
1370 
1371 static TBOOL read_tzr_2_1_1 (char *filename, FILE *file, IMAGE *image,
1372                              int img_offs, TBOOL cmapped)
1373 {
1374   int lx, ly, wrap, y, x;
1375   ULONG *buf_cm, *line_cm;
1376   LPIXEL *buf_rgbm, *line_rgbm;
1377   int safe_bytes, enclen_bytes, enclen, dec, tzr_dec;
1378   UCHAR *tzr_buf;
1379   UINT tone, color;
1380   LPIXEL val;
1381 
1382   if (fseek(file, img_offs, SEEK_SET)) {
1383     tmsg_error("inconsistent data in %s (seek failed)", filename);
1384     return FALSE;
1385   }
1386   lx           = image->pixmap.xsize;
1387   ly           = image->pixmap.ysize;
1388   wrap         = lx;
1389   enclen_bytes = 2 + (lx > 8 * 1024);
1390   safe_bytes   = enclen_bytes + tzr_safe_bytes_for_2_1_1_pixels(lx);
1391   tzr_buf      = Tzr_buffer;
1392   if (safe_bytes > Tzr_buffer_bytes) {
1393     TREALLOC(tzr_buf, safe_bytes)
1394     Tzr_buffer = tzr_buf;
1395     if (Tzr_buffer)
1396       Tzr_buffer_bytes = safe_bytes;
1397     else {
1398       Tzr_buffer_bytes = 0;
1399       return FALSE;
1400     }
1401   }
1402   if (cmapped) {
1403     int i;
1404     buf_cm = (ULONG *)image->pixmap.buffer;
1405     for (line_cm = buf_cm, y = 0; y < ly; line_cm += wrap, y++) {
1406       READ_BYTES_OR_ERROR(tzr_buf, enclen_bytes, file)
1407       if (enclen_bytes == 2)
1408         enclen = tzr_buf[0] << 8 | tzr_buf[1];
1409       else
1410         enclen = tzr_buf[0] << 16 | tzr_buf[1] << 8 | tzr_buf[2];
1411       READ_BYTES_OR_ERROR(tzr_buf, enclen, file)
1412       dec = tzr_decode_2_1_1_cm24(tzr_buf, &tzr_dec, line_cm);
1413       assert(dec == lx);
1414       assert(tzr_dec == enclen);
1415     }
1416   } else {
1417     buf_rgbm = (LPIXEL *)image->pixmap.buffer;
1418     for (line_rgbm = buf_rgbm, y = 0; y < ly; line_rgbm += wrap, y++) {
1419       READ_BYTES_OR_ERROR(tzr_buf, enclen_bytes, file)
1420       if (enclen_bytes == 2)
1421         enclen = tzr_buf[0] << 8 | tzr_buf[1];
1422       else
1423         enclen = tzr_buf[0] << 16 | tzr_buf[1] << 8 | tzr_buf[2];
1424       READ_BYTES_OR_ERROR(tzr_buf, enclen, file)
1425       line_cm = (ULONG *)line_rgbm;
1426       dec     = tzr_decode_2_1_1_cm24(tzr_buf, &tzr_dec, line_cm);
1427       assert(dec == lx);
1428       assert(tzr_dec == enclen);
1429       for (x = lx - 1; x >= 0; x--) {
1430         tone  = line_cm[x] & 0xFF;
1431         color = line_cm[x] & 0x100;
1432         if (color) {
1433           val.r = val.g = val.b = tone >> 1; /* ???? tone * 8;*/
1434           val.m                 = 255;
1435         } else {
1436           val.r = val.g = val.b = 0;
1437           val.m                 = ~(tone);
1438         }
1439         line_rgbm[x] = val;
1440       }
1441     }
1442   }
1443   return TRUE;
1444 
1445 error:
1446   return FALSE;
1447 }
1448 
1449 /*---------------------------------------------------------------------------*/
1450 
1451 static TBOOL read_region_tzr_1_1_1 (char *filename, FILE *file, IMAGE *image,
1452                                     int img_offs, TBOOL cmapped,
1453 				    INFO_REGION *region)
1454 {
1455   int reg_lx, reg_ly, full_lx, full_ly, wrap, y, x, skip, step, k, tmp_x;
1456   USHORT *buf_cm, *line_cm, *tmp_buf;
1457   LPIXEL *buf_rgbm, *line_rgbm;
1458   int safe_bytes, decline_bytes, enclen_bytes, enclen, dec, tzr_dec;
1459   UCHAR *tzr_buf;
1460   UINT tone, color;
1461   LPIXEL val;
1462 
1463   if (fseek(file, img_offs, SEEK_SET)) {
1464     tmsg_error("inconsistent data in %s (seek failed)", filename);
1465     return FALSE;
1466   }
1467   full_lx       = region->lx_in;
1468   wrap          = region->xsize;
1469   step          = region->step;
1470   enclen_bytes  = 2 + (full_lx > 8 * 1024);
1471   safe_bytes    = enclen_bytes + tzr_safe_bytes_for_1_1_1_pixels(full_lx);
1472   decline_bytes = full_lx * sizeof(USHORT);
1473   tzr_buf       = Tzr_buffer;
1474   if (safe_bytes + decline_bytes > Tzr_buffer_bytes) {
1475     TREALLOC(tzr_buf, safe_bytes + decline_bytes)
1476     Tzr_buffer = tzr_buf;
1477     if (Tzr_buffer)
1478       Tzr_buffer_bytes = safe_bytes + decline_bytes;
1479     else {
1480       Tzr_buffer_bytes = 0;
1481       return FALSE;
1482     }
1483   }
1484   tmp_buf = (USHORT *)(tzr_buf + safe_bytes);
1485   for (y = 0; y < region->startScanRow; y++) {
1486     READ_BYTES_OR_ERROR(tzr_buf, enclen_bytes, file)
1487     if (enclen_bytes == 2)
1488       enclen = tzr_buf[0] << 8 | tzr_buf[1];
1489     else
1490       enclen = tzr_buf[0] << 16 | tzr_buf[1] << 8 | tzr_buf[2];
1491     if (fseek(file, enclen, SEEK_CUR)) goto error;
1492   }
1493   buf_cm    = image->pixmap.buffer;
1494   line_cm   = buf_cm + region->x_offset + region->y_offset * wrap;
1495   buf_rgbm  = (LPIXEL *)image->pixmap.buffer;
1496   line_rgbm = buf_rgbm + region->x_offset + region->y_offset * wrap;
1497   for (y = 0; y < region->scanNrow; y++, line_cm += wrap, line_rgbm += wrap) {
1498     READ_BYTES_OR_ERROR(tzr_buf, enclen_bytes, file)
1499     if (enclen_bytes == 2)
1500       enclen = tzr_buf[0] << 8 | tzr_buf[1];
1501     else
1502       enclen = tzr_buf[0] << 16 | tzr_buf[1] << 8 | tzr_buf[2];
1503     READ_BYTES_OR_ERROR(tzr_buf, enclen, file)
1504     dec = tzr_decode_1_1_1_cm16(tzr_buf, &tzr_dec, tmp_buf);
1505     assert(dec == full_lx);
1506     assert(tzr_dec == enclen);
1507     if (cmapped)
1508       for (tmp_x = region->x1, k = 0; k < region->scanNcol;
1509            k++, tmp_x += step) {
1510         line_cm[k] = tmp_buf[tmp_x];
1511       }
1512     else {
1513       for (tmp_x = region->x1, k = 0; k < region->scanNcol;
1514            k++, tmp_x += step) {
1515         tone  = tmp_buf[tmp_x] & 0xF;
1516         color = tmp_buf[tmp_x] & 0x10;
1517         if (color) {
1518           val.r = val.g = val.b = tone * 8;
1519           val.m                 = 255;
1520         } else {
1521           val.r = val.g = val.b = 0;
1522           val.m                 = ~(tone * 17);
1523         }
1524         line_rgbm[k] = val;
1525       }
1526     }
1527     if (y != region->scanNrow - 1)
1528       for (skip = 0; skip < step - 1; skip++) {
1529         READ_BYTES_OR_ERROR(tzr_buf, enclen_bytes, file)
1530         if (enclen_bytes == 2)
1531           enclen = tzr_buf[0] << 8 | tzr_buf[1];
1532         else
1533           enclen = tzr_buf[0] << 16 | tzr_buf[1] << 8 | tzr_buf[2];
1534         if (fseek(file, enclen, SEEK_CUR)) goto error;
1535       }
1536   }
1537   return TRUE;
1538 
1539 error:
1540   return FALSE;
1541 }
1542 
1543 /*---------------------------------------------------------------------------*/
1544 
1545 static TBOOL read_region_tzr_2_1_1 (char *filename, FILE *file, IMAGE *image,
1546                                     int img_offs, TBOOL cmapped,
1547 				    INFO_REGION *region)
1548 {
1549   int reg_lx, reg_ly, full_lx, full_ly, wrap, y, x, skip, step, k, tmp_x;
1550   ULONG *buf_cm, *line_cm, *tmp_buf;
1551   LPIXEL *buf_rgbm, *line_rgbm;
1552   int safe_bytes, decline_bytes, enclen_bytes, enclen, dec, tzr_dec;
1553   UCHAR *tzr_buf;
1554   UINT tone, color;
1555   LPIXEL val;
1556 
1557   if (fseek(file, img_offs, SEEK_SET)) {
1558     tmsg_error("inconsistent data in %s (seek failed)", filename);
1559     return FALSE;
1560   }
1561   full_lx       = region->lx_in;
1562   wrap          = region->xsize;
1563   step          = region->step;
1564   enclen_bytes  = 2 + (full_lx > 8 * 1024);
1565   safe_bytes    = enclen_bytes + tzr_safe_bytes_for_2_1_1_pixels(full_lx);
1566   decline_bytes = full_lx * sizeof(ULONG);
1567   tzr_buf       = Tzr_buffer;
1568   if (safe_bytes + decline_bytes > Tzr_buffer_bytes) {
1569     TREALLOC(tzr_buf, safe_bytes + decline_bytes)
1570     Tzr_buffer = tzr_buf;
1571     if (Tzr_buffer)
1572       Tzr_buffer_bytes = safe_bytes + decline_bytes;
1573     else {
1574       Tzr_buffer_bytes = 0;
1575       return FALSE;
1576     }
1577   }
1578   tmp_buf = (ULONG *)(tzr_buf + safe_bytes);
1579   for (y = 0; y < region->startScanRow; y++) {
1580     READ_BYTES_OR_ERROR(tzr_buf, enclen_bytes, file)
1581     if (enclen_bytes == 2)
1582       enclen = tzr_buf[0] << 8 | tzr_buf[1];
1583     else
1584       enclen = tzr_buf[0] << 16 | tzr_buf[1] << 8 | tzr_buf[2];
1585     if (fseek(file, enclen, SEEK_CUR)) goto error;
1586   }
1587   buf_cm    = (ULONG *)image->pixmap.buffer;
1588   line_cm   = buf_cm + region->x_offset + region->y_offset * wrap;
1589   buf_rgbm  = (LPIXEL *)image->pixmap.buffer;
1590   line_rgbm = buf_rgbm + region->x_offset + region->y_offset * wrap;
1591   for (y = 0; y < region->scanNrow; y++, line_cm += wrap, line_rgbm += wrap) {
1592     READ_BYTES_OR_ERROR(tzr_buf, enclen_bytes, file)
1593     if (enclen_bytes == 2)
1594       enclen = tzr_buf[0] << 8 | tzr_buf[1];
1595     else
1596       enclen = tzr_buf[0] << 16 | tzr_buf[1] << 8 | tzr_buf[2];
1597     READ_BYTES_OR_ERROR(tzr_buf, enclen, file)
1598     dec = tzr_decode_2_1_1_cm24(tzr_buf, &tzr_dec, tmp_buf);
1599     assert(dec == full_lx);
1600     assert(tzr_dec == enclen);
1601     if (cmapped)
1602       for (tmp_x = region->x1, k = 0; k < region->scanNcol;
1603            k++, tmp_x += step) {
1604         line_cm[k] = tmp_buf[tmp_x];
1605       }
1606     else {
1607       for (tmp_x = region->x1, k = 0; k < region->scanNcol;
1608            k++, tmp_x += step) {
1609         tone  = tmp_buf[tmp_x] & 0xFF;
1610         color = tmp_buf[tmp_x] & 0x100;
1611         if (color) {
1612           val.r = val.g = val.b = tone >> 1 /* ???? tone * 8  */;
1613           val.m                 = 255;
1614         } else {
1615           val.r = val.g = val.b = 0;
1616           val.m                 = ~(tone);
1617         }
1618         line_rgbm[k] = val;
1619       }
1620     }
1621     if (y != region->scanNrow - 1)
1622       for (skip = 0; skip < step - 1; skip++) {
1623         READ_BYTES_OR_ERROR(tzr_buf, enclen_bytes, file)
1624         if (enclen_bytes == 2)
1625           enclen = tzr_buf[0] << 8 | tzr_buf[1];
1626         else
1627           enclen = tzr_buf[0] << 16 | tzr_buf[1] << 8 | tzr_buf[2];
1628         if (fseek(file, enclen, SEEK_CUR)) goto error;
1629       }
1630   }
1631   return TRUE;
1632 
1633 error:
1634   return FALSE;
1635 }
1636 
1637 /*---------------------------------------------------------------------------*/
1638 
1639 static TBOOL read_tzr_header (char *filename, FILE *file, IMAGE *image,
1640                               UINT *tzr_type, int *p_img_offs, TBOOL cmapped,
1641 			      TBOOL read_tags)
1642 {
1643   UCHAR buf[TAGS_BUFLEN];
1644   int lx, ly, img_offs = 0;
1645   int tags_len, file_pos, pos;
1646   double x_dpi, y_dpi, h_pos;
1647 
1648   *tzr_type = 0;
1649   READ_BYTES_OR_ERROR(buf, 8, file)
1650   if (*(ULONG *)buf != TZR_MAGIC) {
1651     tmsg_error("bad magic number in %s", filename);
1652     goto error;
1653   }
1654   switch (buf[4 + 0]) {
1655     CASE 1 : switch (buf[4 + 1]) {
1656       CASE 1 : switch (buf[4 + 2]) {
1657         CASE 1 : *tzr_type = 0x01010100;
1658       DEFAULT:
1659         tmsg_error("unsupported file type (%d %d %d) in %s", buf[4 + 0],
1660                    buf[4 + 1], buf[4 + 2], filename);
1661         goto error;
1662       }
1663     }
1664     CASE 2 : switch (buf[4 + 1]) {
1665       CASE 1 : switch (buf[4 + 2]) {
1666         CASE 1 : *tzr_type = 0x02010100;
1667       DEFAULT:
1668         tmsg_error("unsupported file type (%d %d %d) in %s", buf[4 + 0],
1669                    buf[4 + 1], buf[4 + 2], filename);
1670         goto error;
1671       }
1672     DEFAULT:
1673       tmsg_error("unsupported file type (%d %d) in %s", buf[4 + 0], buf[4 + 1],
1674                  filename);
1675       goto error;
1676     }
1677   DEFAULT:
1678     tmsg_error("unsupported file type (%d) in %s", buf[4 + 0], filename);
1679     goto error;
1680   }
1681   switch (*tzr_type) {
1682     CASE 0x01010100 : __OR 0x02010100 : READ_BYTES_OR_ERROR(buf, 9, file) lx =
1683                                             buf[0] << 16 | buf[1] << 8 | buf[2];
1684     ly       = buf[3] << 16 | buf[4] << 8 | buf[5];
1685     img_offs = buf[6] << 16 | buf[7] << 8 | buf[8];
1686     if (*tzr_type == 0x01010100) {
1687       if (cmapped) {
1688         image->type      = CMAPPED;
1689         image->cmap.info = Tcm_new_default_info;
1690       } else
1691         image->type = RGB;
1692     } else {
1693       if (cmapped) {
1694         image->type      = CMAPPED24;
1695         image->cmap.info = Tcm_24_default_info;
1696       } else
1697         image->type = RGB;
1698     }
1699     image->pixmap.xsize   = lx;
1700     image->pixmap.ysize   = ly;
1701     image->pixmap.xSBsize = lx;
1702     image->pixmap.ySBsize = ly;
1703 
1704   DEFAULT:
1705     assert(0);
1706   }
1707   if (read_tags) {
1708     file_pos = ftell(file);
1709     tags_len = img_offs - file_pos;
1710     if (tags_len > TAGS_BUFLEN) {
1711       tmsg_error("tags section of %s too long", filename);
1712       goto error;
1713     }
1714     if (tags_len) READ_BYTES_OR_ERROR(buf, tags_len, file)
1715     pos = 0;
1716     while (pos < tags_len) {
1717       switch (buf[pos]) {
1718         CASE TAG_DPI : if (buf[pos + 1] != 8 + 8) goto unknown_tag;
1719         BYTES_TO_DOUBLE(buf + pos + 2, x_dpi)
1720         BYTES_TO_DOUBLE(buf + pos + 10, y_dpi)
1721         image->pixmap.x_dpi = x_dpi;
1722         image->pixmap.y_dpi = y_dpi;
1723         pos += 1 + 1 + 8 + 8;
1724 
1725         CASE TAG_HPOS : if (buf[pos + 1] != 8) goto unknown_tag;
1726         BYTES_TO_DOUBLE(buf + pos + 2, h_pos)
1727         image->pixmap.h_pos = h_pos;
1728         pos += 1 + 1 + 8;
1729 
1730       DEFAULT:
1731       unknown_tag:
1732         if (buf[pos] >= 128)
1733           pos += 1 + 2 + (buf[pos + 1] << 8 | buf[pos + 2]);
1734         else
1735           pos += 1 + 1 + buf[pos + 1];
1736       }
1737     }
1738   }
1739   *p_img_offs = img_offs;
1740   return TRUE;
1741 
1742 error:
1743   return FALSE;
1744 }
1745 
1746 /*===========================================================================*/
1747 
1748 void next_img_read_tzr_cmapped (void)
1749 {
1750   Next_img_read_tzr_cmapped = TRUE;
1751 }
1752 
1753 /*---------------------------------------------------------------------------*/
1754 
1755 IMAGE *img_read_tzr (char *filename)
1756 {
1757   FILE *file;
1758   IMAGE *image;
1759   UINT tzr_type;
1760   int lx, ly, img_offs;
1761 
1762   SET_READ_CMAPPED
1763 
1764   file = fopen(filename, "rb");
1765   if (!file) return NIL;
1766   image = new_img();
1767   if (!image) goto error;
1768   if (!read_tzr_header(filename, file, image, &tzr_type, &img_offs,
1769                        Read_cmapped, TRUE))
1770     goto error;
1771   lx = image->pixmap.xsize;
1772   ly = image->pixmap.ysize;
1773   if (!allocate_pixmap(image, lx, ly)) goto error;
1774   switch (tzr_type) {
1775     CASE 0x01010100 : if (!read_tzr_1_1_1(filename, file, image, img_offs,
1776                                           Read_cmapped)) goto error;
1777 
1778     CASE 0x02010100 : if (!read_tzr_2_1_1(filename, file, image, img_offs,
1779                                           Read_cmapped)) goto error;
1780 
1781   DEFAULT:
1782     goto error;
1783   }
1784   fclose(file);
1785   return image;
1786 
1787 error:
1788   if (image) free_img(image);
1789   if (file) fclose(file);
1790   return NIL;
1791 }
1792 
1793 /*---------------------------------------------------------------------------*/
1794 
1795 IMAGE *img_read_region_tzr (char *filename, int x0, int y0,
1796                                             int x1, int y1, int step)
1797 {
1798   FILE *file;
1799   IMAGE *image;
1800   UINT tzr_type;
1801   int full_lx, full_ly, reg_lx, reg_ly, img_offs;
1802   INFO_REGION region;
1803   int i, pixels;
1804 
1805   SET_READ_CMAPPED
1806 
1807   file = fopen(filename, "rb");
1808   if (!file) return NIL;
1809   image = new_img();
1810   if (!image) goto error;
1811   if (!read_tzr_header(filename, file, image, &tzr_type, &img_offs,
1812                        Read_cmapped, TRUE))
1813     goto error;
1814   full_lx          = image->pixmap.xsize;
1815   full_ly          = image->pixmap.ysize;
1816   if (x0 == -1) x0 = full_lx - 1;
1817   if (y0 == -1) y0 = full_ly - 1;
1818   reg_lx           = (x1 - x0) / step + 1;
1819   reg_ly           = (y1 - y0) / step + 1;
1820   if (!allocate_pixmap(image, reg_lx, reg_ly)) goto error;
1821 
1822   /* per adesso si fa un clear brutale */
1823   pixels = reg_lx * reg_ly;
1824   switch (image->type) {
1825     CASE RGB
1826         : for (i = 0; i < pixels; i++)((ULONG *)(image->pixmap.buffer))[i] = 0;
1827     CASE CMAPPED : for (i = 0; i < pixels;
1828                         i++)((USHORT *)(image->pixmap.buffer))[i] = 0xF;
1829     CASE CMAPPED24 : for (i = 0; i < pixels;
1830                           i++)((ULONG *)(image->pixmap.buffer))[i] = 0xFF;
1831   DEFAULT:
1832     assert(0);
1833   }
1834 
1835   getInfoRegion(&region, x0, y0, x1, y1, step, full_lx, full_ly);
1836 
1837   switch (tzr_type) {
1838     CASE 0x01010100
1839         : if (!read_region_tzr_1_1_1(filename, file, image, img_offs,
1840                                      Read_cmapped, &region)) goto error;
1841 
1842     CASE 0x02010100
1843         : if (!read_region_tzr_2_1_1(filename, file, image, img_offs,
1844                                      Read_cmapped, &region)) goto error;
1845 
1846   DEFAULT:
1847     goto error;
1848   }
1849   fclose(file);
1850   return image;
1851 
1852 error:
1853   if (image) free_img(image);
1854   if (file) fclose(file);
1855   return NIL;
1856 }
1857 
1858 /*---------------------------------------------------------------------------*/
1859 
1860 IMAGE *img_read_tzr_info (char *filename)
1861 {
1862   FILE *file;
1863   IMAGE *image;
1864   int img_offs;
1865   UINT tzr_type;
1866 
1867   file = fopen(filename, "rb");
1868   if (!file) return NIL;
1869   image = new_img();
1870   if (!image) goto error;
1871   if (!read_tzr_header(filename, file, image, &tzr_type, &img_offs,
1872                        Read_cmapped, TRUE))
1873     goto error;
1874   fclose(file);
1875   return image;
1876 
1877 error:
1878   if (image) free_img(image);
1879   if (file) fclose(file);
1880   return NIL;
1881 }
1882