1 /* tiff exporting for GIMP
2  *  -Peter Mattis
3  *
4  * The TIFF loading code has been completely revamped by Nick Lamb
5  * njl195@zepler.org.uk -- 18 May 1998
6  * And it now gains support for tiles (and doubtless a zillion bugs)
7  * njl195@zepler.org.uk -- 12 June 1999
8  * LZW patent fuss continues :(
9  * njl195@zepler.org.uk -- 20 April 2000
10  * The code for this filter is based on "tifftopnm" and "pnmtotiff",
11  *  2 programs that are a part of the netpbm package.
12  * khk@khk.net -- 13 May 2000
13  * Added support for ICCPROFILE tiff tag. If this tag is present in a
14  * TIFF file, then a parasite is created and vice versa.
15  * peter@kirchgessner.net -- 29 Oct 2002
16  * Progress bar only when run interactive
17  * Added support for layer offsets - pablo.dangelo@web.de -- 7 Jan 2004
18  * Honor EXTRASAMPLES tag while loading images with alphachannel
19  * pablo.dangelo@web.de -- 16 Jan 2004
20  */
21 
22 /*
23  * tifftopnm.c - converts a Tagged Image File to a portable anymap
24  *
25  * Derived by Jef Poskanzer from tif2ras.c, which is:
26  *
27  * Copyright (c) 1990 by Sun Microsystems, Inc.
28  *
29  * Author: Patrick J. Naughton
30  * naughton@wind.sun.com
31  *
32  * Permission to use, copy, modify, and distribute this software and its
33  * documentation for any purpose and without fee is hereby granted,
34  * provided that the above copyright notice appear in all copies and that
35  * both that copyright notice and this permission notice appear in
36  * supporting documentation.
37  *
38  * This file is provided AS IS with no warranties of any kind.  The author
39  * shall have no liability with respect to the infringement of copyrights,
40  * trade secrets or any patents by this file or any part thereof.  In no
41  * event will the author be liable for any lost revenue or profits or
42  * other special, indirect and consequential damages.
43  */
44 
45 #include "config.h"
46 
47 #include <errno.h>
48 #include <string.h>
49 
50 #include <tiffio.h>
51 #include <gexiv2/gexiv2.h>
52 
53 #include <libgimp/gimp.h>
54 #include <libgimp/gimpui.h>
55 
56 #include "file-tiff-io.h"
57 #include "file-tiff-save.h"
58 
59 #include "libgimp/stdplugins-intl.h"
60 
61 
62 #define PLUG_IN_ROLE "gimp-file-tiff-save"
63 
64 
65 static gboolean  save_paths             (TIFF          *tif,
66                                          gint32         image,
67                                          gdouble        width,
68                                          gdouble        height,
69                                          gint           offset_x,
70                                          gint           offset_y);
71 
72 static void      comment_entry_callback (GtkWidget     *widget,
73                                          gchar        **comment);
74 
75 static void      byte2bit               (const guchar  *byteline,
76                                          gint           width,
77                                          guchar        *bitline,
78                                          gboolean       invert);
79 
80 
81 static void
double_to_psd_fixed(gdouble value,gchar * target)82 double_to_psd_fixed (gdouble  value,
83                      gchar   *target)
84 {
85   gdouble in, frac;
86   gint    i, f;
87 
88   frac = modf (value, &in);
89   if (frac < 0)
90     {
91       in -= 1;
92       frac += 1;
93     }
94 
95   i = (gint) CLAMP (in, -16, 15);
96   f = CLAMP ((gint) (frac * 0xFFFFFF), 0, 0xFFFFFF);
97 
98   target[0] = i & 0xFF;
99   target[1] = (f >> 16) & 0xFF;
100   target[2] = (f >>  8) & 0xFF;
101   target[3] = f & 0xFF;
102 }
103 
104 static gboolean
save_paths(TIFF * tif,gint32 image,gdouble width,gdouble height,gint offset_x,gint offset_y)105 save_paths (TIFF    *tif,
106             gint32   image,
107             gdouble  width,
108             gdouble  height,
109             gint     offset_x,
110             gint     offset_y)
111 {
112   gint id = 2000; /* Photoshop paths have IDs >= 2000 */
113   gint num_vectors, *vectors, v;
114   gint num_strokes, *strokes, s;
115   GString *ps_tag;
116 
117   vectors = gimp_image_get_vectors (image, &num_vectors);
118 
119   if (num_vectors <= 0)
120     return FALSE;
121 
122   ps_tag = g_string_new ("");
123 
124   /* Only up to 1000 paths supported */
125   for (v = 0; v < MIN (num_vectors, 1000); v++)
126     {
127       GString *data;
128       gchar   *name, *nameend;
129       gsize    len;
130       gint     lenpos;
131       gchar    pointrecord[26] = { 0, };
132       gchar   *tmpname;
133       GError  *err = NULL;
134 
135       data = g_string_new ("8BIM");
136       g_string_append_c (data, id / 256);
137       g_string_append_c (data, id % 256);
138 
139       /*
140        * - use iso8859-1 if possible
141        * - otherwise use UTF-8, prepended with \xef\xbb\xbf (Byte-Order-Mark)
142        */
143       name = gimp_item_get_name (vectors[v]);
144       tmpname = g_convert (name, -1, "iso8859-1", "utf-8", NULL, &len, &err);
145 
146       if (tmpname && err == NULL)
147         {
148           g_string_append_c (data, MIN (len, 255));
149           g_string_append_len (data, tmpname, MIN (len, 255));
150           g_free (tmpname);
151         }
152       else
153         {
154           /* conversion failed, we fall back to UTF-8 */
155           len = g_utf8_strlen (name, 255 - 3);  /* need three marker-bytes */
156 
157           nameend = g_utf8_offset_to_pointer (name, len);
158           len = nameend - name; /* in bytes */
159           g_assert (len + 3 <= 255);
160 
161           g_string_append_c (data, len + 3);
162           g_string_append_len (data, "\xEF\xBB\xBF", 3); /* Unicode 0xfeff */
163           g_string_append_len (data, name, len);
164 
165           if (tmpname)
166             g_free (tmpname);
167         }
168 
169       if (data->len % 2)  /* padding to even size */
170         g_string_append_c (data, 0);
171       g_free (name);
172 
173       lenpos = data->len;
174       g_string_append_len (data, "\0\0\0\0", 4); /* will be filled in later */
175       len = data->len; /* to calculate the data size later */
176 
177       pointrecord[1] = 6;  /* fill rule record */
178       g_string_append_len (data, pointrecord, 26);
179 
180       strokes = gimp_vectors_get_strokes (vectors[v], &num_strokes);
181 
182       for (s = 0; s < num_strokes; s++)
183         {
184           GimpVectorsStrokeType type;
185           gdouble  *points;
186           gint      num_points;
187           gboolean  closed;
188           gint      p = 0;
189 
190           type = gimp_vectors_stroke_get_points (vectors[v], strokes[s],
191                                                  &num_points, &points, &closed);
192 
193           if (type != GIMP_VECTORS_STROKE_TYPE_BEZIER ||
194               num_points > 65535 ||
195               num_points % 6)
196             {
197               g_printerr ("tiff-save: unsupported stroke type: "
198                           "%d (%d points)\n", type, num_points);
199               continue;
200             }
201 
202           memset (pointrecord, 0, 26);
203           pointrecord[1] = closed ? 0 : 3;
204           pointrecord[2] = (num_points / 6) / 256;
205           pointrecord[3] = (num_points / 6) % 256;
206           g_string_append_len (data, pointrecord, 26);
207 
208           for (p = 0; p < num_points; p += 6)
209             {
210               pointrecord[1] = closed ? 2 : 5;
211 
212               double_to_psd_fixed ((points[p+1] - offset_y) / height, pointrecord + 2);
213               double_to_psd_fixed ((points[p+0] - offset_x) / width,  pointrecord + 6);
214               double_to_psd_fixed ((points[p+3] - offset_y) / height, pointrecord + 10);
215               double_to_psd_fixed ((points[p+2] - offset_x) / width,  pointrecord + 14);
216               double_to_psd_fixed ((points[p+5] - offset_y) / height, pointrecord + 18);
217               double_to_psd_fixed ((points[p+4] - offset_x) / width,  pointrecord + 22);
218 
219               g_string_append_len (data, pointrecord, 26);
220             }
221         }
222 
223       g_free (strokes);
224 
225       /* fix up the length */
226 
227       len = data->len - len;
228       data->str[lenpos + 0] = (len & 0xFF000000) >> 24;
229       data->str[lenpos + 1] = (len & 0x00FF0000) >> 16;
230       data->str[lenpos + 2] = (len & 0x0000FF00) >>  8;
231       data->str[lenpos + 3] = (len & 0x000000FF) >>  0;
232 
233       g_string_append_len (ps_tag, data->str, data->len);
234       g_string_free (data, TRUE);
235       id ++;
236     }
237 
238   TIFFSetField (tif, TIFFTAG_PHOTOSHOP, ps_tag->len, ps_tag->str);
239   g_string_free (ps_tag, TRUE);
240 
241   g_free (vectors);
242 
243   return TRUE;
244 }
245 
246 /*
247  * pnmtotiff.c - converts a portable anymap to a Tagged Image File
248  *
249  * Derived by Jef Poskanzer from ras2tif.c, which is:
250  *
251  * Copyright (c) 1990 by Sun Microsystems, Inc.
252  *
253  * Author: Patrick J. Naughton
254  * naughton@wind.sun.com
255  *
256  * This file is provided AS IS with no warranties of any kind.  The author
257  * shall have no liability with respect to the infringement of copyrights,
258  * trade secrets or any patents by this file or any part thereof.  In no
259  * event will the author be liable for any lost revenue or profits or
260  * other special, indirect and consequential damages.
261  */
262 
263 static gboolean
save_layer(TIFF * tif,TiffSaveVals * tsvals,gint32 image,gint32 layer,gint32 page,gint32 num_pages,gint32 orig_image,gint origin_x,gint origin_y,gint * saved_bpp,gboolean out_linear,GError ** error)264 save_layer (TIFF         *tif,
265             TiffSaveVals *tsvals,
266             gint32        image,
267             gint32        layer,
268             gint32        page,
269             gint32        num_pages,
270             gint32        orig_image, /* the export function might */
271                                       /* have created a duplicate  */
272             gint          origin_x,
273             gint          origin_y,
274             gint         *saved_bpp,
275             gboolean      out_linear,
276             GError      **error)
277 {
278   gboolean          status = FALSE;
279   gushort           red[256];
280   gushort           grn[256];
281   gushort           blu[256];
282   gint              cols, rows, row, i;
283   glong             rowsperstrip;
284   gushort           compression;
285   gushort           extra_samples[1];
286   gboolean          alpha;
287   gshort            predictor;
288   gshort            photometric;
289   const Babl       *format;
290   const Babl       *type;
291   gshort            samplesperpixel;
292   gshort            bitspersample;
293   gshort            sampleformat;
294   gint              bytesperrow;
295   guchar           *src = NULL;
296   guchar           *data = NULL;
297   guchar           *cmap;
298   gint              num_colors;
299   gint              success;
300   GimpImageType     drawable_type;
301   GeglBuffer       *buffer = NULL;
302   gint              tile_height;
303   gint              y, yend;
304   gboolean          is_bw    = FALSE;
305   gboolean          invert   = TRUE;
306   const guchar      bw_map[] = { 0, 0, 0, 255, 255, 255 };
307   const guchar      wb_map[] = { 255, 255, 255, 0, 0, 0 };
308   gchar            *layer_name = NULL;
309   const gdouble     progress_base = (gdouble) page / (gdouble) num_pages;
310   const gdouble     progress_fraction = 1.0 / (gdouble) num_pages;
311   gdouble           xresolution;
312   gdouble           yresolution;
313   gushort           save_unit = RESUNIT_INCH;
314   gint              offset_x, offset_y;
315 
316   compression = tsvals->compression;
317 
318   layer_name = gimp_item_get_name (layer);
319 
320   /* Disabled because this isn't in older releases of libtiff, and it
321    * wasn't helping much anyway
322    */
323 #if 0
324   if (TIFFFindCODEC((uint16) compression) == NULL)
325     compression = COMPRESSION_NONE; /* CODEC not available */
326 #endif
327 
328   predictor = 0;
329   tile_height = gimp_tile_height ();
330   rowsperstrip = tile_height;
331 
332   drawable_type = gimp_drawable_type (layer);
333   buffer        = gimp_drawable_get_buffer (layer);
334 
335   format = gegl_buffer_get_format (buffer);
336   type   = babl_format_get_type (format, 0);
337 
338   switch (gimp_image_get_precision (image))
339     {
340     case GIMP_PRECISION_U8_LINEAR:
341     case GIMP_PRECISION_U8_GAMMA:
342       /* Promote to 16-bit if storage and export TRC don't match. */
343       if ((gimp_image_get_precision (image) == GIMP_PRECISION_U8_LINEAR && out_linear) ||
344           (gimp_image_get_precision (image) != GIMP_PRECISION_U8_LINEAR && ! out_linear))
345         {
346           bitspersample = 8;
347           sampleformat  = SAMPLEFORMAT_UINT;
348         }
349       else
350         {
351           bitspersample = 16;
352           sampleformat  = SAMPLEFORMAT_UINT;
353           type          = babl_type ("u16");
354         }
355       break;
356 
357     case GIMP_PRECISION_U16_LINEAR:
358     case GIMP_PRECISION_U16_GAMMA:
359       bitspersample = 16;
360       sampleformat  = SAMPLEFORMAT_UINT;
361       break;
362 
363     case GIMP_PRECISION_U32_LINEAR:
364     case GIMP_PRECISION_U32_GAMMA:
365       bitspersample = 32;
366       sampleformat  = SAMPLEFORMAT_UINT;
367       break;
368 
369     case GIMP_PRECISION_HALF_LINEAR:
370     case GIMP_PRECISION_HALF_GAMMA:
371       bitspersample = 16;
372       sampleformat  = SAMPLEFORMAT_IEEEFP;
373       break;
374 
375     default:
376     case GIMP_PRECISION_FLOAT_LINEAR:
377     case GIMP_PRECISION_FLOAT_GAMMA:
378       bitspersample = 32;
379       sampleformat  = SAMPLEFORMAT_IEEEFP;
380       break;
381 
382     case GIMP_PRECISION_DOUBLE_LINEAR:
383     case GIMP_PRECISION_DOUBLE_GAMMA:
384       bitspersample = 64;
385       sampleformat  = SAMPLEFORMAT_IEEEFP;
386       break;
387     }
388 
389   *saved_bpp = bitspersample;
390 
391   cols = gegl_buffer_get_width (buffer);
392   rows = gegl_buffer_get_height (buffer);
393 
394   switch (drawable_type)
395     {
396     case GIMP_RGB_IMAGE:
397       predictor       = 2;
398       samplesperpixel = 3;
399       photometric     = PHOTOMETRIC_RGB;
400       alpha           = FALSE;
401       if (out_linear)
402         {
403           format = babl_format_new (babl_model ("RGB"),
404                                     type,
405                                     babl_component ("R"),
406                                     babl_component ("G"),
407                                     babl_component ("B"),
408                                     NULL);
409         }
410       else
411         {
412           format = babl_format_new (babl_model ("R'G'B'"),
413                                     type,
414                                     babl_component ("R'"),
415                                     babl_component ("G'"),
416                                     babl_component ("B'"),
417                                     NULL);
418         }
419       break;
420 
421     case GIMP_GRAY_IMAGE:
422       samplesperpixel = 1;
423       photometric     = PHOTOMETRIC_MINISBLACK;
424       alpha           = FALSE;
425       if (out_linear)
426         {
427           format = babl_format_new (babl_model ("Y"),
428                                     type,
429                                     babl_component ("Y"),
430                                     NULL);
431         }
432       else
433         {
434           format = babl_format_new (babl_model ("Y'"),
435                                     type,
436                                     babl_component ("Y'"),
437                                     NULL);
438         }
439       break;
440 
441     case GIMP_RGBA_IMAGE:
442       predictor       = 2;
443       samplesperpixel = 4;
444       photometric     = PHOTOMETRIC_RGB;
445       alpha           = TRUE;
446       if (tsvals->save_transp_pixels)
447         {
448           if (out_linear)
449             {
450               format = babl_format_new (babl_model ("RGBA"),
451                                         type,
452                                         babl_component ("R"),
453                                         babl_component ("G"),
454                                         babl_component ("B"),
455                                         babl_component ("A"),
456                                         NULL);
457             }
458           else
459             {
460               format = babl_format_new (babl_model ("R'G'B'A"),
461                                         type,
462                                         babl_component ("R'"),
463                                         babl_component ("G'"),
464                                         babl_component ("B'"),
465                                         babl_component ("A"),
466                                         NULL);
467             }
468         }
469       else
470         {
471           if (out_linear)
472             {
473               format = babl_format_new (babl_model ("RaGaBaA"),
474                                         type,
475                                         babl_component ("Ra"),
476                                         babl_component ("Ga"),
477                                         babl_component ("Ba"),
478                                         babl_component ("A"),
479                                         NULL);
480             }
481           else
482             {
483               format = babl_format_new (babl_model ("R'aG'aB'aA"),
484                                         type,
485                                         babl_component ("R'a"),
486                                         babl_component ("G'a"),
487                                         babl_component ("B'a"),
488                                         babl_component ("A"),
489                                         NULL);
490             }
491         }
492       break;
493 
494     case GIMP_GRAYA_IMAGE:
495       samplesperpixel = 2;
496       photometric     = PHOTOMETRIC_MINISBLACK;
497       alpha           = TRUE;
498       if (tsvals->save_transp_pixels)
499         {
500           if (out_linear)
501             {
502               format = babl_format_new (babl_model ("YA"),
503                                         type,
504                                         babl_component ("Y"),
505                                         babl_component ("A"),
506                                         NULL);
507             }
508           else
509             {
510               format = babl_format_new (babl_model ("Y'A"),
511                                         type,
512                                         babl_component ("Y'"),
513                                         babl_component ("A"),
514                                         NULL);
515             }
516         }
517       else
518         {
519           if (out_linear)
520             {
521               format = babl_format_new (babl_model ("YaA"),
522                                         type,
523                                         babl_component ("Ya"),
524                                         babl_component ("A"),
525                                         NULL);
526             }
527           else
528             {
529               format = babl_format_new (babl_model ("Y'aA"),
530                                         type,
531                                         babl_component ("Y'a"),
532                                         babl_component ("A"),
533                                         NULL);
534             }
535         }
536       break;
537 
538     case GIMP_INDEXED_IMAGE:
539     case GIMP_INDEXEDA_IMAGE:
540       cmap = gimp_image_get_colormap (image, &num_colors);
541 
542       if (num_colors == 2 || num_colors == 1)
543         {
544           is_bw = (memcmp (cmap, bw_map, 3 * num_colors) == 0);
545           photometric = PHOTOMETRIC_MINISWHITE;
546 
547           if (!is_bw)
548             {
549               is_bw = (memcmp (cmap, wb_map, 3 * num_colors) == 0);
550 
551               if (is_bw)
552                 invert = FALSE;
553             }
554        }
555 
556       if (is_bw)
557         {
558           bitspersample = 1;
559         }
560       else
561         {
562           bitspersample = 8;
563           photometric   = PHOTOMETRIC_PALETTE;
564 
565           for (i = 0; i < num_colors; i++)
566             {
567               red[i] = cmap[i * 3 + 0] * 65535 / 255;
568               grn[i] = cmap[i * 3 + 1] * 65535 / 255;
569               blu[i] = cmap[i * 3 + 2] * 65535 / 255;
570             }
571        }
572 
573       samplesperpixel = (drawable_type == GIMP_INDEXEDA_IMAGE) ? 2 : 1;
574       bytesperrow     = cols;
575       alpha           = (drawable_type == GIMP_INDEXEDA_IMAGE);
576       format          = gimp_drawable_get_format (layer);
577 
578       g_free (cmap);
579       break;
580 
581     default:
582       goto out;
583     }
584 
585   bytesperrow = cols * babl_format_get_bytes_per_pixel (format);
586 
587   if (compression == COMPRESSION_CCITTFAX3 ||
588       compression == COMPRESSION_CCITTFAX4)
589     {
590       if (bitspersample != 1 || samplesperpixel != 1)
591         {
592           const gchar *msg = _("Only monochrome pictures can be compressed "
593                                "with \"CCITT Group 4\" or \"CCITT Group 3\".");
594 
595           g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, msg);
596 
597           goto out;
598         }
599     }
600 
601   if (compression == COMPRESSION_JPEG)
602     {
603       if (gimp_image_base_type (image) == GIMP_INDEXED)
604         {
605           g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
606                                _("Indexed pictures cannot be compressed "
607                                  "with \"JPEG\"."));
608           goto out;
609         }
610     }
611 
612 
613   /* Set TIFF parameters. */
614   if (num_pages > 1)
615     {
616       TIFFSetField (tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
617       TIFFSetField (tif, TIFFTAG_PAGENUMBER, page, num_pages);
618     }
619   TIFFSetField (tif, TIFFTAG_PAGENAME, layer_name);
620   TIFFSetField (tif, TIFFTAG_IMAGEWIDTH, cols);
621   TIFFSetField (tif, TIFFTAG_IMAGELENGTH, rows);
622   TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, bitspersample);
623   TIFFSetField (tif, TIFFTAG_SAMPLEFORMAT, sampleformat);
624   TIFFSetField (tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
625   TIFFSetField (tif, TIFFTAG_COMPRESSION, compression);
626 
627   if ((compression == COMPRESSION_LZW ||
628        compression == COMPRESSION_ADOBE_DEFLATE) &&
629       (predictor != 0))
630     {
631       TIFFSetField (tif, TIFFTAG_PREDICTOR, predictor);
632     }
633 
634   if (alpha)
635     {
636       if (tsvals->save_transp_pixels ||
637           /* Associated alpha, hence premultiplied components is
638            * meaningless for palette images with transparency in TIFF
639            * format, since alpha is set per pixel, not per color (so a
640            * given color could be set to different alpha on different
641            * pixels, hence it cannot be premultiplied).
642            */
643           drawable_type == GIMP_INDEXEDA_IMAGE)
644         extra_samples [0] = EXTRASAMPLE_UNASSALPHA;
645       else
646         extra_samples [0] = EXTRASAMPLE_ASSOCALPHA;
647 
648       TIFFSetField (tif, TIFFTAG_EXTRASAMPLES, 1, extra_samples);
649     }
650 
651   TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, photometric);
652   TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
653   TIFFSetField (tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
654   /* TIFFSetField( tif, TIFFTAG_STRIPBYTECOUNTS, rows / rowsperstrip ); */
655   TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
656 
657   /* resolution fields */
658   gimp_image_get_resolution (orig_image, &xresolution, &yresolution);
659 
660   if (gimp_unit_is_metric (gimp_image_get_unit (orig_image)))
661     {
662       save_unit = RESUNIT_CENTIMETER;
663       xresolution /= 2.54;
664       yresolution /= 2.54;
665     }
666 
667   if (xresolution > 1e-5 && yresolution > 1e-5)
668     {
669       TIFFSetField (tif, TIFFTAG_XRESOLUTION, xresolution);
670       TIFFSetField (tif, TIFFTAG_YRESOLUTION, yresolution);
671       TIFFSetField (tif, TIFFTAG_RESOLUTIONUNIT, save_unit);
672     }
673 
674   gimp_drawable_offsets (layer, &offset_x, &offset_y);
675 
676   offset_x -= origin_x;
677   offset_y -= origin_y;
678 
679   if (offset_x || offset_y)
680     {
681       TIFFSetField (tif, TIFFTAG_XPOSITION, offset_x / xresolution);
682       TIFFSetField (tif, TIFFTAG_YPOSITION, offset_y / yresolution);
683     }
684 
685   if (! is_bw &&
686       (drawable_type == GIMP_INDEXED_IMAGE || drawable_type == GIMP_INDEXEDA_IMAGE))
687     TIFFSetField (tif, TIFFTAG_COLORMAP, red, grn, blu);
688 
689   /* save path data. we need layer information for that,
690     * so we have to do this in here. :-( */
691   if (page == 0)
692     save_paths (tif, orig_image, cols, rows, offset_x, offset_y);
693 
694   /* array to rearrange data */
695   src  = g_new (guchar, bytesperrow * tile_height);
696   data = g_new (guchar, bytesperrow);
697 
698   /* Now write the TIFF data. */
699   for (y = 0; y < rows; y = yend)
700     {
701       yend = y + tile_height;
702       yend = MIN (yend, rows);
703 
704       gegl_buffer_get (buffer,
705                        GEGL_RECTANGLE (0, y, cols, yend - y), 1.0,
706                        format, src,
707                        GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
708 
709       for (row = y; row < yend; row++)
710         {
711           guchar *t = src + bytesperrow * (row - y);
712 
713           switch (drawable_type)
714             {
715             case GIMP_INDEXED_IMAGE:
716             case GIMP_INDEXEDA_IMAGE:
717               if (is_bw)
718                 {
719                   byte2bit (t, bytesperrow, data, invert);
720                   success = (TIFFWriteScanline (tif, data, row, 0) >= 0);
721                 }
722               else
723                 {
724                   success = (TIFFWriteScanline (tif, t, row, 0) >= 0);
725                 }
726               break;
727 
728             case GIMP_GRAY_IMAGE:
729             case GIMP_GRAYA_IMAGE:
730             case GIMP_RGB_IMAGE:
731             case GIMP_RGBA_IMAGE:
732               success = (TIFFWriteScanline (tif, t, row, 0) >= 0);
733               break;
734 
735             default:
736               success = FALSE;
737               break;
738             }
739 
740           if (!success)
741             {
742               g_message (_("Failed a scanline write on row %d"), row);
743               goto out;
744             }
745         }
746 
747       if ((row % 32) == 0)
748         gimp_progress_update (progress_base + progress_fraction
749                               * (gdouble) row / (gdouble) rows);
750     }
751 
752   /* Save GeoTIFF tags to file, if available */
753   if (tsvals->save_geotiff)
754     {
755       GimpParasite *parasite = NULL;
756 
757       parasite = gimp_image_get_parasite (image,"Gimp_GeoTIFF_ModelPixelScale");
758 
759       if (parasite)
760         {
761           TIFFSetField (tif,
762                         GEOTIFF_MODELPIXELSCALE,
763                         (gimp_parasite_data_size (parasite) / TIFFDataWidth (TIFF_DOUBLE)),
764                         gimp_parasite_data (parasite));
765           gimp_parasite_free (parasite);
766         }
767 
768       parasite = gimp_image_get_parasite (image,"Gimp_GeoTIFF_ModelTiePoint");
769       if (parasite)
770         {
771           TIFFSetField (tif,
772                         GEOTIFF_MODELTIEPOINT,
773                         (gimp_parasite_data_size (parasite) / TIFFDataWidth (TIFF_DOUBLE)),
774                         gimp_parasite_data (parasite));
775           gimp_parasite_free (parasite);
776         }
777 
778       parasite = gimp_image_get_parasite (image,"Gimp_GeoTIFF_ModelTransformation");
779       if (parasite)
780         {
781           TIFFSetField (tif,
782                         GEOTIFF_MODELTRANSFORMATION,
783                         (gimp_parasite_data_size (parasite) / TIFFDataWidth (TIFF_DOUBLE)),
784                         gimp_parasite_data (parasite));
785           gimp_parasite_free (parasite);
786         }
787 
788       parasite = gimp_image_get_parasite (image,"Gimp_GeoTIFF_KeyDirectory");
789       if (parasite)
790         {
791           TIFFSetField (tif,
792                         GEOTIFF_KEYDIRECTORY,
793                         (gimp_parasite_data_size (parasite) / TIFFDataWidth (TIFF_SHORT)),
794                         gimp_parasite_data (parasite));
795           gimp_parasite_free (parasite);
796         }
797 
798       parasite = gimp_image_get_parasite (image,"Gimp_GeoTIFF_DoubleParams");
799       if (parasite)
800         {
801           TIFFSetField (tif,
802                         GEOTIFF_DOUBLEPARAMS,
803                         (gimp_parasite_data_size (parasite) / TIFFDataWidth (TIFF_DOUBLE)),
804                         gimp_parasite_data (parasite));
805           gimp_parasite_free (parasite);
806         }
807 
808       parasite = gimp_image_get_parasite (image,"Gimp_GeoTIFF_Asciiparams");
809       if (parasite)
810         {
811           TIFFSetField (tif,
812                         GEOTIFF_ASCIIPARAMS,
813                         gimp_parasite_data (parasite));
814           gimp_parasite_free (parasite);
815         }
816     }
817 
818   TIFFWriteDirectory (tif);
819 
820   gimp_progress_update (progress_base + progress_fraction);
821 
822   status = TRUE;
823 
824 out:
825   if (buffer)
826     g_object_unref (buffer);
827 
828   g_free (data);
829   g_free (src);
830   g_free (layer_name);
831 
832   return status;
833 }
834 
835 /* FIXME Most of the stuff in save_metadata except the
836  * thumbnail saving should probably be moved to
837  * gimpmetadata.c and gimpmetadata-save.c.
838  */
839 static void
save_metadata(GFile * file,TiffSaveVals * tsvals,gint32 image,GimpMetadata * metadata,GimpMetadataSaveFlags metadata_flags,gint saved_bpp)840 save_metadata (GFile                 *file,
841                TiffSaveVals          *tsvals,
842                gint32                 image,
843                GimpMetadata          *metadata,
844                GimpMetadataSaveFlags  metadata_flags,
845                gint                   saved_bpp)
846 {
847   gchar **exif_tags;
848 
849   /* See bug 758909: clear TIFFTAG_MIN/MAXSAMPLEVALUE because
850    * exiv2 saves them with wrong type and the original values
851    * could be invalid, see also bug 761823.
852    * we also clear some other tags that were only meaningful
853    * for the original imported image.
854    */
855   static const gchar *exif_tags_to_remove[] =
856   {
857     "Exif.Image.0x0118",  /* MinSampleValue */
858     "Exif.Image.0x0119",  /* MaxSampleValue */
859     "Exif.Image.0x011d",  /* PageName */
860     "Exif.Image.Compression",
861     "Exif.Image.FillOrder",
862     "Exif.Image.InterColorProfile",
863     "Exif.Image.NewSubfileType",
864     "Exif.Image.PageNumber",
865     "Exif.Image.PhotometricInterpretation",
866     "Exif.Image.PlanarConfiguration",
867     "Exif.Image.Predictor",
868     "Exif.Image.RowsPerStrip",
869     "Exif.Image.SampleFormat",
870     "Exif.Image.SamplesPerPixel",
871     "Exif.Image.StripByteCounts",
872     "Exif.Image.StripOffsets"
873   };
874   static const guint n_keys = G_N_ELEMENTS(exif_tags_to_remove);
875 
876   for (int k = 0; k < n_keys; k++)
877     {
878       gexiv2_metadata_clear_tag (GEXIV2_METADATA (metadata),
879                                  exif_tags_to_remove[k]);
880     }
881 
882   /* get rid of all the EXIF tags for anything but the first sub image. */
883   exif_tags = gexiv2_metadata_get_exif_tags (GEXIV2_METADATA(metadata));
884   for (char **tag = exif_tags; *tag; tag++)
885     {
886       /* Keeping Exif.Image2, 3 can cause exiv2 to save faulty extra TIFF pages
887        * that are empty except for the Exif metadata. See issue #7195. */
888       if (g_str_has_prefix (*tag, "Exif.Image")
889           && (*tag)[strlen ("Exif.Image")] >= '0'
890           && (*tag)[strlen ("Exif.Image")] <= '9')
891         gexiv2_metadata_clear_tag (GEXIV2_METADATA (metadata), *tag);
892       if (g_str_has_prefix (*tag, "Exif.SubImage")
893           && (*tag)[strlen ("Exif.SubImage")] >= '0'
894           && (*tag)[strlen ("Exif.SubImage")] <= '9')
895         gexiv2_metadata_clear_tag (GEXIV2_METADATA (metadata), *tag);
896       if (g_str_has_prefix (*tag, "Exif.Thumbnail"))
897         gexiv2_metadata_clear_tag (GEXIV2_METADATA (metadata), *tag);
898     }
899 
900   gimp_metadata_set_bits_per_sample (metadata, saved_bpp);
901 
902   if (tsvals->save_exif)
903     metadata_flags |= GIMP_METADATA_SAVE_EXIF;
904   else
905     metadata_flags &= ~GIMP_METADATA_SAVE_EXIF;
906 
907   if (tsvals->save_xmp)
908     metadata_flags |= GIMP_METADATA_SAVE_XMP;
909   else
910     metadata_flags &= ~GIMP_METADATA_SAVE_XMP;
911 
912   if (tsvals->save_iptc)
913     metadata_flags |= GIMP_METADATA_SAVE_IPTC;
914   else
915     metadata_flags &= ~GIMP_METADATA_SAVE_IPTC;
916 
917   if (tsvals->save_thumbnail)
918     metadata_flags |= GIMP_METADATA_SAVE_THUMBNAIL;
919   else
920     metadata_flags &= ~GIMP_METADATA_SAVE_THUMBNAIL;
921 
922   if (tsvals->save_profile)
923     metadata_flags |= GIMP_METADATA_SAVE_COLOR_PROFILE;
924   else
925     metadata_flags &= ~GIMP_METADATA_SAVE_COLOR_PROFILE;
926 
927   gimp_image_metadata_save_finish (image,
928                                    "image/tiff",
929                                    metadata, metadata_flags,
930                                    file, NULL);
931 }
932 
933 gboolean
save_image(GFile * file,TiffSaveVals * tsvals,gint32 image,gint32 orig_image,const gchar * image_comment,gint * saved_bpp,GimpMetadata * metadata,GimpMetadataSaveFlags metadata_flags,GError ** error)934 save_image (GFile                  *file,
935             TiffSaveVals           *tsvals,
936             gint32                  image,
937             gint32                  orig_image,    /* the export function */
938                                                    /* might have created  */
939                                                    /* a duplicate         */
940             const gchar            *image_comment,
941             gint                   *saved_bpp,
942             GimpMetadata           *metadata,
943             GimpMetadataSaveFlags   metadata_flags,
944             GError                **error)
945 {
946   TIFF     *tif = NULL;
947   gboolean  status              = FALSE;
948   gboolean  out_linear          = FALSE;
949   gint32    num_layers, *layers, current_layer = 0;
950   gint      origin_x = 0, origin_y = 0;
951   gint32    i;
952 
953   layers = gimp_image_get_layers (image, &num_layers);
954 
955   gimp_progress_init_printf (_("Exporting '%s'"),
956                              gimp_file_get_utf8_name (file));
957 
958   /* Open file and write some global data */
959   tif = tiff_open (file, "w", error);
960 
961   if (! tif)
962     {
963       if (! error)
964         g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
965                      _("Could not open '%s' for writing: %s"),
966                      gimp_file_get_utf8_name (file), g_strerror (errno));
967       goto out;
968     }
969 
970   /* The TIFF spec explicitly says ASCII for the image description. */
971   if (image_comment)
972     {
973       const gchar *c = image_comment;
974       gint         len;
975 
976       for (len = strlen (c); len; c++, len--)
977         {
978           if ((guchar) *c > 127)
979             {
980               g_message (_("The TIFF format only supports comments in\n"
981                            "7bit ASCII encoding. No comment is saved."));
982               image_comment = NULL;
983 
984               break;
985             }
986         }
987     }
988 
989   /* do we have a comment?  If so, create a new parasite to hold it,
990    * and attach it to the image. The attach function automatically
991    * detaches a previous incarnation of the parasite. */
992   if (image_comment && *image_comment)
993     {
994       GimpParasite *parasite;
995 
996       TIFFSetField (tif, TIFFTAG_IMAGEDESCRIPTION, image_comment);
997       parasite = gimp_parasite_new ("gimp-comment",
998                                     GIMP_PARASITE_PERSISTENT,
999                                     strlen (image_comment) + 1, image_comment);
1000       gimp_image_attach_parasite (orig_image, parasite);
1001       gimp_parasite_free (parasite);
1002     }
1003 
1004 #ifdef TIFFTAG_ICCPROFILE
1005   if (tsvals->save_profile)
1006     {
1007       GimpColorProfile *profile;
1008       const guint8     *icc_data;
1009       gsize             icc_length;
1010 
1011       profile = gimp_image_get_effective_color_profile (orig_image);
1012 
1013       /* Curve of the exported data depends on the saved profile, i.e.
1014        * any explicitly-set profile in priority, or the default one for
1015        * the storage format as fallback.
1016        */
1017       out_linear = (gimp_color_profile_is_linear (profile));
1018 
1019       /* Write the profile to the TIFF file. */
1020       icc_data = gimp_color_profile_get_icc_profile (profile, &icc_length);
1021       TIFFSetField (tif, TIFFTAG_ICCPROFILE, icc_length, icc_data);
1022       g_object_unref (profile);
1023     }
1024 #endif
1025 
1026   /* calculate the top-left coordinates */
1027   for (i = 0; i < num_layers; i++)
1028     {
1029       gint offset_x, offset_y;
1030 
1031       gimp_drawable_offsets (layers[i], &offset_x, &offset_y);
1032 
1033       origin_x = MIN (origin_x, offset_x);
1034       origin_y = MIN (origin_y, offset_y);
1035     }
1036 
1037   /* write last layer as first page. */
1038   if (! save_layer (tif,  tsvals, image,
1039                     layers[num_layers - current_layer - 1],
1040                     current_layer, num_layers, orig_image,
1041                     origin_x, origin_y,
1042                     saved_bpp, out_linear, error))
1043     {
1044       goto out;
1045     }
1046   current_layer++;
1047 
1048   /* close file so we can safely let exiv2 work on it to write metadata.
1049    * this can be simplified once multi page TIFF is supported by exiv2
1050    */
1051   TIFFFlushData (tif);
1052   TIFFClose (tif);
1053   tif = NULL;
1054   if (metadata)
1055     save_metadata (file, tsvals, image, metadata, metadata_flags, *saved_bpp);
1056 
1057   /* write the remaining layers */
1058   if (num_layers > 1)
1059     {
1060       tif = tiff_open (file, "a", error);
1061 
1062       if (! tif)
1063         {
1064           if (! error)
1065             g_set_error (error, G_FILE_ERROR,
1066                           g_file_error_from_errno (errno),
1067                           _("Could not open '%s' for writing: %s"),
1068                           gimp_file_get_utf8_name (file),
1069                           g_strerror (errno));
1070           goto out;
1071         }
1072 
1073       for (; current_layer < num_layers; current_layer++)
1074         {
1075           gint tmp_saved_bpp;
1076           if (! save_layer (tif,  tsvals, image,
1077                             layers[num_layers - current_layer - 1],
1078                             current_layer, num_layers, orig_image,
1079                             origin_x, origin_y,
1080                             &tmp_saved_bpp, out_linear, error))
1081             {
1082               goto out;
1083             }
1084           if (tmp_saved_bpp != *saved_bpp)
1085             {
1086               /* this should never happen.
1087                * if it does, decide if it's really an error.
1088                */
1089               g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1090                            _("Writing pages with different bit depth "
1091                              "is strange."));
1092               goto out;
1093             }
1094           gimp_progress_update ((gdouble) (current_layer + 1) / num_layers);
1095         }
1096     }
1097 
1098   status = TRUE;
1099 
1100 out:
1101   /* close the file for good */
1102   if (tif)
1103     {
1104       TIFFFlushData (tif);
1105       TIFFClose (tif);
1106     }
1107 
1108   gimp_progress_update (1.0);
1109 
1110   return status;
1111 }
1112 
1113 gboolean
save_dialog(TiffSaveVals * tsvals,gint32 image,const gchar * help_id,gboolean has_alpha,gboolean is_monochrome,gboolean is_indexed,gchar ** image_comment)1114 save_dialog (TiffSaveVals  *tsvals,
1115              gint32         image,
1116              const gchar   *help_id,
1117              gboolean       has_alpha,
1118              gboolean       is_monochrome,
1119              gboolean       is_indexed,
1120              gchar        **image_comment)
1121 {
1122   GError      *error = NULL;
1123   GtkWidget   *dialog;
1124   GtkWidget   *vbox;
1125   GtkWidget   *frame;
1126   GtkWidget   *entry;
1127   GtkWidget   *toggle;
1128   GtkWidget   *cmp_g3;
1129   GtkWidget   *cmp_g4;
1130   GtkWidget   *cmp_jpeg;
1131   GtkBuilder  *builder;
1132   gchar       *ui_file;
1133   gchar      **parasites;
1134   gboolean     run;
1135   gboolean     has_geotiff = FALSE;
1136   gint         n_parasites;
1137   gint         i;
1138 
1139   parasites = gimp_image_get_parasite_list (image, &n_parasites);
1140   for (i = 0; i < n_parasites; i++)
1141     {
1142       if (g_str_has_prefix (parasites[i], "Gimp_GeoTIFF_"))
1143         {
1144           has_geotiff = TRUE;
1145           break;
1146         }
1147     }
1148   g_strfreev (parasites);
1149 
1150   dialog = gimp_export_dialog_new (_("TIFF"), PLUG_IN_ROLE, help_id);
1151 
1152   builder = gtk_builder_new ();
1153   ui_file = g_build_filename (gimp_data_directory (),
1154                               "ui", "plug-ins", "plug-in-file-tiff.ui",
1155                               NULL);
1156   if (! gtk_builder_add_from_file (builder, ui_file, &error))
1157     {
1158       gchar *display_name = g_filename_display_name (ui_file);
1159 
1160       g_printerr (_("Error loading UI file '%s': %s"),
1161                   display_name, error ? error->message : _("Unknown error"));
1162 
1163       g_free (display_name);
1164     }
1165 
1166   g_free (ui_file);
1167 
1168   vbox = GTK_WIDGET (gtk_builder_get_object (builder, "tiff_export_vbox"));
1169 
1170   gtk_box_pack_start (GTK_BOX (gimp_export_dialog_get_content_area (dialog)),
1171                       vbox, FALSE, FALSE, 0);
1172   gtk_widget_show (vbox);
1173 
1174   vbox = GTK_WIDGET (gtk_builder_get_object (builder, "radio_button_box"));
1175 
1176   frame = gimp_int_radio_group_new (TRUE, _("Compression"),
1177                                     G_CALLBACK (gimp_radio_button_update),
1178                                     &tsvals->compression, tsvals->compression,
1179 
1180                                     _("_None"),      COMPRESSION_NONE,          NULL,
1181                                     _("_LZW"),       COMPRESSION_LZW,           NULL,
1182                                     _("_Pack Bits"), COMPRESSION_PACKBITS,      NULL,
1183                                     _("_Deflate"),   COMPRESSION_ADOBE_DEFLATE, NULL,
1184                                     _("_JPEG"),      COMPRESSION_JPEG,          &cmp_jpeg,
1185                                     _("CCITT Group _3 fax"), COMPRESSION_CCITTFAX3, &cmp_g3,
1186                                     _("CCITT Group _4 fax"), COMPRESSION_CCITTFAX4, &cmp_g4,
1187 
1188                                     NULL);
1189 
1190   gtk_widget_set_sensitive (cmp_g3, is_monochrome);
1191   gtk_widget_set_sensitive (cmp_g4, is_monochrome);
1192   gtk_widget_set_sensitive (cmp_jpeg, ! is_indexed);
1193 
1194   if (! is_monochrome)
1195     {
1196       if (tsvals->compression == COMPRESSION_CCITTFAX3 ||
1197           tsvals->compression == COMPRESSION_CCITTFAX4)
1198         {
1199           gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (cmp_g3),
1200                                            COMPRESSION_NONE);
1201         }
1202     }
1203 
1204   if (is_indexed && tsvals->compression == COMPRESSION_JPEG)
1205     {
1206       gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (cmp_jpeg),
1207                                        COMPRESSION_NONE);
1208     }
1209 
1210   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1211   gtk_widget_show (frame);
1212 
1213   toggle = GTK_WIDGET (gtk_builder_get_object (builder, "save-alpha"));
1214   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
1215                                 has_alpha && (tsvals->save_transp_pixels || is_indexed));
1216   gtk_widget_set_sensitive (toggle, has_alpha && ! is_indexed);
1217   g_signal_connect (toggle, "toggled",
1218                     G_CALLBACK (gimp_toggle_button_update),
1219                     &tsvals->save_transp_pixels);
1220 
1221   entry = GTK_WIDGET (gtk_builder_get_object (builder, "commentfield"));
1222   gtk_entry_set_text (GTK_ENTRY (entry), *image_comment ? *image_comment : "");
1223 
1224   g_signal_connect (entry, "changed",
1225                     G_CALLBACK (comment_entry_callback),
1226                     image_comment);
1227 
1228   toggle = GTK_WIDGET (gtk_builder_get_object (builder, "save-exif"));
1229   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
1230                                 tsvals->save_exif);
1231   g_signal_connect (toggle, "toggled",
1232                     G_CALLBACK (gimp_toggle_button_update),
1233                     &tsvals->save_exif);
1234 
1235   toggle = GTK_WIDGET (gtk_builder_get_object (builder, "save-xmp"));
1236   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
1237                                 tsvals->save_xmp);
1238   g_signal_connect (toggle, "toggled",
1239                     G_CALLBACK (gimp_toggle_button_update),
1240                     &tsvals->save_xmp);
1241 
1242   toggle = GTK_WIDGET (gtk_builder_get_object (builder, "save-iptc"));
1243   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
1244                                 tsvals->save_iptc);
1245   g_signal_connect (toggle, "toggled",
1246                     G_CALLBACK (gimp_toggle_button_update),
1247                     &tsvals->save_iptc);
1248 
1249   toggle = GTK_WIDGET (gtk_builder_get_object (builder, "save-geotiff"));
1250   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
1251                                 has_geotiff && tsvals->save_geotiff);
1252   gtk_widget_set_sensitive (toggle, has_geotiff);;
1253   g_signal_connect (toggle, "toggled",
1254                     G_CALLBACK (gimp_toggle_button_update),
1255                     &tsvals->save_geotiff);
1256 
1257   toggle = GTK_WIDGET (gtk_builder_get_object (builder, "save-thumbnail"));
1258   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
1259                                 tsvals->save_thumbnail);
1260   g_signal_connect (toggle, "toggled",
1261                     G_CALLBACK (gimp_toggle_button_update),
1262                     &tsvals->save_thumbnail);
1263 
1264   toggle = GTK_WIDGET (gtk_builder_get_object (builder, "save-color-profile"));
1265 #ifdef TIFFTAG_ICCPROFILE
1266   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
1267                                 tsvals->save_profile);
1268   g_signal_connect (toggle, "toggled",
1269                     G_CALLBACK (gimp_toggle_button_update),
1270                     &tsvals->save_profile);
1271 #else
1272   gtk_widget_hide (toggle);
1273 #endif
1274 
1275   toggle = GTK_WIDGET (gtk_builder_get_object (builder, "save-layers"));
1276   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
1277                                 tsvals->save_layers);
1278   g_signal_connect (toggle, "toggled",
1279                     G_CALLBACK (gimp_toggle_button_update),
1280                     &tsvals->save_layers);
1281 
1282   frame = GTK_WIDGET (gtk_builder_get_object (builder, "layers-frame"));
1283   g_object_bind_property (toggle, "active",
1284                           frame,  "sensitive",
1285                           G_BINDING_SYNC_CREATE);
1286 
1287   toggle = GTK_WIDGET (gtk_builder_get_object (builder, "crop-layers"));
1288   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
1289                                 tsvals->crop_layers);
1290   g_signal_connect (toggle, "toggled",
1291                     G_CALLBACK (gimp_toggle_button_update),
1292                     &tsvals->crop_layers);
1293 
1294   gtk_widget_show (dialog);
1295 
1296   run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
1297 
1298   gtk_widget_destroy (dialog);
1299 
1300   return run;
1301 }
1302 
1303 static void
comment_entry_callback(GtkWidget * widget,gchar ** comment)1304 comment_entry_callback (GtkWidget  *widget,
1305                         gchar     **comment)
1306 {
1307   const gchar *text = gtk_entry_get_text (GTK_ENTRY (widget));
1308 
1309   g_free (*comment);
1310   *comment = g_strdup (text);
1311 }
1312 
1313 /* Convert n bytes of 0/1 to a line of bits */
1314 static void
byte2bit(const guchar * byteline,gint width,guchar * bitline,gboolean invert)1315 byte2bit (const guchar *byteline,
1316           gint          width,
1317           guchar       *bitline,
1318           gboolean      invert)
1319 {
1320   guchar bitval;
1321   guchar rest[8];
1322 
1323   while (width >= 8)
1324     {
1325       bitval = 0;
1326       if (*(byteline++)) bitval |= 0x80;
1327       if (*(byteline++)) bitval |= 0x40;
1328       if (*(byteline++)) bitval |= 0x20;
1329       if (*(byteline++)) bitval |= 0x10;
1330       if (*(byteline++)) bitval |= 0x08;
1331       if (*(byteline++)) bitval |= 0x04;
1332       if (*(byteline++)) bitval |= 0x02;
1333       if (*(byteline++)) bitval |= 0x01;
1334       *(bitline++) = invert ? ~bitval : bitval;
1335       width -= 8;
1336     }
1337 
1338   if (width > 0)
1339     {
1340       memset (rest, 0, 8);
1341       memcpy (rest, byteline, width);
1342       bitval = 0;
1343       byteline = rest;
1344       if (*(byteline++)) bitval |= 0x80;
1345       if (*(byteline++)) bitval |= 0x40;
1346       if (*(byteline++)) bitval |= 0x20;
1347       if (*(byteline++)) bitval |= 0x10;
1348       if (*(byteline++)) bitval |= 0x08;
1349       if (*(byteline++)) bitval |= 0x04;
1350       if (*(byteline++)) bitval |= 0x02;
1351       *bitline = invert ? ~bitval & (0xff << (8 - width)) : bitval;
1352     }
1353 }
1354