1 
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 
7 #include "tiio_tzp.h"
8 
9 extern "C" {
10 #include "../tif/tifimage/tiff.h"
11 #include "../tif/tifimage/tiffio.h"
12 }
13 
14 //#include "toonz.h"
15 //#include "tmsg.h"
16 //#include "file.h"
17 //#include "img.h"
18 //#include "tiff.h"
19 //#include "tiffio.h"
20 //#include "tim.h"
21 //#include "history.h"
22 //#include "../infoRegionP.h"
23 //#include "version.h"
24 //#include "machine.h"
25 //#include "tenv.h"
26 //#include "ImageP/img_security.h"
27 
28 #define ICON_WIDTH 100
29 #define ICON_HEIGHT 90
30 
31 #define TBOOL int
32 #define FALSE 0
33 #define TRUE 1
34 
35 #define UCHAR unsigned char
36 #define USHORT unsigned short
37 #define ULONG unsigned long
38 #define UINT unsigned int
39 
40 #define CASE                                                                   \
41   break;                                                                       \
42   case
43 #define __OR case
44 #define DEFAULT                                                                \
45   break;                                                                       \
46   default
47 
48 #ifndef MAXINT
49 #define MAXINT ((int)((~0U) >> 1))
50 #endif
51 
52 #define NOT_LESS_THAN(A, B)
53 typedef struct { UCHAR r, g, b, m; } LPIXEL;
54 
55 #define TMALLOC(A, C) A = malloc(C * sizeof(A[0]));
56 #define TFREE(A) free(A);
57 #define NIL 0
58 
59 typedef struct {
60   int x1, y1, x2, y2;
61   int x_offset, y_offset;         /*  offset all'interno della regione   */
62   int xsize, ysize;               /*      dimensioni della regione       */
63   int scanNrow, scanNcol;         /* righe e col. dell'immagine da scan. */
64   int startScanRow, startScanCol; /*   offset nell'immagine da scandire  */
65   int step;                       /*          fattore di scale           */
66   int lx_in, ly_in;               /*    dimensioni immag. da scandire    */
67   int verso_x, verso_y;           /* verso di scrittura nel buffer dest. */
68   int buf_inc;                    /* incremento tra due pix. consecutivi */
69   int sxpix, expix, sypix, eypix; /* pixel estremi del buffer di input   */
70 } INFO_REGION;
71 
72 typedef struct {
73   /*UCHAR    tone_offs; sempre 0 */
74   UCHAR tone_bits;
75   UCHAR color_offs;
76   UCHAR color_bits;
77   UCHAR pencil_offs;
78   UCHAR pencil_bits;
79   USHORT offset_mask;  // fa allo stesso tempo sia da offset che da maschera
80   USHORT default_val;  // da utilizzare, p.es., per pixel fuori dall'immagine
81   short n_tones;
82   short n_colors;
83   short n_pencils;
84 } TCM_INFO;
85 
86 static const TCM_INFO Tcm_old_default_info = {
87     /*0,*/ 4, 4, 5, 9, 2, 0x0800, 0x080f, 16, 32, 4};
88 static const TCM_INFO Tcm_new_default_info = {
89     /*0,*/ 4, 4, 7, 11, 5, 0x0000, 0x000f, 16, 128, 32};
90 static const TCM_INFO Tcm_24_default_info = {
91     /*0,*/ 8, 8, 8, 16, 8, 0x0000, 0x00ff, 256, 256, 256};
92 
93 #define TCM_TONE_MASK(TCM) ((1U << (TCM).tone_bits) - 1U)
94 #define TCM_COLOR_MASK(TCM)                                                    \
95   (((1U << (TCM).color_bits) - 1U) << (TCM).color_offs)
96 #define TCM_PENCIL_MASK(TCM)                                                   \
97   (((1U << (TCM).pencil_bits) - 1U) << (TCM).pencil_offs)
98 
99 #define TCM_COLOR_INDEX(TCM, ID)                                               \
100   ((ID) << (TCM).color_offs | ((TCM).n_tones - 1) | (TCM).offset_mask)
101 #define TCM_PENCIL_INDEX(TCM, ID)                                              \
102   ((ID) << (TCM).pencil_offs | (TCM).offset_mask)
103 
104 #define TCM_INDEX_IS_COLOR_ONLY(TCM, INDEX)                                    \
105   (((INDEX)&TCM_TONE_MASK(TCM)) == TCM_TONE_MASK(TCM))
106 #define TCM_INDEX_IS_PENCIL_ONLY(TCM, INDEX) (((INDEX)&TCM_TONE_MASK(TCM)) == 0)
107 
108 #define TCM_COLOR_ID(TCM, INDEX)                                               \
109   ((int)(((INDEX) >> (TCM).color_offs) & ((1U << (TCM).color_bits) - 1U)))
110 #define TCM_PENCIL_ID(TCM, INDEX)                                              \
111   ((int)(((INDEX) >> (TCM).pencil_offs) & ((1U << (TCM).pencil_bits) - 1U)))
112 
113 #define TCM_MIN_CMAP_BUFFER_SIZE(TCM)                                          \
114   ((((TCM).n_pencils - 1) << (TCM).pencil_offs |                               \
115     ((TCM).n_colors - 1) << (TCM).color_offs | (TCM).n_tones - 1) +            \
116    1)
117 
118 #define TCM_MIN_CMAP_COLBUFFER_SIZE(TCM) ((TCM).n_colors * (TCM).n_tones)
119 
120 #define TCM_MIN_CMAP_PENBUFFER_SIZE(TCM) ((TCM).n_pencils * (TCM).n_tones)
121 
122 #define TCM_CMAP_BUFFER_SIZE(TCM)                                              \
123   (1 << ((TCM).pencil_bits + (TCM).color_bits + (TCM).tone_bits))
124 
125 #define TCM_CMAP_COLBUFFER_SIZE(TCM) (1 << ((TCM).color_bits + (TCM).tone_bits))
126 
127 #define TCM_CMAP_PENBUFFER_SIZE(TCM)                                           \
128   (1 << ((TCM).pencil_bits + (TCM).tone_bits))
129 
130 static int Next_img_read_with_extra = FALSE;
131 static int Read_with_extra          = FALSE;
132 #define SET_READ_WITH_EXTRA                                                    \
133   {                                                                            \
134     Read_with_extra          = Next_img_read_with_extra;                       \
135     Next_img_read_with_extra = FALSE;                                          \
136   }
137 
138 typedef struct {
139   USHORT bits_per_sample, samples_per_pixel, photometric;
140   int xsize, ysize, xSBsize, ySBsize, x0, y0;
141   double x_dpi, y_dpi;
142   double h_pos;  // in pixel, mentre TIFFTAG_XPOSITION e' in RESUNITS
143   UCHAR extra_mask;
144   TBOOL edu_file;
145 } TZUP_FIELDS;
146 
147 // Tipi di  IMAGE
148 enum img_type {
149   IMG_NONE,
150   CMAPPED,   /* fa riferimento a una color-map */
151   CMAPPED24, /* 3 x 8 bit (ink, paint, ramp) + 8 bit extra (nel MSB) */
152   RGB,       /* ogni pixel e' una terna red-green-blue   - 8bit per canale */
153   RGB64,     /* ogni pixel e' una terna red-green-blue - 16bit per canale */
154   GR8,       /* a toni di grigio */
155   CMAP       /* color map */
156 };
157 
158 /* pixel-map */
159 struct s_pixmap {
160   USHORT *buffer;
161   UCHAR *extra;     /* patches etc. */
162   UCHAR extra_mask; /* bits extra usati in buffer (CMAPPED24) o in extra */
163   int xsize, ysize;
164   int xSBsize, ySBsize, xD, yD; /* savebox */
165   double x_dpi, y_dpi;
166   double h_pos; /* in pixel */
167 };
168 
169 /* color-map */
170 struct s_cmap {
171   char *name;        /* riferimento a CMAP esterna */
172   LPIXEL *buffer;    /* buffer della colormap (premoltiplicata) */
173   LPIXEL *penbuffer; /* buffer della componente di pencil per > 16 bits */
174   LPIXEL *colbuffer; /* buffer della componente di color  per > 16 bits */
175   LPIXEL *pencil;    /* i colori non premoltiplicati */
176   LPIXEL *color;     /* tanti quanto dicono info.n_pencils e n_colors */
177   TCM_INFO info;     /* vedi tcm.h */
178   void *names;       /* nomi dei colori, gestiti da colorsdb */
179 
180   /* seguono i campi che andrebbero eliminati perche' doppioni */
181   int offset;            /* == info.offset_mask */
182   int pencil_n, color_n; /* == info.n_pencils e n_colors */
183 };
184 
185 /* Enum per l'identificazione dell' algoritmo di riduzione dei colori */
186 
187 typedef enum { CM_NONE = -1, CM_STANDARD, CM_CUSTOM } IMG_CM_ALGORITHM;
188 
189 /* Struttura per le modalita' di scrittura dei formati di file supportati  */
190 
191 typedef struct {
192   char rgb_is_compressed;
193   char rgb_write_matte;
194   char rgb_64_bits;
195   char rgb_colorstyle; /* full color or greyscale */
196   char tga_bytes_per_pixel;
197   char tga_is_colormap;
198   char tga_is_compressed;
199 
200   /*
201 * Microsoft Windows Bitmap (BMP and DIB)
202 *
203 *                         | compression | colorstyle | numcolors |
204 * ---------------------------------------------------------------
205 *       BLack & White     |      0      |     0      |     2     |
206 * ----------------------------------------------------------------
207 *    16 Grey Tones        |      0      |    GR8     |     16    |
208 * ---------------------------------------------------------------
209 *    16 Grey Tones Comp.  |      1      |    GR8     |     16    |
210 * ---------------------------------------------------------------
211 *   256 Grey Tones        |      0      |    GR8     |     256   |
212 * ---------------------------------------------------------------
213 *   256 Grey Tones Comp.  |      1      |    GR8     |     256   |
214 * ---------------------------------------------------------------
215 *    16 Color Mapped      |      0      |  CMAPPED   |     16    |
216 * ---------------------------------------------------------------
217 *    16 Color Mapped Comp.|      1      |  CMAPPED   |     16    |
218 * ---------------------------------------------------------------
219 *   256 Color Mapped      |      0      |  CMAPPED   |     256   |
220 * ---------------------------------------------------------------
221 *   256 Color Mapped Comp.|      1      |  CMAPPED   |     256   |
222 * ---------------------------------------------------------------
223 *       Full Color        |      0      |    RGB     |     0     |
224 * ---------------------------------------------------------------
225 *
226 */
227   unsigned short bmp_compression;
228   unsigned short bmp_colorstyle;
229   unsigned short bmp_numcolors;
230 
231   /*---------------------------------------------------------------*/
232 
233   unsigned int jpg_quality;
234   unsigned int jpg_smoothing;
235   unsigned int jpg_components;
236 
237   /*---------------------------------------------------------------*/
238 
239   unsigned short tif_compression;
240   unsigned short tif_orientation;
241   unsigned short tif_photometric;
242   unsigned short tif_bits_per_sample;
243   unsigned short tif_samples_per_pixel;
244 
245   /*---------------------------------------------------------------*/
246 
247   IMG_CM_ALGORITHM cm_algorithm;
248 
249   /*---------------------------------------------------------------*/
250 
251   /*TNZMOVIE_QUALITY      pct_quality;
252 TNZMOVIE_COMPRESSION  pct_compression;
253 */
254   /*---------------------------------------------------------------*/
255   /*
256 TNZMOVIE_QUALITY     mov_quality;
257 TNZMOVIE_COMPRESSION mov_compression;
258 */
259   int avi_bpp;
260   char *avi_compression;
261 } IMG_IO_SETTINGS;
262 
263 /* Struttura IMAGE */
264 typedef struct s_image {
265   enum img_type type;
266   char *filename;
267   char *history;
268   struct s_pixmap icon;   /* Icon */
269   struct s_cmap cmap;     /* Colormap */
270   struct s_pixmap pixmap; /* Pixel Map */
271   IMG_IO_SETTINGS io_settings;
272 } IMAGE;
273 
274 extern int Silent_tiff_print_error;
275 extern int Tiff_ignore_missing_internal_colormap;
276 
277 static int write_rgb_image(IMAGE *image, TIFF *tif),
278     write_cmapped_image(IMAGE *image, TIFF *tif),
279     write_cmapped24_image(IMAGE *image, TIFF *tif),
280     write_extra(IMAGE *image, TIFF *tif),
281     get_tzup_fields(TIFF *tif, TZUP_FIELDS *tzup_f),
282     get_bits_per_sample(TIFF *tif, USHORT *bps),
283     get_samples_per_pixel(TIFF *tif, USHORT *spp),
284     get_image_sizes(TIFF *tif, int *xsize, int *ysize),
285     get_photometric(TIFF *tif, USHORT *pm),
286     get_resolutions(TIFF *tif, double *x_dpi, double *y_dpi),
287     get_history(TIFF *tif, char **history),
288     get_compression(TIFF *tif, int *compression),
289     get_rows_per_strip(TIFF *tif, long *rowperstrip),
290     get_tag_software(TIFF *tif, char *tag_software),
291     get_orientation(TIFF *tif, int *orientation);
292 
293 static bool scanline_needs_swapping(TIFF *tfp);
294 
295 static void get_planarconfig(TIFF *tif, USHORT *planargonfig);
296 
297 static void get_image_offsets_and_dimensions(TIFF *tif, int xSBsize,
298                                              int ySBsize, int *x0, int *y0,
299                                              int *xsize, int *ysize,
300                                              double *h_pos, UCHAR *extra_mask,
301                                              TBOOL *edu_file),
302 
303     get_plt_name(char *filename, char *pltname),
304 
305     clear_image_buffer_16(IMAGE *img, USHORT bg_val),
306     clear_image_buffer_24(IMAGE *img, ULONG bg_val),
307     clear_extra(IMAGE *img, UCHAR bg_val),
308     clear_image_region_buffer_16(USHORT *buffer, int x0, int y0,
309                                  int clear_xsize, int clear_ysize, int wrap_x,
310                                  USHORT bg_val),
311     clear_image_region_buffer_24(ULONG *buffer, int x0, int y0, int clear_xsize,
312                                  int clear_ysize, int wrap_x, ULONG bg_val),
313     clear_extra_region(UCHAR *extra, int x0, int y0, int clear_xsize,
314                        int clear_ysize, int wrap_x, UCHAR bg_val);
315 
316 static int get_image(TIFF *tif, IMAGE *image),
317     get_image_contig_16(TIFF *tif, IMAGE *image),
318     get_image_contig_24(TIFF *tif, IMAGE *image),
319     get_icon(TIFF *tif, IMAGE *image), get_extra(TIFF *tif, IMAGE *image);
320 
321 static char Verbose = 0; /* Variabile per debug */
322 
323 /*---------------------------------------------------------------------------*/
324 
get_output_compression(void)325 static UINT get_output_compression(void) {
326   static UINT output_compression = 0;
327   /*
328 char *s;
329 if ( !output_compression)
330 {
331 if (tenv_get_var_s("TOONZ_TZUP_COMPRESSION", &s))
332 {
333 if (strstr (s, "rle") || strstr (s, "RLE"))
334 output_compression = COMPRESSION_TOONZ1;
335 else
336 output_compression = COMPRESSION_LZW;
337 }
338 else
339 output_compression = COMPRESSION_LZW;
340 }
341 */
342   return output_compression;
343 }
344 
345 /*---------------------------------------------------------------------------*/
346 
347 #ifdef CICCIO
img_write_tzup(unsigned short * filename,IMAGE * image)348 int img_write_tzup(unsigned short *filename, IMAGE *image) {
349   TIFF *tfp;
350   int bits_per_sample, samples_per_pixel, photometric, planar_config;
351   int orientation, rows_per_strip, bytes_per_line;
352   int width, height, row, scanline, cmap_size, i;
353   char str[200], *history;
354   UCHAR *outbuf;
355   USHORT window[TOONZWINDOW_COUNT];
356   USHORT palette[TOONZPALETTE_COUNT];
357   TCM_INFO *tcm;
358   UINT tif_compression;
359 
360   /* CHECK_IMAGEDLL_LICENSE_AND_GET_IMG_LICENSE_ATTR */
361 
362   Silent_tiff_print_error               = 1;
363   Tiff_ignore_missing_internal_colormap = 1;
364   tfp                                   = TIFFOpen(filename, "w");
365   if (!tfp) {
366     /*throw "unable to open file for output"; , filename);*/
367     return FALSE;
368   }
369 
370   switch (image->type) {
371     CASE RGB : bits_per_sample       = 8;
372     samples_per_pixel                = 4;
373     photometric                      = PHOTOMETRIC_RGB;
374     planar_config                    = PLANARCONFIG_CONTIG;
375     CASE CMAPPED : bits_per_sample   = 16;
376     samples_per_pixel                = 1;
377     photometric                      = PHOTOMETRIC_PALETTE;
378     planar_config                    = PLANARCONFIG_CONTIG;
379     CASE CMAPPED24 : bits_per_sample = 32;
380     samples_per_pixel                = 1;
381     photometric                      = PHOTOMETRIC_PALETTE;
382     planar_config                    = PLANARCONFIG_CONTIG;
383   DEFAULT:
384     /*tmsg_error("bad image type writing file %s", filename);*/
385     goto bad;
386   }
387 
388   orientation = ORIENTATION_BOTLEFT;
389   /*
390 width  = image->pixmap.xsize;
391 height = image->pixmap.ysize;
392 */
393   width  = image->pixmap.xSBsize;
394   height = image->pixmap.ySBsize;
395 
396   if (image->cmap.info.n_pencils && image->cmap.info.n_colors)
397     tcm = &image->cmap.info;
398   else if (image->type == CMAPPED24)
399     tcm = (TCM_INFO *)&Tcm_24_default_info;
400   else
401     tcm = (TCM_INFO *)&Tcm_new_default_info;
402 
403   if (image->cmap.offset)
404     cmap_size = TCM_MIN_CMAP_BUFFER_SIZE(*tcm);
405   else
406     cmap_size = TCM_CMAP_BUFFER_SIZE(*tcm);
407   palette[0]  = (image->cmap.offset > 0) ? 4 : 3;
408   palette[1]  = image->cmap.offset;
409   palette[2]  = cmap_size <= 0xffff ? cmap_size : 0;
410   palette[3]  = 0 /* tcm->tone_offs */;
411   palette[4]  = tcm->tone_bits;
412   palette[5]  = tcm->color_offs;
413   palette[6]  = tcm->color_bits;
414   palette[7]  = tcm->pencil_offs;
415   palette[8]  = tcm->pencil_bits;
416   palette[9]  = tcm->offset_mask;
417   palette[10] = tcm->n_colors;
418   palette[11] = tcm->n_pencils;
419 
420   for (i = 12; i < TOONZPALETTE_COUNT; i++) palette[i] = 0;
421 
422   tif_compression = get_output_compression();
423 
424   TIFFSetField(tfp, TIFFTAG_TOONZPALETTE, palette);
425   TIFFSetField(tfp, TIFFTAG_BITSPERSAMPLE, bits_per_sample);
426   TIFFSetField(tfp, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel);
427   TIFFSetField(tfp, TIFFTAG_IMAGEWIDTH, width);
428   TIFFSetField(tfp, TIFFTAG_IMAGELENGTH, height);
429   TIFFSetField(tfp, TIFFTAG_ORIENTATION, orientation);
430   TIFFSetField(tfp, TIFFTAG_PLANARCONFIG, planar_config);
431   TIFFSetField(tfp, TIFFTAG_PHOTOMETRIC, photometric);
432   TIFFSetField(tfp, TIFFTAG_COMPRESSION, tif_compression);
433 
434   /*
435 * NOTARE CHE VA COMPLETATA LA PARTE RELAITVA AL SETTAGGIO DELLA RISOLUZIONE
436 *
437 */
438   TIFFSetField(tfp, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
439   TIFFSetField(tfp, TIFFTAG_XRESOLUTION, image->pixmap.x_dpi);
440   TIFFSetField(tfp, TIFFTAG_YRESOLUTION, image->pixmap.y_dpi);
441   switch (orientation) {
442     CASE ORIENTATION_BOTLEFT
443         : __OR ORIENTATION_BOTRIGHT
444           : __OR ORIENTATION_TOPLEFT
445             : __OR ORIENTATION_TOPRIGHT
446               : if (image->pixmap.x_dpi) TIFFSetField(
447                     tfp, TIFFTAG_XPOSITION,
448                     image->pixmap.h_pos / image->pixmap.x_dpi + 8.0);
449     CASE ORIENTATION_LEFTBOT
450         : __OR ORIENTATION_RIGHTBOT
451           : __OR ORIENTATION_LEFTTOP
452             : __OR ORIENTATION_RIGHTTOP
453               : if (image->pixmap.y_dpi) TIFFSetField(
454                     tfp, TIFFTAG_XPOSITION,
455                     image->pixmap.h_pos / image->pixmap.y_dpi + 8.0);
456   }
457   /*snprintf(str, sizeof(str), "TOONZ %s", versione_del_software);*/
458   TIFFSetField(tfp, TIFFTAG_SOFTWARE, str);
459 
460   /* Aggiungo le informazioni relative alla savebox a all'history */
461 
462   window[0] = image->pixmap.xD;
463   window[1] = image->pixmap.yD;
464   window[2] = image->pixmap.xsize;
465   window[3] = image->pixmap.ysize;
466   window[4] = image->pixmap.extra_mask;
467 
468   for (i = 5; i < TOONZWINDOW_COUNT - 1; i++) window[i] = 0;
469 
470   window[TOONZWINDOW_COUNT - 1] = 0;
471   /*  (Img_license_attr & TA_TOONZ_EDU) != 0;*/
472 
473   TIFFSetField(tfp, TIFFTAG_TOONZWINDOW, window);
474 
475   history = build_history();
476   /*
477 if (image->history)
478 {
479 switch(check_history(image->history, history))
480 {
481 CASE APPEND:
482 image->history = append_history(image->history, history);
483 CASE REPLACE:
484 image->history = replace_last_history(image->history, history);
485 DEFAULT:
486 tmsg_error("Internal error: bad history type");
487 abort();
488 }
489 free (history);
490 }
491 else
492 */
493   image->history = history;
494 
495   TIFFSetField(tfp, TIFFTAG_TOONZHISTORY, image->history);
496 
497   bytes_per_line = TIFFScanlineSize(tfp);
498 
499   /*
500 * massima lunghezza di bytes in una strip e' 8k
501 * vedi Graphics File Formats pag.48
502 */
503   if (planar_config == PLANARCONFIG_CONTIG)
504     rows_per_strip = (8 * 1024) / bytes_per_line;
505   else
506     rows_per_strip = 1L;
507 
508   TIFFSetField(tfp, TIFFTAG_ROWSPERSTRIP,
509                rows_per_strip == 0 ? 1L : rows_per_strip);
510 
511   switch (image->type) {
512     CASE RGB : if (!write_rgb_image(image, tfp)) {
513       // tmsg_error("unable to write buffer to file %s", filename);
514       goto bad;
515     }
516     CASE CMAPPED : if (!write_cmapped_image(image, tfp)) {
517       // tmsg_error("unable to write buffer to file %s", filename);
518       goto bad;
519     }
520     CASE CMAPPED24 : if (!write_cmapped24_image(image, tfp)) {
521       // tmsg_error("unable to write buffer to file %s", filename);
522       goto bad;
523     }
524   DEFAULT:
525     // tmsg_error("bad image type writing file %s", filename);
526     goto bad;
527   }
528 
529   Silent_tiff_print_error               = 0;
530   Tiff_ignore_missing_internal_colormap = 0;
531   TIFFClose(tfp);
532   return TRUE;
533 
534 bad:
535   Silent_tiff_print_error               = 0;
536   Tiff_ignore_missing_internal_colormap = 0;
537   TIFFClose(tfp);
538   return FALSE;
539 }
540 #endif
541 
542 /*---------------------------------------------------------------------------*/
543 
write_rgb_image(IMAGE * image,TIFF * tfp)544 static int write_rgb_image(IMAGE *image, TIFF *tfp) {
545   int scanlinesize;
546   UCHAR *outbuf, *buf;
547   int row, lx, ly, x, wrapx, x0, y0;
548   LPIXEL *gl_buf, *tmp;
549 
550   lx    = image->pixmap.xSBsize;
551   ly    = image->pixmap.ySBsize;
552   x0    = image->pixmap.xD;
553   y0    = image->pixmap.yD;
554   wrapx = image->pixmap.xsize;
555 
556   tmp          = (LPIXEL *)image->pixmap.buffer + y0 * wrapx + x0;
557   scanlinesize = TIFFScanlineSize(tfp);
558   outbuf       = new UCHAR[scanlinesize];
559 
560   if (!outbuf) return FALSE;
561 
562   for (row = 0; row < ly; row++) {
563     buf    = outbuf;
564     gl_buf = tmp;
565     for (x = 0; x < lx; x++) {
566       *buf++ = gl_buf->r;
567       *buf++ = gl_buf->g;
568       *buf++ = gl_buf->b;
569       *buf++ = gl_buf->m;
570       gl_buf++;
571     }
572     if (TIFFWriteScanline(tfp, outbuf, row, 0) < 0) goto bad;
573     tmp += wrapx;
574   }
575 
576   delete[] outbuf;
577 
578   if (image->pixmap.extra_mask) write_extra(image, tfp);
579 
580   return TRUE;
581 
582 bad:
583   // tmsg_error("write_scan_line failed at row %d", row);
584   delete[] outbuf;
585   return FALSE;
586 }
587 
588 /*---------------------------------------------------------------------------*/
589 
write_cmapped_image(IMAGE * image,TIFF * tfp)590 static int write_cmapped_image(IMAGE *image, TIFF *tfp) {
591   int scanline, lx, ly, x0, y0, wrapx;
592   int row;
593   UCHAR *outbuf;
594   USHORT *tmp;
595   int tmp_icon;
596   struct s_pixmap ori_icon;
597   UINT tif_compression;
598 
599   tif_compression = get_output_compression();
600 
601   tmp_icon = FALSE;
602 
603   lx    = image->pixmap.xSBsize;
604   ly    = image->pixmap.ySBsize;
605   x0    = image->pixmap.xD;
606   y0    = image->pixmap.yD;
607   wrapx = image->pixmap.xsize;
608 
609   tmp    = image->pixmap.buffer + y0 * wrapx + x0;
610   outbuf = 0;
611   for (row = 0; row < ly; row++) {
612     outbuf = (UCHAR *)tmp;
613     if (TIFFWriteScanline(tfp, outbuf, row, 0) < 0) goto bad;
614     tmp += wrapx;
615   }
616   if (image->pixmap.extra_mask && !image->icon.buffer) {
617     ori_icon = image->icon;
618     // make_icon (image, ICON_WIDTH, ICON_HEIGHT);
619     tmp_icon = TRUE;
620   }
621   if (image->icon.buffer) {
622     if (!TIFFFlush(tfp)) {
623       // tmsg_error("Unable to flush data to .tz(up) file");
624       goto bad;
625     }
626     lx = image->icon.xsize;
627     ly = image->icon.ysize;
628 
629     TIFFSetField(tfp, TIFFTAG_SUBFILETYPE, 1);
630     TIFFSetField(tfp, TIFFTAG_BITSPERSAMPLE, 16);
631     TIFFSetField(tfp, TIFFTAG_SAMPLESPERPIXEL, 1);
632     TIFFSetField(tfp, TIFFTAG_IMAGEWIDTH, lx);
633     TIFFSetField(tfp, TIFFTAG_IMAGELENGTH, ly);
634     TIFFSetField(tfp, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT);
635     TIFFSetField(tfp, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
636     TIFFSetField(tfp, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
637     TIFFSetField(tfp, TIFFTAG_COMPRESSION, tif_compression);
638 
639     scanline = TIFFScanlineSize(tfp);
640     outbuf   = (UCHAR *)image->icon.buffer;
641     for (row = 0; row < ly; row++) {
642       if (TIFFWriteScanline(tfp, outbuf, row, 0) < 0) {
643         // tmsg_error("error writing icon to .tz(up) file");
644         goto bad;
645       }
646       outbuf += scanline;
647     }
648   }
649   if (image->pixmap.extra_mask) write_extra(image, tfp);
650 
651   if (tmp_icon && image->icon.buffer) {
652     TFREE(image->icon.buffer)
653     image->icon = ori_icon;
654   }
655   return TRUE;
656 
657 bad:
658   if (tmp_icon && image->icon.buffer) {
659     TFREE(image->icon.buffer)
660     image->icon = ori_icon;
661   }
662   return FALSE;
663 }
664 
665 /*---------------------------------------------------------------------------*/
666 
write_cmapped24_image(IMAGE * image,TIFF * tfp)667 static int write_cmapped24_image(IMAGE *image, TIFF *tfp) {
668   int scanline, lx, ly, x0, y0, wrapx;
669   int row;
670   UCHAR *outbuf;
671   ULONG *tmp;
672   UINT tif_compression;
673 
674   tif_compression = get_output_compression();
675 
676   lx    = image->pixmap.xSBsize;
677   ly    = image->pixmap.ySBsize;
678   x0    = image->pixmap.xD;
679   y0    = image->pixmap.yD;
680   wrapx = image->pixmap.xsize;
681 
682   tmp    = (ULONG *)image->pixmap.buffer + y0 * wrapx + x0;
683   outbuf = 0;
684   for (row = 0; row < ly; row++) {
685     outbuf = (UCHAR *)tmp;
686     if (TIFFWriteScanline(tfp, outbuf, row, 0) < 0) goto bad;
687     tmp += wrapx;
688   }
689 
690   if (image->icon.buffer) {
691     if (!TIFFFlush(tfp)) {
692       // tmsg_error("Unable to flush data to .tz(up) file");
693       goto bad;
694     }
695     lx = image->icon.xsize;
696     ly = image->icon.ysize;
697 
698     TIFFSetField(tfp, TIFFTAG_SUBFILETYPE, 1);
699     TIFFSetField(tfp, TIFFTAG_BITSPERSAMPLE, 32);
700     TIFFSetField(tfp, TIFFTAG_SAMPLESPERPIXEL, 1);
701     TIFFSetField(tfp, TIFFTAG_IMAGEWIDTH, lx);
702     TIFFSetField(tfp, TIFFTAG_IMAGELENGTH, ly);
703     TIFFSetField(tfp, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT);
704     TIFFSetField(tfp, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
705     TIFFSetField(tfp, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
706     TIFFSetField(tfp, TIFFTAG_COMPRESSION, tif_compression);
707 
708     scanline = TIFFScanlineSize(tfp);
709     outbuf   = (UCHAR *)image->icon.buffer;
710     for (row = 0; row < ly; row++) {
711       if (TIFFWriteScanline(tfp, outbuf, row, 0) < 0) {
712         // tmsg_error("error writing icon to .tz(up) file");
713         goto bad;
714       }
715       outbuf += scanline;
716     }
717   }
718   return TRUE;
719 
720 bad:
721   return FALSE;
722 }
723 
724 /*---------------------------------------------------------------------------*/
725 
write_extra(IMAGE * image,TIFF * tfp)726 static int write_extra(IMAGE *image, TIFF *tfp) {
727   int lx, ly, x0, y0, wrapx, row;
728   UCHAR *extra;
729   UINT tif_compression;
730   int rowsperstrip;
731 
732   if (!image->pixmap.extra_mask) return TRUE;
733 
734   tif_compression = get_output_compression();
735 
736   if (!TIFFFlush(tfp)) {
737     // tmsg_error("Unable to flush data to .tz(up) file");
738     goto bad;
739   }
740   lx    = image->pixmap.xSBsize;
741   ly    = image->pixmap.ySBsize;
742   x0    = image->pixmap.xD;
743   y0    = image->pixmap.yD;
744   wrapx = image->pixmap.xsize;
745 
746   TIFFSetField(tfp, TIFFTAG_SUBFILETYPE, 1);
747   TIFFSetField(tfp, TIFFTAG_BITSPERSAMPLE, 8);
748   TIFFSetField(tfp, TIFFTAG_SAMPLESPERPIXEL, 1);
749   TIFFSetField(tfp, TIFFTAG_IMAGEWIDTH, lx);
750   TIFFSetField(tfp, TIFFTAG_IMAGELENGTH, ly);
751   TIFFSetField(tfp, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT);
752   TIFFSetField(tfp, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
753   TIFFSetField(tfp, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
754   TIFFSetField(tfp, TIFFTAG_COMPRESSION, tif_compression);
755 
756   rowsperstrip = (8 * 1024) / lx; /* contig, 1 byte per pixel */
757   NOT_LESS_THAN(1, rowsperstrip)
758   TIFFSetField(tfp, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
759 
760   extra = image->pixmap.extra + y0 * wrapx + x0;
761   for (row = 0; row < ly; row++) {
762     if (TIFFWriteScanline(tfp, extra, row, 0) < 0) goto bad;
763     extra += wrapx;
764   }
765   return TRUE;
766 
767 bad:
768   // tmsg_error ("error writing extra information to .tz(up) file");
769   return FALSE;
770 }
771 
772 /*===========================================================================*/
773 
next_img_read_with_extra(void)774 void next_img_read_with_extra(void) { Next_img_read_with_extra = TRUE; }
775 
776 /*===========================================================================*/
777 
load()778 TImageP TImageReaderTZP::load() {
779   /*
780 FILE *fp;
781 if ((fp = _wfopen(getFilePath().getWideString().c_str(), L"rb")) == NULL)
782 {
783 throw TImageException(getFilePath(),"can't open file");
784 }
785 
786 //{
787 //  fclose(fp);
788 //  throw TImageException(getFilePath(),"invalid file format");
789 //}
790 
791 TRaster32P raster(lx,ly);
792 TPixel32* row;
793 
794 TRasterImageP rasImage(raster);
795 
796 TImageP image(rasImage);
797 
798 */
799 
800   wstring fn = getFilePath().getWideString();
801   TIFF *tfp;
802   IMAGE *image = NIL;
803   TZUP_FIELDS tzup_f;
804   // char pltname[1024];
805   USHORT *window = NIL;
806   USHORT *palette; /*  [TOONZPALETTE_COUNT] */
807   // int max_n_colors, max_n_pencils;
808 
809   /*
810 CHECK_IMAGEDLL_LICENSE_AND_GET_IMG_LICENSE_ATTR
811 SET_READ_WITH_EXTRA
812 */
813 
814   Silent_tiff_print_error               = 1;
815   Tiff_ignore_missing_internal_colormap = 1;
816   tfp                                   = TIFFOpen(fn.c_str(), "r");
817   if (!tfp) return TImageP();
818 
819   if (!get_tzup_fields(tfp, &tzup_f)) return TImageP();
820 
821   /*
822 if (tzup_f.edu_file && !(Img_license_attr & TA_TOONZ_EDU))
823 {
824 char str[1024];
825 BUILD_EDU_ERROR_STRING(str)
826 tmsg_error (str);
827 goto bad;
828 }
829 */
830 
831   // image = new IMAGE; // new_img();
832   // if (!image)
833   //  goto bad;
834 
835   if (!TIFFGetField(tfp, TIFFTAG_TOONZPALETTE, &palette)) {
836     // image->cmap.info = Tcm_old_default_info;
837   } else {
838     //// image->cmap.info.tone_offs   = palette[3]; sempre 0
839     /*
840 image->cmap.info.tone_bits   = (UCHAR)palette[4];
841 image->cmap.info.color_offs  = (UCHAR)palette[5];
842 image->cmap.info.color_bits  = (UCHAR)palette[6];
843 image->cmap.info.pencil_offs = (UCHAR)palette[7];
844 image->cmap.info.pencil_bits = (UCHAR)palette[8];
845 image->cmap.info.offset_mask = palette[9];
846 image->cmap.info.n_tones     = 1 << palette[4];
847 image->cmap.info.n_colors    = palette[10];
848 image->cmap.info.n_pencils   = palette[11];
849 image->cmap.info.default_val = (image->cmap.info.n_tones-1) |
850                       image->cmap.info.offset_mask;
851 */
852   }
853 
854   /* estendo la palette */
855 
856   /*
857 max_n_colors  = 1 << image->cmap.info.color_bits;
858 max_n_pencils = 1 << image->cmap.info.pencil_bits;
859 if (max_n_colors  > image->cmap.info.n_colors ||
860 max_n_pencils > image->cmap.info.n_pencils)
861 {
862 image->cmap.info.n_colors  = max_n_colors;
863 image->cmap.info.n_pencils = max_n_pencils;
864 image->cmap.color_n  = image->cmap.info.n_colors;
865 image->cmap.pencil_n = image->cmap.info.n_pencils;
866 }
867 */
868 
869   TRasterCM16P raster(tzup_f.xsize, tzup_f.ysize);
870 
871   ///===========
872   {
873     bool swapNeeded = scanline_needs_swapping(tfp);
874 
875     int x0    = tzup_f.x0;
876     int y0    = tzup_f.y0;
877     int lx    = tzup_f.xSBsize;
878     int ly    = tzup_f.ySBsize;
879     int x1    = x0 + lx - 1;
880     int y1    = y0 + ly - 1;
881     int xsize = tzup_f.xsize;
882     int ysize = tzup_f.ysize;
883 
884     int wrap = tzup_f.xsize;
885 
886     assert(raster->getBounds().contains(TRect(x0, y0, x1, y1)));
887     raster->fillOutside(TRect(x0, y0, x1, y1), TPixelCM16(0, 0, 15));
888     raster->lock();
889     for (int y = y0; y <= y1; y++) {
890       TPixelCM16 *row = raster->pixels(y) + x0;
891       if (TIFFReadScanline(tfp, (UCHAR *)row, y - y0, 0) < 0)
892         if (swapNeeded) TIFFSwabArrayOfShort((USHORT *)row, lx);
893     }
894     raster->unlock();
895     /*
896 buf   = image->pixmap.buffer;
897 default_val = image->cmap.info.default_val;
898 for (y = 0; y < y0; y++)
899 {
900 pix = buf + y * wrap;
901 for (x = 0; x < xsize; x++)
902 *pix++ = default_val;
903 }
904 for ( ; y <= y1; y++)
905 {
906 pix = buf + y * wrap;
907 for (x = 0; x < x0; x++)
908 *pix++ = default_val;
909 if (TIFFReadScanline (tf, (UCHAR *)pix, y - y0, 0) < 0)
910 {
911 static int gia_dato = FALSE;
912 if ( !gia_dato)
913 {
914 //tmsg_error("bad data read on line %d", y);
915 gia_dato = TRUE;
916 }
917 memset (pix, 0, lx * sizeof(*pix));
918 }
919 if (swap_needed)
920 TIFFSwabArrayOfShort((USHORT *)pix, lx);
921 pix += lx;
922 for (x = x1 + 1; x < xsize; x++)
923 *pix++ = default_val;
924 }
925 for ( ; y < ysize; y++)
926 {
927 pix = buf + y * wrap;
928 for (x = 0; x < xsize; x++)
929 *pix++ = default_val;
930 }
931 */
932   }
933   ///===========
934 
935   switch (tzup_f.photometric) {
936     CASE PHOTOMETRIC_MINISBLACK : __OR PHOTOMETRIC_MINISWHITE
937                                   : __OR PHOTOMETRIC_RGB
938                                     :;  // image->type = RGB;
939 
940     CASE PHOTOMETRIC_PALETTE :
941         /*
942 if (tzup_f.bits_per_sample == 32)
943 image->type = CMAPPED24;
944 else
945 image->type = CMAPPED;
946 */
947 
948         DEFAULT:
949         // tmsg_error("bad photometric interpretation in file %s", filename);
950         // goto bad;
951         ;
952   }
953 
954   // if (!get_history(tfp, &image->history))
955   //  image->history = NIL;
956 
957   // image->pixmap.extra_mask = tzup_f.extra_mask;
958 
959   // if (!allocate_pixmap(image, tzup_f.xsize, tzup_f.ysize))
960   // image->pixmap.buffer = new USHORT[tzup_f.xsize*tzup_f.ysize];
961   // if(!image->pixmap.buffer)
962   //  goto bad;
963 
964   // image->pixmap.xD      = tzup_f.x0;
965   // image->pixmap.yD      = tzup_f.y0;
966   // image->pixmap.xSBsize = tzup_f.xSBsize;
967   // image->pixmap.ySBsize = tzup_f.ySBsize;
968 
969   /*
970 if (!get_image(tfp, image))
971 {
972 //tmsg_error("no image while reading file %s", filename);
973 goto bad;
974 }
975 if (!get_icon(tfp, image))
976 {
977 //make_icon(image, ICON_WIDTH, ICON_HEIGHT);
978 }
979 if (image->pixmap.extra)
980 if ( !get_extra (tfp, image))
981 {
982 //tmsg_error("missing extra information while reading file %s", filename);
983 goto bad;
984 }
985 image->pixmap.x_dpi = tzup_f.x_dpi;
986 image->pixmap.y_dpi = tzup_f.y_dpi;
987 image->pixmap.h_pos = tzup_f.h_pos;
988 
989 Silent_tiff_print_error = 0;
990 Tiff_ignore_missing_internal_colormap = 0;
991 */
992 
993   TIFFClose(tfp);
994 
995   // image->filename = 0; // strsave(filename);
996 
997   // get_plt_name(filename, pltname);
998   // image->cmap.name = 0; // strsave(pltname);
999 
1000   assert(0);
1001   return 0;
1002   // TToonzImageP toonzImage(raster);
1003   // return TImageP(toonzImage);
1004 
1005   /*
1006 bad:
1007 if (image)
1008 {
1009 //free_img(image);
1010 }
1011 Silent_tiff_print_error = 0;
1012 Tiff_ignore_missing_internal_colormap = 0;
1013 if (tfp)
1014 TIFFClose(tfp);
1015 return NIL;
1016 
1017 */
1018 }
1019 
1020 /*===========================================================================*/
1021 
scanline_needs_swapping(TIFF * tfp)1022 static bool scanline_needs_swapping(TIFF *tfp) {
1023   USHORT compression;
1024 
1025   TIFFGetField(tfp, TIFFTAG_COMPRESSION, &compression);
1026   return compression == COMPRESSION_LZW && TIFFNeedSwab(tfp);
1027 }
1028 
1029 /*---------------------------------------------------------------------------*/
1030 
read_region_tzup_16(IMAGE * image,TIFF * tfp,char * filename,INFO_REGION * region,int scale,UCHAR * buf,int scanline_size,int rowperstrip,int wrap_out,int xD_offset,int yD_offset)1031 static int read_region_tzup_16(IMAGE *image, TIFF *tfp, char *filename,
1032                                INFO_REGION *region, int scale, UCHAR *buf,
1033                                int scanline_size, int rowperstrip, int wrap_out,
1034                                int xD_offset, int yD_offset) {
1035   USHORT *inp = NIL, *outp = NIL, *appo_outp = NIL;
1036   int row, nrow, rrow;
1037   TBOOL swap_needed;
1038 
1039   swap_needed = scanline_needs_swapping(tfp);
1040 
1041   appo_outp = image->pixmap.buffer + yD_offset * wrap_out + xD_offset;
1042 
1043   if (Verbose) printf("Posizione in uscita: %d, %d\n", xD_offset, yD_offset);
1044 
1045   /* Puntatore per avanzamento nel buffer della regione */
1046   outp = appo_outp;
1047 
1048   row = region->startScanRow;
1049   /*
1050 * Questa serie di scanline viene fatta perche' non viene
1051 * accettato un accesso random alle righe del file.
1052 */
1053   if (row > 0) {
1054     int c;
1055     c = (row / rowperstrip) * rowperstrip;
1056     for (; c < row; c++) {
1057       if (TIFFReadScanline(tfp, buf, c, 0) < 0) {
1058         // tmsg_error("bad image data read on line %d of file %s", c, filename);
1059         return FALSE;
1060       }
1061     }
1062   }
1063   for (nrow = 0; nrow < region->scanNrow; nrow++) {
1064     appo_outp = outp;
1065     if (TIFFReadScanline(tfp, buf, row, 0) < 0) {
1066       // tmsg_error("bad image data read at line %d of file %s", row, filename);
1067       return FALSE;
1068     }
1069     if (swap_needed)
1070       TIFFSwabArrayOfShort((USHORT *)buf, scanline_size / sizeof(USHORT));
1071 
1072     inp = (USHORT *)buf + region->startScanCol;
1073     for (rrow = 0; rrow < region->scanNcol; rrow++) {
1074       *outp++ = *inp;
1075       inp += scale;
1076     }
1077     if (scale > 1) {
1078       register currRow = 0, stepRow = 1, nextRow = 0;
1079       if (row + scale > region->ly_in)
1080         break;
1081       else
1082         nextRow = row + scale;
1083       stepRow   = (nextRow / rowperstrip) * rowperstrip;
1084       for (currRow = stepRow; currRow < nextRow; currRow++) {
1085         if (TIFFReadScanline(tfp, buf, currRow, 0) < 0) {
1086           // tmsg_error("bad image data in file %s at line %d", filename,
1087           // currRow);
1088           return FALSE;
1089         }
1090       }
1091     }
1092     outp = appo_outp + wrap_out;
1093     row += scale;
1094   }
1095   return TRUE;
1096 }
1097 
1098 /*---------------------------------------------------------------------------*/
1099 
read_region_tzup_24(IMAGE * image,TIFF * tfp,char * filename,INFO_REGION * region,int scale,UCHAR * buf,int scanline_size,int rowperstrip,int wrap_out,int xD_offset,int yD_offset)1100 static int read_region_tzup_24(IMAGE *image, TIFF *tfp, char *filename,
1101                                INFO_REGION *region, int scale, UCHAR *buf,
1102                                int scanline_size, int rowperstrip, int wrap_out,
1103                                int xD_offset, int yD_offset) {
1104   ULONG *inp = NIL, *outp = NIL, *appo_outp = NIL;
1105   int row, nrow, rrow;
1106   TBOOL swap_needed;
1107 
1108   swap_needed = scanline_needs_swapping(tfp);
1109 
1110   appo_outp = (ULONG *)image->pixmap.buffer + yD_offset * wrap_out + xD_offset;
1111 
1112   if (Verbose) printf("Posizione in uscita: %d, %d\n", xD_offset, yD_offset);
1113 
1114   /* Puntatore per avanzamento nel buffer della regione */
1115   outp = appo_outp;
1116 
1117   row = region->startScanRow;
1118   /*
1119 * Questa serie di scanline viene fatta perche' non viene
1120 * accettato un accesso random alle righe del file.
1121 */
1122   if (row > 0) {
1123     int c;
1124     c = (row / rowperstrip) * rowperstrip;
1125     for (; c < row; c++) {
1126       if (TIFFReadScanline(tfp, buf, c, 0) < 0) {
1127         // tmsg_error("bad image data read on line %d of file %s", c, filename);
1128         return FALSE;
1129       }
1130     }
1131   }
1132   for (nrow = 0; nrow < region->scanNrow; nrow++) {
1133     appo_outp = outp;
1134     if (TIFFReadScanline(tfp, buf, row, 0) < 0) {
1135       // tmsg_error("bad image data read at line %d of file %s", row, filename);
1136       return FALSE;
1137     }
1138     if (swap_needed)
1139       TIFFSwabArrayOfLong((TUINT32 *)buf, scanline_size / sizeof(ULONG));
1140 
1141     inp = (ULONG *)buf + region->startScanCol;
1142     for (rrow = 0; rrow < region->scanNcol; rrow++) {
1143       *outp++ = *inp;
1144       inp += scale;
1145     }
1146     if (scale > 1) {
1147       register currRow = 0, stepRow = 1, nextRow = 0;
1148       if (row + scale > region->ly_in)
1149         break;
1150       else
1151         nextRow = row + scale;
1152       stepRow   = (nextRow / rowperstrip) * rowperstrip;
1153       for (currRow = stepRow; currRow < nextRow; currRow++) {
1154         if (TIFFReadScanline(tfp, buf, currRow, 0) < 0) {
1155           // tmsg_error("bad image data in file %s at line %d", filename,
1156           // currRow);
1157           return FALSE;
1158         }
1159       }
1160     }
1161     outp = appo_outp + wrap_out;
1162     row += scale;
1163   }
1164   return TRUE;
1165 }
1166 
1167 /*===========================================================================*/
1168 
read_region_extra(IMAGE * image,TIFF * tfp,char * filename,INFO_REGION * region,int scale,UCHAR * buf,int wrap_out,int xD_offset,int yD_offset)1169 static int read_region_extra(IMAGE *image, TIFF *tfp, char *filename,
1170                              INFO_REGION *region, int scale, UCHAR *buf,
1171                              int wrap_out, int xD_offset, int yD_offset) {
1172   UCHAR *inp = NIL, *outp = NIL, *appo_outp = NIL;
1173   int row, nrow, rrow;
1174   int scanline_size, rowperstrip;
1175 
1176   if (!TIFFReadDirectory(tfp)) return FALSE;
1177 
1178   scanline_size = TIFFScanlineSize(tfp);
1179   if (!TIFFGetField(tfp, TIFFTAG_ROWSPERSTRIP, &rowperstrip))
1180     rowperstrip = MAXINT / 2;
1181 
1182   appo_outp = image->pixmap.extra + yD_offset * wrap_out + xD_offset;
1183 
1184   if (Verbose)
1185     printf("Posizione in uscita (extra): %d, %d\n", xD_offset, yD_offset);
1186 
1187   /* Puntatore per avanzamento nel buffer della regione */
1188   outp = appo_outp;
1189 
1190   row = region->startScanRow;
1191   /*
1192 * Questa serie di scanline viene fatta perche' non viene
1193 * accettato un accesso random alle righe del file.
1194 */
1195   if (row > 0) {
1196     int c;
1197     c = (row / rowperstrip) * rowperstrip;
1198     for (; c < row; c++) {
1199       if (TIFFReadScanline(tfp, buf, c, 0) < 0) {
1200         // tmsg_error("bad extra data read on line %d of file %s", c, filename);
1201         return FALSE;
1202       }
1203     }
1204   }
1205   for (nrow = 0; nrow < region->scanNrow; nrow++) {
1206     appo_outp = outp;
1207     if (TIFFReadScanline(tfp, buf, row, 0) < 0) {
1208       // tmsg_error("bad extra data read at line %d of file %s", row, filename);
1209       return FALSE;
1210     }
1211 
1212     inp = buf + region->startScanCol;
1213     for (rrow = 0; rrow < region->scanNcol; rrow++) {
1214       *outp++ = *inp;
1215       inp += scale;
1216     }
1217     if (scale > 1) {
1218       register currRow = 0, stepRow = 1, nextRow = 0;
1219       if (row + scale > region->ly_in)
1220         break;
1221       else
1222         nextRow = row + scale;
1223       stepRow   = (nextRow / rowperstrip) * rowperstrip;
1224       for (currRow = stepRow; currRow < nextRow; currRow++) {
1225         if (TIFFReadScanline(tfp, buf, currRow, 0) < 0) {
1226           // tmsg_error("bad extra data in file %s at line %d", filename,
1227           // currRow);
1228           return FALSE;
1229         }
1230       }
1231     }
1232     outp = appo_outp + wrap_out;
1233     row += scale;
1234   }
1235   return TRUE;
1236 }
1237 
1238 /*---------------------------------------------------------------------------*/
1239 #ifdef CICCIO
img_read_region_tzup(unsigned short * filename,int x1,int y1,int x2,int y2,int scale)1240 IMAGE *img_read_region_tzup(unsigned short *filename, int x1, int y1, int x2,
1241                             int y2, int scale) {
1242   TIFF *tfp    = NIL;
1243   IMAGE *image = NIL;
1244   INFO_REGION region;
1245   TZUP_FIELDS tzup_f;
1246   char pltname[1024];
1247   UCHAR *buf = NIL;
1248   USHORT planarconfig;
1249   int rowperstrip;
1250   int xsize_out, ysize_out, clear_xsize, clear_ysize;
1251   int xD_offset, yD_offset;
1252   int x1_reg, y1_reg, x2_reg, y2_reg;
1253   int box_x1, box_y1, box_x2, box_y2;
1254   USHORT *palette; /*  [TOONZPALETTE_COUNT] */
1255   int scanline_size;
1256   int ret;
1257   int max_n_colors, max_n_pencils;
1258 
1259   /*
1260 CHECK_IMAGEDLL_LICENSE_AND_GET_IMG_LICENSE_ATTR
1261 SET_READ_WITH_EXTRA
1262 */
1263 
1264   Silent_tiff_print_error               = 1;
1265   Tiff_ignore_missing_internal_colormap = 1;
1266   tfp                                   = TIFFOpen(filename, "r");
1267   if (!tfp) return NIL;
1268 
1269   if (!get_tzup_fields(tfp, &tzup_f)) goto bad;
1270 
1271   /*
1272 if (tzup_f.edu_file && !(Img_license_attr & TA_TOONZ_EDU))
1273 {
1274 char str[1024];
1275 BUILD_EDU_ERROR_STRING(str)
1276 tmsg_error (str);
1277 goto bad;
1278 }
1279 */
1280 
1281   TIFFGetField(tfp, TIFFTAG_ROWSPERSTRIP, &rowperstrip);
1282 
1283   TIFFGetField(tfp, TIFFTAG_PLANARCONFIG, &planarconfig);
1284   if (planarconfig == PLANARCONFIG_SEPARATE) {
1285     // tmsg_error("separate buffer image in file %s not supported
1286     // yet",filename);
1287     goto bad;
1288   }
1289 
1290   image = new IMAGE;  // new_img();
1291   if (!image) goto bad;
1292 
1293   if (!TIFFGetField(tfp, TIFFTAG_TOONZPALETTE, &palette)) {
1294     image->cmap.info = Tcm_old_default_info;
1295   } else {
1296     /*image->cmap.info.tone_offs   = palette[3]; */
1297     image->cmap.info.tone_bits   = (UCHAR)palette[4];
1298     image->cmap.info.color_offs  = (UCHAR)palette[5];
1299     image->cmap.info.color_bits  = (UCHAR)palette[6];
1300     image->cmap.info.pencil_offs = (UCHAR)palette[7];
1301     image->cmap.info.pencil_bits = (UCHAR)palette[8];
1302     image->cmap.info.offset_mask = palette[9];
1303     image->cmap.info.n_tones     = 1 << palette[4];
1304     image->cmap.info.n_colors    = palette[10];
1305     image->cmap.info.n_pencils   = palette[11];
1306     image->cmap.info.default_val =
1307         (image->cmap.info.n_tones - 1) | image->cmap.info.offset_mask;
1308   }
1309 
1310   /* estendo la palette */
1311 
1312   max_n_colors  = 1 << image->cmap.info.color_bits;
1313   max_n_pencils = 1 << image->cmap.info.pencil_bits;
1314   if (max_n_colors > image->cmap.info.n_colors ||
1315       max_n_pencils > image->cmap.info.n_pencils) {
1316     image->cmap.info.n_colors  = max_n_colors;
1317     image->cmap.info.n_pencils = max_n_pencils;
1318     image->cmap.color_n        = image->cmap.info.n_colors;
1319     image->cmap.pencil_n       = image->cmap.info.n_pencils;
1320   }
1321 
1322   switch (tzup_f.photometric) {
1323     CASE PHOTOMETRIC_MINISBLACK : __OR PHOTOMETRIC_MINISWHITE
1324                                   : __OR PHOTOMETRIC_RGB : image->type = RGB;
1325 
1326     CASE PHOTOMETRIC_PALETTE : if (tzup_f.bits_per_sample == 32) image->type =
1327         CMAPPED24;
1328     else image->type = CMAPPED;
1329 
1330   DEFAULT:
1331     // tmsg_error("bad photometric interpretation in file %s", filename);
1332     goto bad;
1333   }
1334 
1335   x1_reg = x1 - tzup_f.x0;
1336   y1_reg = y1 - tzup_f.y0;
1337 
1338   x2_reg = x2 - tzup_f.x0;
1339   y2_reg = y2 - tzup_f.y0;
1340 
1341   xsize_out = (x2 - x1) / scale + 1;
1342   ysize_out = (y2 - y1) / scale + 1;
1343 
1344   getInfoRegion(&region, x1_reg, y1_reg, x2_reg, y2_reg, scale, tzup_f.xSBsize,
1345                 tzup_f.ySBsize);
1346 
1347   xD_offset = region.x_offset;
1348   yD_offset = region.y_offset;
1349 
1350   // if (Verbose)
1351   //  printInfoRegion(&region);
1352 
1353   image->pixmap.extra_mask = tzup_f.extra_mask;
1354 
1355   // if (!allocate_pixmap(image, xsize_out, ysize_out))
1356   image->pixmap.buffer = new USHORT[xsize_out * ysize_out];
1357   if (image->pixmap.buffer) goto bad;
1358 
1359   if (TRUE /* x1 != 0 || x2 != tzup_f.xsize - 1 ||
1360              y1 != 0 || y2 != tzup_f.ysize - 1 */) {
1361     clear_xsize = xsize_out;
1362     clear_ysize = ysize_out;
1363     if (image->type == CMAPPED)
1364       clear_image_region_buffer_16(image->pixmap.buffer, 0, 0, clear_xsize,
1365                                    clear_ysize, xsize_out,
1366                                    image->cmap.info.offset_mask + 15);
1367     else if (image->type == CMAPPED24)
1368       clear_image_region_buffer_24((ULONG *)image->pixmap.buffer, 0, 0,
1369                                    clear_xsize, clear_ysize, xsize_out, 255);
1370     else
1371       abort();
1372   } else {
1373     clear_xsize = 0;
1374     clear_ysize = 0;
1375   }
1376   if (Verbose) {
1377     printf("Clear xsize/xsize_out: %d/%d in %d:\n", clear_xsize, xsize_out,
1378            tzup_f.xsize);
1379     printf("Clear ysize/ysize_out: %d/%d in %d:\n", clear_ysize, ysize_out,
1380            tzup_f.ysize);
1381   }
1382   if (image->pixmap.extra)
1383     clear_extra_region(image->pixmap.extra, 0, 0, clear_xsize, clear_ysize,
1384                        xsize_out, 0);
1385   box_x1 = tzup_f.x0;
1386   box_y1 = tzup_f.y0;
1387   box_x2 = tzup_f.x0 + tzup_f.xSBsize - 1;
1388   box_y2 = tzup_f.y0 + tzup_f.ySBsize - 1;
1389   if (x1 > box_x2 || x2 < box_x1 || y1 > box_y2 || y2 < box_y1) {
1390     image->pixmap.xsize   = xsize_out;
1391     image->pixmap.ysize   = ysize_out;
1392     image->pixmap.xSBsize = xsize_out;
1393     image->pixmap.ySBsize = ysize_out;
1394     image->pixmap.xD      = 0;
1395     image->pixmap.yD      = 0;
1396     image->pixmap.x_dpi   = tzup_f.x_dpi;
1397     image->pixmap.y_dpi   = tzup_f.y_dpi;
1398     image->pixmap.h_pos   = tzup_f.h_pos;
1399     image->filename       = strsave(filename);
1400     get_plt_name(filename, pltname);
1401     image->cmap.name = strsave(pltname);
1402     goto ok;
1403   }
1404   image->pixmap.xD      = xD_offset;
1405   image->pixmap.yD      = yD_offset;
1406   image->pixmap.xSBsize = region.scanNcol;
1407   image->pixmap.ySBsize = region.scanNrow;
1408 
1409   /* Buffer per la scanline */
1410   scanline_size = TIFFScanlineSize(tfp);
1411   TMALLOC(buf, scanline_size)
1412   if (!buf) goto bad;
1413 
1414   switch (image->type) {
1415     CASE CMAPPED : ret = read_region_tzup_16(
1416                        image, tfp, filename, &region, scale, buf, scanline_size,
1417                        rowperstrip, xsize_out, xD_offset, yD_offset);
1418     CASE CMAPPED24
1419         : ret = read_region_tzup_24(image, tfp, filename, &region, scale, buf,
1420                                     scanline_size, rowperstrip, xsize_out,
1421                                     xD_offset, yD_offset);
1422   DEFAULT:
1423     ret = FALSE;
1424     abort();
1425   }
1426   if (!ret) goto bad;
1427 
1428   image->pixmap.x_dpi = tzup_f.x_dpi;
1429   image->pixmap.y_dpi = tzup_f.y_dpi;
1430   image->pixmap.h_pos = tzup_f.h_pos;
1431 
1432   image->filename = strsave(filename);
1433   get_plt_name(filename, pltname);
1434   image->cmap.name = strsave(pltname);
1435 
1436   if (!get_icon(tfp, image)) make_icon(image, ICON_WIDTH, ICON_HEIGHT);
1437 
1438   if (image->pixmap.extra) {
1439     ret = read_region_extra(image, tfp, filename, &region, scale, buf,
1440                             xsize_out, xD_offset, yD_offset);
1441     if (!ret) goto bad;
1442   }
1443 
1444 ok:
1445   Silent_tiff_print_error               = 0;
1446   Tiff_ignore_missing_internal_colormap = 0;
1447   TIFFClose(tfp);
1448   TFREE(buf);
1449   return image;
1450 
1451 bad:
1452   if (image) free_img(image);
1453   Silent_tiff_print_error               = 0;
1454   Tiff_ignore_missing_internal_colormap = 0;
1455   TIFFClose(tfp);
1456   TFREE(buf);
1457   return NIL;
1458 }
1459 
1460 #endif
1461 
1462 /*---------------------------------------------------------------------------*/
1463 
img_read_tzup_info(unsigned short * filename)1464 IMAGE *img_read_tzup_info(unsigned short *filename) {
1465   TIFF *tfp;
1466   IMAGE *image = NIL;
1467   TZUP_FIELDS tzup_f;
1468   USHORT *palette; /*  [TOONZPALETTE_COUNT] */
1469   int max_n_colors, max_n_pencils;
1470 
1471   /* CHECK_IMAGEDLL_LICENSE_AND_GET_IMG_LICENSE_ATTR */
1472 
1473   Silent_tiff_print_error               = 1;
1474   Tiff_ignore_missing_internal_colormap = 1;
1475 
1476   tfp = TIFFOpen((wchar_t *)filename, "r");
1477   if (!tfp) goto bad;
1478 
1479   if (!get_tzup_fields(tfp, &tzup_f)) goto bad;
1480 
1481   /*if (tzup_f.edu_file && !(Img_license_attr & TA_TOONZ_EDU))
1482 {
1483 char str[1024];
1484 BUILD_EDU_ERROR_STRING(str)
1485 tmsg_warning (str);
1486 }
1487 */
1488 
1489   image = new IMAGE;  // new_img();
1490   if (!image) goto bad;
1491 
1492   if (!TIFFGetField(tfp, TIFFTAG_TOONZPALETTE, &palette)) {
1493     image->cmap.info = Tcm_old_default_info;
1494   } else {
1495     /*image->cmap.info.tone_offs   = palette[3]; */
1496     image->cmap.info.tone_bits   = (UCHAR)palette[4];
1497     image->cmap.info.color_offs  = (UCHAR)palette[5];
1498     image->cmap.info.color_bits  = (UCHAR)palette[6];
1499     image->cmap.info.pencil_offs = (UCHAR)palette[7];
1500     image->cmap.info.pencil_bits = (UCHAR)palette[8];
1501     image->cmap.info.offset_mask = palette[9];
1502     image->cmap.info.n_tones     = 1 << palette[4];
1503     image->cmap.info.n_colors    = palette[10];
1504     image->cmap.info.n_pencils   = palette[11];
1505     image->cmap.info.default_val =
1506         (image->cmap.info.n_tones - 1) | image->cmap.info.offset_mask;
1507   }
1508 
1509   /* estendo la palette */
1510 
1511   max_n_colors  = 1 << image->cmap.info.color_bits;
1512   max_n_pencils = 1 << image->cmap.info.pencil_bits;
1513   if (max_n_colors > image->cmap.info.n_colors ||
1514       max_n_pencils > image->cmap.info.n_pencils) {
1515     image->cmap.info.n_colors  = max_n_colors;
1516     image->cmap.info.n_pencils = max_n_pencils;
1517     image->cmap.color_n        = image->cmap.info.n_colors;
1518     image->cmap.pencil_n       = image->cmap.info.n_pencils;
1519   }
1520 
1521   switch (tzup_f.photometric) {
1522     CASE PHOTOMETRIC_MINISBLACK : __OR PHOTOMETRIC_MINISWHITE
1523                                   : __OR PHOTOMETRIC_RGB : image->type = RGB;
1524 
1525     CASE PHOTOMETRIC_PALETTE : if (tzup_f.bits_per_sample == 32) image->type =
1526         CMAPPED24;
1527     else image->type = CMAPPED;
1528 
1529   DEFAULT:
1530     // tmsg_error("bad photometric interpretation in file %s", filename);
1531     goto bad;
1532   }
1533   image->pixmap.extra_mask = tzup_f.extra_mask;
1534 
1535   if (!get_history(tfp, &image->history)) {
1536     image->history = NIL;
1537   }
1538   image->pixmap.xsize   = tzup_f.xsize;
1539   image->pixmap.ysize   = tzup_f.ysize;
1540   image->pixmap.xD      = tzup_f.x0;
1541   image->pixmap.yD      = tzup_f.y0;
1542   image->pixmap.xSBsize = tzup_f.xSBsize;
1543   image->pixmap.ySBsize = tzup_f.ySBsize;
1544   image->pixmap.x_dpi   = tzup_f.x_dpi;
1545   image->pixmap.y_dpi   = tzup_f.y_dpi;
1546   image->pixmap.h_pos   = tzup_f.h_pos;
1547 
1548   Silent_tiff_print_error               = 0;
1549   Tiff_ignore_missing_internal_colormap = 0;
1550   TIFFClose(tfp);
1551   return image;
1552 
1553 bad:
1554   if (image) {
1555     // free_img(image);
1556   }
1557   Silent_tiff_print_error               = 0;
1558   Tiff_ignore_missing_internal_colormap = 0;
1559   if (tfp) TIFFClose(tfp);
1560   return NIL;
1561 }
1562 
1563 /*---------------------------------------------------------------------------*/
1564 
1565 #ifdef CICCIO
img_read_tzup_icon(char * filename)1566 IMAGE *img_read_tzup_icon(char *filename) {
1567   TIFF *tfp;
1568   IMAGE *image = NIL;
1569   TZUP_FIELDS tzup_f;
1570   char pltname[1024];
1571   USHORT *palette; /*  [TOONZPALETTE_COUNT] */
1572   int max_n_colors, max_n_pencils;
1573 
1574   Silent_tiff_print_error               = 1;
1575   Tiff_ignore_missing_internal_colormap = 1;
1576   tfp                                   = TIFFOpen(filename, "r");
1577   if (!tfp) return NIL;
1578 
1579   if (!get_tzup_fields(tfp, &tzup_f)) goto bad;
1580 
1581   image = new_img();
1582   if (!image) goto bad;
1583 
1584   image->type           = (tzup_f.bits_per_sample == 32) ? CMAPPED24 : CMAPPED;
1585   image->pixmap.xsize   = tzup_f.xsize;
1586   image->pixmap.ysize   = tzup_f.ysize;
1587   image->pixmap.xSBsize = tzup_f.xSBsize;
1588   image->pixmap.ySBsize = tzup_f.ySBsize;
1589   image->pixmap.xD      = tzup_f.x0;
1590   image->pixmap.yD      = tzup_f.y0;
1591 
1592   get_plt_name(filename, pltname);
1593   image->cmap.name = strsave(pltname);
1594 
1595   if (!TIFFGetField(tfp, TIFFTAG_TOONZPALETTE, &palette)) {
1596     image->cmap.info = Tcm_old_default_info;
1597   } else {
1598     /*image->cmap.info.tone_offs   = palette[3]; */
1599     image->cmap.info.tone_bits   = palette[4];
1600     image->cmap.info.color_offs  = palette[5];
1601     image->cmap.info.color_bits  = palette[6];
1602     image->cmap.info.pencil_offs = palette[7];
1603     image->cmap.info.pencil_bits = palette[8];
1604     image->cmap.info.offset_mask = palette[9];
1605     image->cmap.info.n_tones     = 1 << palette[4];
1606     image->cmap.info.n_colors    = palette[10];
1607     image->cmap.info.n_pencils   = palette[11];
1608     image->cmap.info.default_val =
1609         (image->cmap.info.n_tones - 1) | image->cmap.info.offset_mask;
1610   }
1611 
1612   /* estendo la palette */
1613 
1614   max_n_colors  = 1 << image->cmap.info.color_bits;
1615   max_n_pencils = 1 << image->cmap.info.pencil_bits;
1616   if (max_n_colors > image->cmap.info.n_colors ||
1617       max_n_pencils > image->cmap.info.n_pencils) {
1618     image->cmap.info.n_colors  = max_n_colors;
1619     image->cmap.info.n_pencils = max_n_pencils;
1620     image->cmap.color_n        = image->cmap.info.n_colors;
1621     image->cmap.pencil_n       = image->cmap.info.n_pencils;
1622   }
1623 
1624   if (!get_icon(tfp, image)) {
1625     // tmsg_error("unable to read icon image of file %s", filename);
1626     goto bad;
1627   }
1628   Silent_tiff_print_error               = 0;
1629   Tiff_ignore_missing_internal_colormap = 0;
1630   TIFFClose(tfp);
1631   return image;
1632 
1633 bad:
1634   if (image) free_img(image);
1635   Silent_tiff_print_error               = 0;
1636   Tiff_ignore_missing_internal_colormap = 0;
1637   TIFFClose(tfp);
1638   return NIL;
1639 }
1640 #endif
1641 
1642 /*===========================================================================*/
1643 
get_tzup_fields(TIFF * tfp,TZUP_FIELDS * tzup_f)1644 static int get_tzup_fields(TIFF *tfp, TZUP_FIELDS *tzup_f) {
1645   if (!get_bits_per_sample(tfp, &tzup_f->bits_per_sample)) {
1646     // tmsg_error("can't handle %d-bit images", tzup_f->bits_per_sample);
1647     goto bad;
1648   }
1649   if (!get_samples_per_pixel(tfp, &tzup_f->samples_per_pixel)) {
1650     // tmsg_error("can't handle %d-channel images", tzup_f->samples_per_pixel);
1651     goto bad;
1652   }
1653   if (!get_image_sizes(tfp, &tzup_f->xSBsize, &tzup_f->ySBsize)) {
1654     // tmsg_error("bad image size %dx%d reading .tz(up) file",
1655     //           tzup_f->xSBsize, tzup_f->ySBsize);
1656     goto bad;
1657   }
1658   if (!get_photometric(tfp, &tzup_f->photometric)) {
1659     // tmsg_error("bad photometric interpretation reading .tz(up) file");
1660     goto bad;
1661   }
1662   if (!get_resolutions(tfp, &tzup_f->x_dpi, &tzup_f->y_dpi)) {
1663     // tmsg_error("bad resolutions xres=%lf, yres=%lf reading .tz(up) file",
1664     //           tzup_f->x_dpi, tzup_f->y_dpi);
1665     goto bad;
1666   }
1667   get_image_offsets_and_dimensions(tfp, tzup_f->xSBsize, tzup_f->ySBsize,
1668                                    &tzup_f->x0, &tzup_f->y0, &tzup_f->xsize,
1669                                    &tzup_f->ysize, &tzup_f->h_pos,
1670                                    &tzup_f->extra_mask, &tzup_f->edu_file);
1671   return TRUE;
1672 
1673 bad:
1674   return FALSE;
1675 }
1676 
1677 /*---------------------------------------------------------------------------*/
1678 
get_bits_per_sample(TIFF * tif,USHORT * bps)1679 static int get_bits_per_sample(TIFF *tif, USHORT *bps) {
1680   if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, bps)) {
1681     *bps = 0;
1682     return FALSE;
1683   }
1684   switch (*bps) {
1685     CASE 1 : __OR 2 : __OR 4 : __OR 8 : __OR 16 : __OR 32 : return TRUE;
1686   }
1687   return FALSE;
1688 }
1689 
1690 /*---------------------------------------------------------------------------*/
1691 
get_samples_per_pixel(TIFF * tif,USHORT * spp)1692 static int get_samples_per_pixel(TIFF *tif, USHORT *spp) {
1693   if (!TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, spp)) {
1694     *spp = 0;
1695     return FALSE;
1696   }
1697   switch (*spp) { CASE 1 : __OR 3 : __OR 4 : return TRUE; }
1698   return FALSE;
1699 }
1700 
1701 /*---------------------------------------------------------------------------*/
1702 
get_image_sizes(TIFF * tif,int * xsize,int * ysize)1703 static int get_image_sizes(TIFF *tif, int *xsize, int *ysize) {
1704   *ysize = 0;
1705   if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, xsize)) return FALSE;
1706   if (!TIFFGetField(tif, TIFFTAG_IMAGELENGTH, ysize)) return FALSE;
1707   return TRUE;
1708 }
1709 
1710 /*---------------------------------------------------------------------------*/
1711 
get_image_offsets_and_dimensions(TIFF * tfp,int xSBsize,int ySBsize,int * x0,int * y0,int * xsize,int * ysize,double * h_pos,UCHAR * extra_mask,TBOOL * edu_file)1712 static void get_image_offsets_and_dimensions(TIFF *tfp, int xSBsize,
1713                                              int ySBsize, int *x0, int *y0,
1714                                              int *xsize, int *ysize,
1715                                              double *h_pos, UCHAR *extra_mask,
1716                                              TBOOL *edu_file) {
1717   USHORT *window, orientation;
1718   float xposition, dpi;
1719   // int i;
1720 
1721   if (!TIFFGetField(tfp, TIFFTAG_TOONZWINDOW, &window)) {
1722     *x0         = 0;
1723     *y0         = 0;
1724     *xsize      = xSBsize;
1725     *ysize      = ySBsize;
1726     *extra_mask = 0;
1727 
1728     *edu_file = FALSE;
1729   } else {
1730     *x0                     = window[0];
1731     *y0                     = window[1];
1732     *xsize                  = window[2];
1733     *ysize                  = window[3];
1734     if (*xsize == 0) *xsize = xSBsize + *x0;
1735     if (*ysize == 0) *ysize = ySBsize + *y0;
1736     *extra_mask             = Read_with_extra ? window[4] : 0;
1737 
1738     *edu_file = window[TOONZWINDOW_COUNT - 1] & 1;
1739   }
1740   if (!TIFFGetField(tfp, TIFFTAG_XPOSITION, &xposition)) xposition = 8.0;
1741   if (!TIFFGetField(tfp, TIFFTAG_ORIENTATION, &orientation))
1742     orientation = ORIENTATION_TOPLEFT;
1743   switch (orientation) {
1744     CASE ORIENTATION_BOTLEFT
1745         : __OR ORIENTATION_BOTRIGHT
1746           : __OR ORIENTATION_TOPLEFT
1747             : __OR ORIENTATION_TOPRIGHT
1748               : if (!TIFFGetField(tfp, TIFFTAG_XRESOLUTION, &dpi)) dpi = 0.0;
1749     CASE ORIENTATION_LEFTBOT
1750         : __OR ORIENTATION_RIGHTBOT
1751           : __OR ORIENTATION_LEFTTOP
1752             : __OR ORIENTATION_RIGHTTOP
1753               : if (!TIFFGetField(tfp, TIFFTAG_YRESOLUTION, &dpi)) dpi = 0.0;
1754   }
1755   *h_pos = (xposition - 8.0) * dpi;
1756 }
1757 
1758 /*---------------------------------------------------------------------------*/
1759 
get_photometric(TIFF * tif,USHORT * pm)1760 static int get_photometric(TIFF *tif, USHORT *pm) {
1761   if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, pm)) return FALSE;
1762   return TRUE;
1763 }
1764 
1765 /*---------------------------------------------------------------------------*/
1766 
get_resolutions(TIFF * tif,double * x_dpi,double * y_dpi)1767 static int get_resolutions(TIFF *tif, double *x_dpi, double *y_dpi) {
1768   float xdpi, ydpi;
1769   // USHORT resunit;
1770 
1771   if (!TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xdpi) ||
1772       !TIFFGetField(tif, TIFFTAG_YRESOLUTION, &ydpi)) {
1773     *x_dpi = *y_dpi = 0.0;
1774     return FALSE;
1775   }
1776   *x_dpi = (double)xdpi;
1777   *y_dpi = (double)ydpi;
1778   return TRUE;
1779 }
1780 
1781 /*---------------------------------------------------------------------------*/
1782 
get_orientation(TIFF * tif,int * orientation)1783 static int get_orientation(TIFF *tif, int *orientation) {
1784   if (!TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation)) return FALSE;
1785   return TRUE;
1786 }
1787 
1788 /*---------------------------------------------------------------------------*/
1789 
get_rows_per_strip(TIFF * tif,long * rowperstrip)1790 static int get_rows_per_strip(TIFF *tif, long *rowperstrip) {
1791   if (!TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowperstrip)) return FALSE;
1792   return TRUE;
1793 }
1794 
1795 /*---------------------------------------------------------------------------*/
1796 
get_compression(TIFF * tif,int * compression)1797 static int get_compression(TIFF *tif, int *compression) {
1798   if (!TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression)) return FALSE;
1799   return TRUE;
1800 }
1801 
1802 /*---------------------------------------------------------------------------*/
1803 
get_tag_software(TIFF * tif,char * tag_software)1804 static int get_tag_software(TIFF *tif, char *tag_software) {
1805   if (!TIFFGetField(tif, TIFFTAG_SOFTWARE, tag_software)) return FALSE;
1806   return TRUE;
1807 }
1808 
1809 /*---------------------------------------------------------------------------*/
1810 
get_planarconfig(TIFF * tif,USHORT * planarconfig)1811 static void get_planarconfig(TIFF *tif, USHORT *planarconfig) {
1812   TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
1813 }
1814 
1815 /*---------------------------------------------------------------------------*/
1816 
get_history(TIFF * tif,char ** history)1817 static int get_history(TIFF *tif, char **history) {
1818   if (!TIFFGetField(tif, TIFFTAG_TOONZHISTORY, history)) return FALSE;
1819   //*history = strsave(*history);
1820   return TRUE;
1821 }
1822 
1823 /*---------------------------------------------------------------------------*/
1824 
get_image(TIFF * tf,IMAGE * image)1825 static int get_image(TIFF *tf, IMAGE *image) {
1826   USHORT planarconfig;
1827   // int i;
1828 
1829   TIFFGetField(tf, TIFFTAG_PLANARCONFIG, &planarconfig);
1830   if (planarconfig == PLANARCONFIG_SEPARATE) {
1831     // tmsg_error("separate buffer image not supported yet in .tz(up) files");
1832     return FALSE;
1833   }
1834   switch (image->type) {
1835     CASE CMAPPED : return get_image_contig_16(tf, image);
1836     CASE CMAPPED24 : return get_image_contig_24(tf, image);
1837   DEFAULT:
1838     abort();
1839   }
1840   return FALSE;
1841 }
1842 
1843 /*---------------------------------------------------------------------------*/
1844 
get_image_contig_16(TIFF * tf,IMAGE * image)1845 static int get_image_contig_16(TIFF *tf, IMAGE *image) {
1846   int x, y, x0, y0, x1, y1, lx, ly, xsize, ysize, wrap;
1847   USHORT *buf, *pix, default_val;
1848   TBOOL swap_needed;
1849 
1850   swap_needed = scanline_needs_swapping(tf);
1851 
1852   x0          = image->pixmap.xD;
1853   y0          = image->pixmap.yD;
1854   lx          = image->pixmap.xSBsize;
1855   ly          = image->pixmap.ySBsize;
1856   x1          = x0 + lx - 1;
1857   y1          = y0 + ly - 1;
1858   xsize       = image->pixmap.xsize;
1859   ysize       = image->pixmap.ysize;
1860   wrap        = image->pixmap.xsize;
1861   buf         = image->pixmap.buffer;
1862   default_val = image->cmap.info.default_val;
1863   for (y = 0; y < y0; y++) {
1864     pix = buf + y * wrap;
1865     for (x = 0; x < xsize; x++) *pix++ = default_val;
1866   }
1867   for (; y <= y1; y++) {
1868     pix = buf + y * wrap;
1869     for (x = 0; x < x0; x++) *pix++ = default_val;
1870     if (TIFFReadScanline(tf, (UCHAR *)pix, y - y0, 0) < 0) {
1871       static int gia_dato = FALSE;
1872       if (!gia_dato) {
1873         // tmsg_error("bad data read on line %d", y);
1874         gia_dato = TRUE;
1875       }
1876       memset(pix, 0, lx * sizeof(*pix));
1877     }
1878     if (swap_needed) TIFFSwabArrayOfShort((USHORT *)pix, lx);
1879     pix += lx;
1880     for (x = x1 + 1; x < xsize; x++) *pix++ = default_val;
1881   }
1882   for (; y < ysize; y++) {
1883     pix = buf + y * wrap;
1884     for (x = 0; x < xsize; x++) *pix++ = default_val;
1885   }
1886   return TRUE;
1887 }
1888 
1889 /*---------------------------------------------------------------------------*/
1890 
get_image_contig_24(TIFF * tf,IMAGE * image)1891 static int get_image_contig_24(TIFF *tf, IMAGE *image) {
1892   int x, y, x0, y0, x1, y1, lx, ly, xsize, ysize, wrap;
1893   ULONG *buf, *pix, default_val;
1894   TBOOL swap_needed;
1895 
1896   swap_needed = scanline_needs_swapping(tf);
1897 
1898   x0          = image->pixmap.xD;
1899   y0          = image->pixmap.yD;
1900   lx          = image->pixmap.xSBsize;
1901   ly          = image->pixmap.ySBsize;
1902   x1          = x0 + lx - 1;
1903   y1          = y0 + ly - 1;
1904   xsize       = image->pixmap.xsize;
1905   ysize       = image->pixmap.ysize;
1906   wrap        = image->pixmap.xsize;
1907   buf         = (ULONG *)image->pixmap.buffer;
1908   default_val = image->cmap.info.default_val;
1909   for (y = 0; y < y0; y++) {
1910     pix = buf + y * wrap;
1911     for (x = 0; x < xsize; x++) *pix++ = default_val;
1912   }
1913   for (; y <= y1; y++) {
1914     pix = buf + y * wrap;
1915     for (x = 0; x < x0; x++) *pix++ = default_val;
1916     if (TIFFReadScanline(tf, (UCHAR *)pix, y - y0, 0) < 0) {
1917       static int gia_dato = FALSE;
1918       if (!gia_dato) {
1919         // tmsg_error("bad data read on line %d", y);
1920         gia_dato = TRUE;
1921       }
1922       memset(pix, 0, lx * sizeof(*pix));
1923     }
1924     if (swap_needed) TIFFSwabArrayOfLong((TUINT32 *)pix, lx);
1925     pix += lx;
1926     for (x = x1 + 1; x < xsize; x++) *pix++ = default_val;
1927   }
1928   for (; y < ysize; y++) {
1929     pix = buf + y * wrap;
1930     for (x = 0; x < xsize; x++) *pix++ = default_val;
1931   }
1932   return TRUE;
1933 }
1934 
1935 /*---------------------------------------------------------------------------*/
1936 
get_icon_16(TIFF * tfp,IMAGE * image)1937 static int get_icon_16(TIFF *tfp, IMAGE *image) {
1938   int lx, ly;
1939   UCHAR *buffer;
1940   USHORT *icon_buffer;
1941   int scanline, row;
1942   TBOOL swap_needed;
1943 
1944   if (!TIFFReadDirectory(tfp)) return FALSE;
1945   if (!get_image_sizes(tfp, &lx, &ly)) return FALSE;
1946   swap_needed = scanline_needs_swapping(tfp);
1947 
1948   scanline = TIFFScanlineSize(tfp);
1949 
1950   icon_buffer = new USHORT[lx * ly];
1951 
1952   if (!icon_buffer) return FALSE;
1953   image->icon.buffer  = icon_buffer;
1954   image->icon.xsize   = lx;
1955   image->icon.ysize   = ly;
1956   image->icon.xSBsize = lx;
1957   image->icon.ySBsize = ly;
1958   image->icon.xD      = 0;
1959   image->icon.yD      = 0;
1960 
1961   buffer = (UCHAR *)image->icon.buffer;
1962   for (row = 0; row < image->icon.ysize; row++) {
1963     if (TIFFReadScanline(tfp, buffer, row, 0) < 0) {
1964       // tmsg_error("bad data read on line %d", row);
1965       return FALSE;
1966     }
1967     if (swap_needed) TIFFSwabArrayOfShort((USHORT *)buffer, lx);
1968 
1969     buffer += scanline;
1970   }
1971   return TRUE;
1972 }
1973 
1974 /*---------------------------------------------------------------------------*/
1975 
get_icon_24(TIFF * tfp,IMAGE * image)1976 static int get_icon_24(TIFF *tfp, IMAGE *image) {
1977   int lx, ly;
1978   UCHAR *buffer;
1979   ULONG *icon_buffer;
1980   int scanline, row;
1981   TBOOL swap_needed;
1982 
1983   if (!TIFFReadDirectory(tfp)) return FALSE;
1984   if (!get_image_sizes(tfp, &lx, &ly)) return FALSE;
1985   swap_needed = scanline_needs_swapping(tfp);
1986 
1987   scanline = TIFFScanlineSize(tfp);
1988 
1989   icon_buffer = new ULONG[lx * ly];
1990   if (!icon_buffer) return FALSE;
1991   image->icon.buffer  = (USHORT *)icon_buffer;
1992   image->icon.xsize   = lx;
1993   image->icon.ysize   = ly;
1994   image->icon.xSBsize = lx;
1995   image->icon.ySBsize = ly;
1996   image->icon.xD      = 0;
1997   image->icon.yD      = 0;
1998 
1999   buffer = (UCHAR *)image->icon.buffer;
2000   for (row = 0; row < image->icon.ysize; row++) {
2001     if (TIFFReadScanline(tfp, buffer, row, 0) < 0) {
2002       // tmsg_error("bad data read on line %d", row);
2003       return FALSE;
2004     }
2005     if (swap_needed) TIFFSwabArrayOfLong((TUINT32 *)buffer, lx);
2006 
2007     buffer += scanline;
2008   }
2009   return TRUE;
2010 }
2011 
2012 /*---------------------------------------------------------------------------*/
2013 
get_icon(TIFF * tfp,IMAGE * image)2014 static int get_icon(TIFF *tfp, IMAGE *image) {
2015   switch (image->type) {
2016     CASE CMAPPED : return get_icon_16(tfp, image);
2017     CASE CMAPPED24 : return get_icon_24(tfp, image);
2018   DEFAULT:
2019     abort();
2020   }
2021   return FALSE;
2022 }
2023 
2024 /*---------------------------------------------------------------------------*/
2025 
get_extra(TIFF * tfp,IMAGE * image)2026 static int get_extra(TIFF *tfp, IMAGE *image) {
2027   int x, y, x0, y0, x1, y1, lx, ly, xsize, ysize, wrap;
2028   UCHAR *buf, *pix;
2029 
2030   if (!TIFFReadDirectory(tfp)) return FALSE;
2031 
2032   x0    = image->pixmap.xD;
2033   y0    = image->pixmap.yD;
2034   lx    = image->pixmap.xSBsize;
2035   ly    = image->pixmap.ySBsize;
2036   x1    = x0 + lx - 1;
2037   y1    = y0 + ly - 1;
2038   xsize = image->pixmap.xsize;
2039   ysize = image->pixmap.ysize;
2040   wrap  = image->pixmap.xsize;
2041   buf   = image->pixmap.extra;
2042   for (y = 0; y < y0; y++) {
2043     pix = buf + y * wrap;
2044     for (x = 0; x < xsize; x++) *pix++ = 0;
2045   }
2046   for (; y <= y1; y++) {
2047     pix = buf + y * wrap;
2048     for (x = 0; x < x0; x++) *pix++ = 0;
2049     if (TIFFReadScanline(tfp, (UCHAR *)pix, y - y0, 0) < 0) {
2050       static int gia_dato = FALSE;
2051       if (!gia_dato) {
2052         // tmsg_error("bad data read on extra line %d", y);
2053         gia_dato = TRUE;
2054       }
2055       memset(pix, 0, lx * sizeof(*pix));
2056     }
2057     pix += lx;
2058     for (x = x1 + 1; x < xsize; x++) *pix++ = 0;
2059   }
2060   for (; y < ysize; y++) {
2061     pix = buf + y * wrap;
2062     for (x = 0; x < xsize; x++) *pix++ = 0;
2063   }
2064   return TRUE;
2065 }
2066 
2067 /*---------------------------------------------------------------------------*/
2068 
get_plt_name(char * filename,char * pltname)2069 static void get_plt_name(char *filename, char *pltname) {
2070   // sprintf (pltname, "%s.plt", tim_get_name_nodot((const char*)filename));
2071 }
2072 
2073 /*---------------------------------------------------------------------------*/
2074 
clear_image_buffer_16(IMAGE * img,USHORT bg_val)2075 static void clear_image_buffer_16(IMAGE *img, USHORT bg_val) {
2076   clear_image_region_buffer_16(img->pixmap.buffer, 0, 0, img->pixmap.xsize,
2077                                img->pixmap.ysize, img->pixmap.xsize, bg_val);
2078 }
2079 
2080 /*---------------------------------------------------------------------------*/
2081 
clear_image_buffer_24(IMAGE * img,ULONG bg_val)2082 static void clear_image_buffer_24(IMAGE *img, ULONG bg_val) {
2083   clear_image_region_buffer_24((ULONG *)img->pixmap.buffer, 0, 0,
2084                                img->pixmap.xsize, img->pixmap.ysize,
2085                                img->pixmap.xsize, bg_val);
2086 }
2087 
2088 /*---------------------------------------------------------------------------*/
2089 
clear_extra(IMAGE * img,UCHAR bg_val)2090 static void clear_extra(IMAGE *img, UCHAR bg_val) {
2091   clear_extra_region(img->pixmap.extra, 0, 0, img->pixmap.xsize,
2092                      img->pixmap.ysize, img->pixmap.xsize, bg_val);
2093 }
2094 
2095 /*---------------------------------------------------------------------------*/
2096 
clear_image_region_buffer_16(USHORT * buffer,int x0,int y0,int xsize,int ysize,int wrap_x,USHORT bg_val)2097 static void clear_image_region_buffer_16(USHORT *buffer, int x0, int y0,
2098                                          int xsize, int ysize, int wrap_x,
2099                                          USHORT bg_val) {
2100   USHORT *tmp = new USHORT[xsize];
2101   int x, y, bytes;
2102 
2103   if (!tmp) return;
2104 
2105   for (x = 0; x < xsize; x++) tmp[x] = bg_val;
2106 
2107   bytes = xsize * sizeof(USHORT);
2108   buffer += x0 + y0 * wrap_x;
2109   for (y = 0; y < ysize; y++) {
2110     memcpy(buffer, tmp, bytes);
2111     buffer += wrap_x;
2112   }
2113   delete[] tmp;
2114 }
2115 
2116 /*---------------------------------------------------------------------------*/
2117 
clear_image_region_buffer_24(ULONG * buffer,int x0,int y0,int xsize,int ysize,int wrap_x,ULONG bg_val)2118 static void clear_image_region_buffer_24(ULONG *buffer, int x0, int y0,
2119                                          int xsize, int ysize, int wrap_x,
2120                                          ULONG bg_val) {
2121   ULONG *tmp = new ULONG[xsize];
2122   int x, y, bytes;
2123 
2124   if (!tmp) return;
2125 
2126   for (x = 0; x < xsize; x++) tmp[x] = bg_val;
2127 
2128   bytes = xsize * sizeof(ULONG);
2129   buffer += x0 + y0 * wrap_x;
2130   for (y = 0; y < ysize; y++) {
2131     memcpy(buffer, tmp, bytes);
2132     buffer += wrap_x;
2133   }
2134   delete tmp;
2135 }
2136 
2137 /*---------------------------------------------------------------------------*/
2138 
clear_extra_region(UCHAR * extra,int x0,int y0,int xsize,int ysize,int wrap_x,UCHAR bg_val)2139 static void clear_extra_region(UCHAR *extra, int x0, int y0, int xsize,
2140                                int ysize, int wrap_x, UCHAR bg_val) {
2141   int y;
2142 
2143   extra += x0 + y0 * wrap_x;
2144   for (y = 0; y < ysize; y++) {
2145     memset(extra, bg_val, xsize);
2146     extra += wrap_x;
2147   }
2148 }
2149