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