1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 
3 /*
4  *  GThumb
5  *
6  *  Copyright (C) 2009 Free Software Foundation, Inc.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 #ifdef HAVE_LIBTIFF
24 #include <tiffio.h>
25 #endif /* HAVE_LIBTIFF */
26 #include <glib/gi18n.h>
27 #include <gthumb.h>
28 #include "cairo-io-enum-types.h"
29 #include "gth-image-saver-tiff.h"
30 #include "preferences.h"
31 
32 
33 struct _GthImageSaverTiffPrivate {
34 	GSettings  *settings;
35 	GtkBuilder *builder;
36 	char       *default_ext;
37 };
38 
39 
G_DEFINE_TYPE_WITH_CODE(GthImageSaverTiff,gth_image_saver_tiff,GTH_TYPE_IMAGE_SAVER,G_ADD_PRIVATE (GthImageSaverTiff))40 G_DEFINE_TYPE_WITH_CODE (GthImageSaverTiff,
41 			 gth_image_saver_tiff,
42 			 GTH_TYPE_IMAGE_SAVER,
43 			 G_ADD_PRIVATE (GthImageSaverTiff))
44 
45 
46 static void
47 gth_image_saver_tiff_finalize (GObject *object)
48 {
49 	GthImageSaverTiff *self = GTH_IMAGE_SAVER_TIFF (object);
50 
51 	_g_object_unref (self->priv->settings);
52 	_g_object_unref (self->priv->builder);
53 	g_free (self->priv->default_ext);
54 
55 	G_OBJECT_CLASS (gth_image_saver_tiff_parent_class)->finalize (object);
56 }
57 
58 
59 static const char *
gth_image_saver_tiff_get_default_ext(GthImageSaver * base)60 gth_image_saver_tiff_get_default_ext (GthImageSaver *base)
61 {
62 	GthImageSaverTiff *self = GTH_IMAGE_SAVER_TIFF (base);
63 
64 	if (self->priv->default_ext == NULL)
65 		self->priv->default_ext = g_settings_get_string (self->priv->settings, PREF_TIFF_DEFAULT_EXT);
66 
67 	return self->priv->default_ext;
68 }
69 
70 
71 static GtkWidget *
gth_image_saver_tiff_get_control(GthImageSaver * base)72 gth_image_saver_tiff_get_control (GthImageSaver *base)
73 {
74 #ifdef HAVE_LIBTIFF
75 
76 	GthImageSaverTiff  *self = GTH_IMAGE_SAVER_TIFF (base);
77 	char              **extensions;
78 	int                 i;
79 	int                 active_idx;
80 	GthTiffCompression  compression_type;
81 
82 	_g_object_unref (self->priv->builder);
83 	self->priv->builder = _gtk_builder_new_from_file ("tiff-options.ui", "cairo_io");
84 
85 	active_idx = 0;
86 	extensions = g_strsplit (gth_image_saver_get_extensions (base), " ", -1);
87 	for (i = 0; extensions[i] != NULL; i++) {
88 		GtkTreeIter iter;
89 
90 		gtk_list_store_append (GTK_LIST_STORE (gtk_builder_get_object (self->priv->builder, "tiff_default_ext_liststore")), &iter);
91 		gtk_list_store_set (GTK_LIST_STORE (gtk_builder_get_object (self->priv->builder, "tiff_default_ext_liststore")),
92 				    &iter,
93 				    0, extensions[i],
94 				    -1);
95 		if (g_str_equal (extensions[i], gth_image_saver_get_default_ext (base)))
96 			active_idx = i;
97 	}
98 	gtk_combo_box_set_active (GTK_COMBO_BOX (_gtk_builder_get_widget (self->priv->builder, "tiff_default_extension_combobox")), active_idx);
99 	g_strfreev (extensions);
100 
101 	compression_type = g_settings_get_enum (self->priv->settings, PREF_TIFF_COMPRESSION);
102 	switch (compression_type) {
103 	case GTH_TIFF_COMPRESSION_NONE:
104 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_comp_none_radiobutton")), TRUE);
105 		break;
106 	case GTH_TIFF_COMPRESSION_DEFLATE:
107 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_comp_deflate_radiobutton")), TRUE);
108 		break;
109 	case GTH_TIFF_COMPRESSION_JPEG:
110 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_comp_jpeg_radiobutton")), TRUE);
111 		break;
112 	}
113 
114 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_hdpi_spinbutton")),
115 				   g_settings_get_int (self->priv->settings, PREF_TIFF_HORIZONTAL_RES));
116 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_vdpi_spinbutton")),
117 				   g_settings_get_int (self->priv->settings, PREF_TIFF_VERTICAL_RES));
118 
119 	return _gtk_builder_get_widget (self->priv->builder, "tiff_options");
120 
121 #else /* ! HAVE_LIBTIFF */
122 
123 	return GTH_IMAGE_SAVER_CLASS (gth_image_saver_tiff_parent_class)->get_control (base);
124 
125 #endif /* HAVE_LIBTIFF */
126 }
127 
128 
129 static void
gth_image_saver_tiff_save_options(GthImageSaver * base)130 gth_image_saver_tiff_save_options (GthImageSaver *base)
131 {
132 #ifdef HAVE_LIBTIFF
133 
134 	GthImageSaverTiff  *self = GTH_IMAGE_SAVER_TIFF (base);
135 	GtkTreeIter         iter;
136 	GthTiffCompression  compression_type;
137 
138 	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (_gtk_builder_get_widget (self->priv->builder, "tiff_default_extension_combobox")), &iter)) {
139 		g_free (self->priv->default_ext);
140 		gtk_tree_model_get (GTK_TREE_MODEL (gtk_builder_get_object (self->priv->builder, "tiff_default_ext_liststore")),
141 				    &iter,
142 				    0, &self->priv->default_ext,
143 				    -1);
144 		g_settings_set_string (self->priv->settings, PREF_TIFF_DEFAULT_EXT, self->priv->default_ext);
145 	}
146 
147 	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_comp_none_radiobutton"))))
148 		compression_type = GTH_TIFF_COMPRESSION_NONE;
149 	else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_comp_deflate_radiobutton"))))
150 		compression_type = GTH_TIFF_COMPRESSION_DEFLATE;
151 	else
152 		compression_type = GTH_TIFF_COMPRESSION_JPEG;
153 	g_settings_set_enum (self->priv->settings, PREF_TIFF_COMPRESSION, compression_type);
154 
155 	g_settings_set_int (self->priv->settings, PREF_TIFF_HORIZONTAL_RES, (int) gtk_spin_button_get_value (GTK_SPIN_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_hdpi_spinbutton"))));
156 	g_settings_set_int (self->priv->settings, PREF_TIFF_VERTICAL_RES, (int) gtk_spin_button_get_value (GTK_SPIN_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_vdpi_spinbutton"))));
157 
158 #endif /* HAVE_LIBTIFF */
159 }
160 
161 
162 static gboolean
gth_image_saver_tiff_can_save(GthImageSaver * self,const char * mime_type)163 gth_image_saver_tiff_can_save (GthImageSaver *self,
164 			       const char    *mime_type)
165 {
166 #ifdef HAVE_LIBTIFF
167 
168 	return g_content_type_equals (mime_type, "image/tiff");
169 
170 #else /* ! HAVE_LIBTIFF */
171 
172 	GSList          *formats;
173 	GSList          *scan;
174 	GdkPixbufFormat *tiff_format;
175 
176 	if (! g_content_type_equals (mime_type, "image/tiff"))
177 		return FALSE;
178 
179 	formats = gdk_pixbuf_get_formats ();
180 	tiff_format = NULL;
181 	for (scan = formats; (tiff_format == NULL) && (scan != NULL); scan = g_slist_next (scan)) {
182 		GdkPixbufFormat  *format = scan->data;
183 		char            **mime_types;
184 		int               i;
185 
186 		mime_types = gdk_pixbuf_format_get_mime_types (format);
187 		for (i = 0; mime_types[i] != NULL; i++)
188 			if (g_content_type_equals (mime_types[i], "image/tiff"))
189 				break;
190 
191 		if (mime_types[i] == NULL)
192 			continue;
193 
194 		if (! gdk_pixbuf_format_is_writable (format))
195 			continue;
196 
197 		tiff_format = format;
198 	}
199 
200 	return tiff_format != NULL;
201 
202 #endif /* HAVE_LIBTIFF */
203 }
204 
205 
206 #ifdef HAVE_LIBTIFF
207 
208 
209 /* -- gth_image_saver_tiff_save_pixbuf -- */
210 
211 
212 #define TILE_HEIGHT 40   /* FIXME */
213 
214 
215 static tsize_t
tiff_read(thandle_t handle,tdata_t buf,tsize_t size)216 tiff_read (thandle_t handle, tdata_t buf, tsize_t size)
217 {
218 	return -1;
219 }
220 
221 
222 static tsize_t
tiff_write(thandle_t handle,tdata_t buf,tsize_t size)223 tiff_write (thandle_t handle, tdata_t buf, tsize_t size)
224 {
225         GthBufferData *buffer_data = (GthBufferData *)handle;
226 
227         gth_buffer_data_write (buffer_data, buf, size, NULL);
228         return size;
229 }
230 
231 
232 static toff_t
tiff_seek(thandle_t handle,toff_t offset,int whence)233 tiff_seek (thandle_t handle, toff_t offset, int whence)
234 {
235 	GthBufferData *buffer_data = (GthBufferData *)handle;
236 
237 	return gth_buffer_data_seek (buffer_data, offset, whence);
238 }
239 
240 
241 static int
tiff_close(thandle_t context)242 tiff_close (thandle_t context)
243 {
244         return 0;
245 }
246 
247 
248 static toff_t
tiff_size(thandle_t handle)249 tiff_size (thandle_t handle)
250 {
251         return -1;
252 }
253 
254 
255 static gboolean
_cairo_surface_write_as_tiff(cairo_surface_t * image,char ** buffer,gsize * buffer_size,char ** keys,char ** values,GError ** error)256 _cairo_surface_write_as_tiff (cairo_surface_t  *image,
257 			      char            **buffer,
258 			      gsize            *buffer_size,
259 			      char            **keys,
260 			      char            **values,
261 			      GError          **error)
262 {
263 	GthBufferData *buffer_data;
264 	TIFF          *tif;
265 	int            cols, rows, row;
266 	glong          rowsperstrip;
267 	gushort        compression;
268 	int            alpha;
269 	gshort         predictor;
270 	gshort         photometric;
271 	gshort         samplesperpixel;
272 	gshort         bitspersample;
273 	gushort        extra_samples[1];
274 	int            rowstride;
275 	guchar        *pixels, *ptr, *buf;
276 	int            horizontal_dpi = 72, vertical_dpi = 72;
277 	gboolean       save_resolution = FALSE;
278 
279 	compression = COMPRESSION_DEFLATE;
280 
281 	if (keys && *keys) {
282 		char **kiter = keys;
283 		char **viter = values;
284 
285 		while (*kiter) {
286 			if (strcmp (*kiter, "compression") == 0) {
287 				if (*viter == NULL) {
288 					g_set_error (error,
289 						     GDK_PIXBUF_ERROR,
290 						     GDK_PIXBUF_ERROR_BAD_OPTION,
291 						     "Must specify a compression type");
292 					return FALSE;
293 				}
294 
295 				if (strcmp (*viter, "none") == 0)
296 					compression = COMPRESSION_NONE;
297 				else if (strcmp (*viter, "pack bits") == 0)
298 					compression = COMPRESSION_PACKBITS;
299 				else if (strcmp (*viter, "lzw") == 0)
300 					compression = COMPRESSION_LZW;
301 				else if (strcmp (*viter, "deflate") == 0)
302 					compression = COMPRESSION_DEFLATE;
303 				else if (strcmp (*viter, "jpeg") == 0)
304 					compression = COMPRESSION_JPEG;
305 				else {
306 					g_set_error (error,
307 						     GDK_PIXBUF_ERROR,
308 						     GDK_PIXBUF_ERROR_BAD_OPTION,
309 						     "Unsupported compression type passed to the TIFF saver");
310 					return FALSE;
311 				}
312 			}
313 			else if (strcmp (*kiter, "vertical dpi") == 0) {
314 				char *endptr = NULL;
315 				vertical_dpi = strtol (*viter, &endptr, 10);
316 				save_resolution = TRUE;
317 
318 				if (endptr == *viter) {
319 					g_set_error (error,
320 						     GDK_PIXBUF_ERROR,
321 						     GDK_PIXBUF_ERROR_BAD_OPTION,
322 						     "TIFF vertical dpi must be a value greater than 0; value '%s' could not be parsed.",
323 						     *viter);
324 					return FALSE;
325 				}
326 
327 				if (vertical_dpi < 0) {
328 					g_set_error (error,
329 						     GDK_PIXBUF_ERROR,
330 						     GDK_PIXBUF_ERROR_BAD_OPTION,
331 						     "TIFF vertical dpi must be a value greater than 0; value '%d' is not allowed.",
332 						     vertical_dpi);
333 					return FALSE;
334 				}
335 			}
336 			else if (strcmp (*kiter, "horizontal dpi") == 0) {
337 				char *endptr = NULL;
338 				horizontal_dpi = strtol (*viter, &endptr, 10);
339 				save_resolution = TRUE;
340 
341 				if (endptr == *viter) {
342 					g_set_error (error,
343 						     GDK_PIXBUF_ERROR,
344 						     GDK_PIXBUF_ERROR_BAD_OPTION,
345 						     "TIFF horizontal dpi must be a value greater than 0; value '%s' could not be parsed.",
346 						     *viter);
347 					return FALSE;
348 				}
349 
350 				if (horizontal_dpi < 0) {
351 					g_set_error (error,
352 						     GDK_PIXBUF_ERROR,
353 						     GDK_PIXBUF_ERROR_BAD_OPTION,
354 						     "TIFF horizontal dpi must be a value greater than 0; value '%d' is not allowed.",
355 						     horizontal_dpi);
356 					return FALSE;
357 				}
358 			}
359 			else {
360 				g_warning ("Bad option name '%s' passed to the TIFF saver", *kiter);
361 				return FALSE;
362 			}
363 
364 			++kiter;
365 			++viter;
366 		}
367 	}
368 
369 	predictor    = 0;
370 	rowsperstrip = TILE_HEIGHT;
371 
372 	buffer_data = gth_buffer_data_new ();
373 	tif = TIFFClientOpen ("gth-tiff-writer", "w",
374 			      buffer_data,
375 	                      tiff_read,
376 	                      tiff_write,
377 	                      tiff_seek,
378 	                      tiff_close,
379 	                      tiff_size,
380 	                      NULL,
381 	                      NULL);
382 	if (tif == NULL) {
383 		g_set_error_literal (error,
384 				     GDK_PIXBUF_ERROR,
385 				     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
386 				     "Couldn't allocate memory for writing TIFF file");
387 		return FALSE;
388 	}
389 
390 	cols      = cairo_image_surface_get_width (image);
391 	rows      = cairo_image_surface_get_height (image);
392 	alpha     = _cairo_image_surface_get_has_alpha (image);
393 	pixels    = _cairo_image_surface_flush_and_get_data (image);
394 	rowstride = cairo_image_surface_get_stride (image);
395 
396 	predictor       = 2;
397 	bitspersample   = 8;
398 	photometric     = PHOTOMETRIC_RGB;
399 
400 	if (alpha)
401 		samplesperpixel = 4;
402 	else
403 		samplesperpixel = 3;
404 
405 	/* Set TIFF parameters. */
406 
407 	TIFFSetField (tif, TIFFTAG_SUBFILETYPE,   0);
408 	TIFFSetField (tif, TIFFTAG_IMAGEWIDTH,    cols);
409 	TIFFSetField (tif, TIFFTAG_IMAGELENGTH,   rows);
410 	TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, bitspersample);
411 	TIFFSetField (tif, TIFFTAG_ORIENTATION,   ORIENTATION_TOPLEFT);
412 	TIFFSetField (tif, TIFFTAG_COMPRESSION,   compression);
413 
414 	if ((compression == COMPRESSION_LZW || compression == COMPRESSION_DEFLATE)
415 	    && (predictor != 0))
416 	{
417 		TIFFSetField (tif, TIFFTAG_PREDICTOR, predictor);
418 	}
419 
420 	if (alpha) {
421 		extra_samples [0] = EXTRASAMPLE_ASSOCALPHA;
422 		TIFFSetField (tif, TIFFTAG_EXTRASAMPLES, 1, extra_samples);
423 	}
424 
425 	TIFFSetField (tif, TIFFTAG_PHOTOMETRIC,     photometric);
426 	/*TIFFSetField (tif, TIFFTAG_DOCUMENTNAME,    filename);*/
427 	TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
428 	TIFFSetField (tif, TIFFTAG_ROWSPERSTRIP,    rowsperstrip);
429 	TIFFSetField (tif, TIFFTAG_PLANARCONFIG,    PLANARCONFIG_CONTIG);
430 
431 	if (save_resolution) {
432 		TIFFSetField (tif, TIFFTAG_XRESOLUTION, (double) horizontal_dpi);
433 		TIFFSetField (tif, TIFFTAG_YRESOLUTION, (double) vertical_dpi);
434 		TIFFSetField (tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
435 	}
436 
437 	buf = g_try_malloc (cols * samplesperpixel * sizeof (guchar));
438 	if (! buf) {
439 		g_set_error_literal (error,
440 				     GDK_PIXBUF_ERROR,
441 				     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
442 				     _("Insufficient memory"));
443 		return FALSE;
444 	}
445 
446 	/* Now write the TIFF data. */
447 	ptr = pixels;
448 	for (row = 0; row < rows; row++) {
449 		_cairo_copy_line_as_rgba_big_endian (buf, ptr, cols, alpha);
450 		if (TIFFWriteScanline (tif, buf, row, 0) < 0) {
451 			g_set_error (error,
452 				     GDK_PIXBUF_ERROR,
453 				     GDK_PIXBUF_ERROR_FAILED,
454 				     "TIFF Failed a scanline write on row %d",
455 				     row);
456 			return FALSE;
457 		}
458 
459 		ptr += rowstride;
460 	}
461 
462 	g_free (buf);
463 
464 	TIFFFlushData (tif);
465 	TIFFClose (tif);
466 
467 	gth_buffer_data_get (buffer_data, buffer, buffer_size);
468 	gth_buffer_data_free (buffer_data, FALSE);
469 
470 	return TRUE;
471 }
472 
473 
474 #endif /* HAVE_LIBTIFF */
475 
476 
477 static gboolean
gth_image_saver_tiff_save_image(GthImageSaver * base,GthImage * image,char ** buffer,gsize * buffer_size,const char * mime_type,GCancellable * cancellable,GError ** error)478 gth_image_saver_tiff_save_image (GthImageSaver  *base,
479 				 GthImage       *image,
480 				 char          **buffer,
481 				 gsize          *buffer_size,
482 				 const char     *mime_type,
483 				 GCancellable   *cancellable,
484 				 GError        **error)
485 {
486 #ifdef HAVE_LIBTIFF
487 	GthImageSaverTiff  *self = GTH_IMAGE_SAVER_TIFF (base);
488 	char    	  **option_keys;
489 	char              **option_values;
490 	int                 i = -1;
491 	int                 i_value;
492 	cairo_surface_t    *surface;
493 	gboolean            result;
494 
495 	option_keys = g_malloc (sizeof (char *) * 4);
496 	option_values = g_malloc (sizeof (char *) * 4);
497 
498 	i++;
499 	option_keys[i] = g_strdup ("compression");;
500 	option_values[i] = g_settings_get_string (self->priv->settings, PREF_TIFF_COMPRESSION);
501 
502 	i++;
503 	i_value = g_settings_get_int (self->priv->settings, PREF_TIFF_VERTICAL_RES);
504 	option_keys[i] = g_strdup ("vertical dpi");;
505 	option_values[i] = g_strdup_printf ("%d", i_value);
506 
507 	i++;
508 	i_value = g_settings_get_int (self->priv->settings, PREF_TIFF_HORIZONTAL_RES);
509 	option_keys[i] = g_strdup ("horizontal dpi");;
510 	option_values[i] = g_strdup_printf ("%d", i_value);
511 
512 	i++;
513 	option_keys[i] = NULL;
514 	option_values[i] = NULL;
515 
516 	surface = gth_image_get_cairo_surface (image);
517 	result = _cairo_surface_write_as_tiff (surface,
518 					       buffer,
519 					       buffer_size,
520 					       option_keys,
521 					       option_values,
522 					       error);
523 
524 	cairo_surface_destroy (surface);
525 	g_strfreev (option_keys);
526 	g_strfreev (option_values);
527 
528 #else /* ! HAVE_LIBTIFF */
529 
530 	GdkPixbuf *pixbuf;
531 	char      *pixbuf_type;
532 	gboolean   result;
533 
534 	pixbuf = gth_image_get_pixbuf (image);
535 	pixbuf_type = _gdk_pixbuf_get_type_from_mime_type (mime_type);
536 	result = gdk_pixbuf_save_to_bufferv (pixbuf,
537 					     buffer,
538 					     buffer_size,
539 					     pixbuf_type,
540 					     NULL,
541 					     NULL,
542 					     error);
543 
544 	g_free (pixbuf_type);
545 	g_object_unref (pixbuf);
546 
547 #endif /* HAVE_LIBTIFF */
548 
549 	return result;
550 }
551 
552 
553 static void
gth_image_saver_tiff_class_init(GthImageSaverTiffClass * klass)554 gth_image_saver_tiff_class_init (GthImageSaverTiffClass *klass)
555 {
556 	GObjectClass       *object_class;
557 	GthImageSaverClass *image_saver_class;
558 
559 	object_class = G_OBJECT_CLASS (klass);
560 	object_class->finalize = gth_image_saver_tiff_finalize;
561 
562 	image_saver_class = GTH_IMAGE_SAVER_CLASS (klass);
563 	image_saver_class->id = "tiff";
564 	image_saver_class->display_name = _("TIFF");
565 	image_saver_class->mime_type = "image/tiff";
566 	image_saver_class->extensions = "tiff tif";
567 	image_saver_class->get_default_ext = gth_image_saver_tiff_get_default_ext;
568 	image_saver_class->get_control = gth_image_saver_tiff_get_control;
569 	image_saver_class->save_options = gth_image_saver_tiff_save_options;
570 	image_saver_class->can_save = gth_image_saver_tiff_can_save;
571 	image_saver_class->save_image = gth_image_saver_tiff_save_image;
572 }
573 
574 
575 static void
gth_image_saver_tiff_init(GthImageSaverTiff * self)576 gth_image_saver_tiff_init (GthImageSaverTiff *self)
577 {
578 	self->priv = gth_image_saver_tiff_get_instance_private (self);
579 	self->priv->settings = g_settings_new (GTHUMB_IMAGE_SAVERS_TIFF_SCHEMA);
580 	self->priv->builder = NULL;
581 	self->priv->default_ext = NULL;
582 }
583