1 /* Eye Of Gnome - Image
2  *
3  * Copyright (C) 2006 The Free Software Foundation
4  *
5  * Author: Lucas Rocha <lucasr@gnome.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #define GDK_PIXBUF_ENABLE_BACKEND
27 
28 #include "eog-image.h"
29 #include "eog-image-private.h"
30 #include "eog-debug.h"
31 
32 #ifdef HAVE_JPEG
33 #include "eog-image-jpeg.h"
34 #endif
35 
36 #include "eog-marshal.h"
37 #include "eog-pixbuf-util.h"
38 #include "eog-metadata-reader.h"
39 #include "eog-image-save-info.h"
40 #include "eog-transform.h"
41 #include "eog-util.h"
42 #include "eog-jobs.h"
43 #include "eog-thumbnail.h"
44 
45 #include <unistd.h>
46 #include <string.h>
47 
48 #include <glib.h>
49 #include <glib-object.h>
50 #include <glib/gi18n.h>
51 #include <gtk/gtk.h>
52 #include <gdk-pixbuf/gdk-pixbuf.h>
53 
54 #ifdef HAVE_EXIF
55 #include "eog-exif-util.h"
56 #include <libexif/exif-data.h>
57 #include <libexif/exif-utils.h>
58 #include <libexif/exif-loader.h>
59 #endif
60 
61 #ifdef HAVE_EXEMPI
62 #include <exempi/xmp.h>
63 #endif
64 
65 #ifdef HAVE_LCMS
66 #include <lcms2.h>
67 #ifndef EXIF_TAG_GAMMA
68 #define EXIF_TAG_GAMMA 0xa500
69 #endif
70 #endif
71 
72 #ifdef HAVE_RSVG
73 #include <librsvg/rsvg.h>
74 #endif
75 
76 G_DEFINE_TYPE_WITH_PRIVATE (EogImage, eog_image, G_TYPE_OBJECT)
77 
78 enum {
79 	SIGNAL_CHANGED,
80 	SIGNAL_SIZE_PREPARED,
81 	SIGNAL_THUMBNAIL_CHANGED,
82 	SIGNAL_SAVE_PROGRESS,
83 	SIGNAL_NEXT_FRAME,
84 	SIGNAL_FILE_CHANGED,
85 	SIGNAL_LAST
86 };
87 
88 static gint signals[SIGNAL_LAST];
89 
90 static GList *supported_mime_types = NULL;
91 
92 #define EOG_IMAGE_READ_BUFFER_SIZE 65535
93 
94 static void
eog_image_free_mem_private(EogImage * image)95 eog_image_free_mem_private (EogImage *image)
96 {
97 	EogImagePrivate *priv;
98 
99 	priv = image->priv;
100 
101 	if (priv->status == EOG_IMAGE_STATUS_LOADING) {
102 		eog_image_cancel_load (image);
103 	} else {
104 		if (priv->anim_source != 0) {
105 			g_source_remove (priv->anim_source);
106 			priv->anim_source = 0;
107 		}
108 
109 		if (priv->anim_iter != NULL) {
110 			g_object_unref (priv->anim_iter);
111 			priv->anim_iter = NULL;
112 		}
113 
114 		if (priv->anim != NULL) {
115 			g_object_unref (priv->anim);
116 			priv->anim = NULL;
117 		}
118 
119 		priv->is_playing = FALSE;
120 
121 		if (priv->image != NULL) {
122 			g_object_unref (priv->image);
123 			priv->image = NULL;
124 		}
125 
126 #ifdef HAVE_RSVG
127 		if (priv->svg != NULL) {
128 			g_object_unref (priv->svg);
129 			priv->svg = NULL;
130 		}
131 #endif
132 
133 #ifdef HAVE_EXIF
134 		if (priv->exif != NULL) {
135 			exif_data_unref (priv->exif);
136 			priv->exif = NULL;
137 		}
138 #endif
139 
140 		if (priv->exif_chunk != NULL) {
141 			g_free (priv->exif_chunk);
142 			priv->exif_chunk = NULL;
143 		}
144 
145 		priv->exif_chunk_len = 0;
146 
147 #ifdef HAVE_EXEMPI
148 		if (priv->xmp != NULL) {
149 			xmp_free (priv->xmp);
150 			priv->xmp = NULL;
151 		}
152 #endif
153 
154 #ifdef HAVE_LCMS
155 		if (priv->profile != NULL) {
156 			cmsCloseProfile (priv->profile);
157 			priv->profile = NULL;
158 		}
159 #endif
160 
161 		priv->status = EOG_IMAGE_STATUS_UNKNOWN;
162 		priv->metadata_status = EOG_IMAGE_METADATA_NOT_READ;
163 	}
164 }
165 
166 static void
eog_image_dispose(GObject * object)167 eog_image_dispose (GObject *object)
168 {
169 	EogImagePrivate *priv;
170 
171 	priv = EOG_IMAGE (object)->priv;
172 
173 	eog_image_free_mem_private (EOG_IMAGE (object));
174 
175 	if (priv->file) {
176 		g_object_unref (priv->file);
177 		priv->file = NULL;
178 	}
179 
180 	if (priv->caption) {
181 		g_free (priv->caption);
182 		priv->caption = NULL;
183 	}
184 
185 	if (priv->collate_key) {
186 		g_free (priv->collate_key);
187 		priv->collate_key = NULL;
188 	}
189 
190 	if (priv->file_type) {
191 		g_free (priv->file_type);
192 		priv->file_type = NULL;
193 	}
194 
195 	g_mutex_clear (&priv->status_mutex);
196 
197 	if (priv->trans) {
198 		g_object_unref (priv->trans);
199 		priv->trans = NULL;
200 	}
201 
202 	if (priv->trans_autorotate) {
203 		g_object_unref (priv->trans_autorotate);
204 		priv->trans_autorotate = NULL;
205 	}
206 
207 	if (priv->undo_stack) {
208 		g_slist_foreach (priv->undo_stack, (GFunc) g_object_unref, NULL);
209 		g_slist_free (priv->undo_stack);
210 		priv->undo_stack = NULL;
211 	}
212 
213 	G_OBJECT_CLASS (eog_image_parent_class)->dispose (object);
214 }
215 
216 static void
eog_image_finalize(GObject * object)217 eog_image_finalize (GObject *object)
218 {
219 	EogImagePrivate *priv;
220 
221 	priv = EOG_IMAGE (object)->priv;
222 
223 	g_mutex_clear (&priv->status_mutex);
224 
225 	G_OBJECT_CLASS (eog_image_parent_class)->finalize (object);
226 }
227 
228 static void
eog_image_class_init(EogImageClass * klass)229 eog_image_class_init (EogImageClass *klass)
230 {
231 	GObjectClass *object_class = (GObjectClass*) klass;
232 
233 	object_class->dispose = eog_image_dispose;
234 	object_class->finalize = eog_image_finalize;
235 
236 	signals[SIGNAL_SIZE_PREPARED] =
237 		g_signal_new ("size-prepared",
238 			      EOG_TYPE_IMAGE,
239 			      G_SIGNAL_RUN_LAST,
240 			      G_STRUCT_OFFSET (EogImageClass, size_prepared),
241 			      NULL, NULL,
242 			      eog_marshal_VOID__INT_INT,
243 			      G_TYPE_NONE, 2,
244 			      G_TYPE_INT,
245 			      G_TYPE_INT);
246 
247 	signals[SIGNAL_CHANGED] =
248 		g_signal_new ("changed",
249 			      EOG_TYPE_IMAGE,
250 			      G_SIGNAL_RUN_LAST,
251 			      G_STRUCT_OFFSET (EogImageClass, changed),
252 			      NULL, NULL,
253 			      g_cclosure_marshal_VOID__VOID,
254 			      G_TYPE_NONE, 0);
255 
256 	signals[SIGNAL_THUMBNAIL_CHANGED] =
257 		g_signal_new ("thumbnail-changed",
258 			      EOG_TYPE_IMAGE,
259 			      G_SIGNAL_RUN_LAST,
260 			      G_STRUCT_OFFSET (EogImageClass, thumbnail_changed),
261 			      NULL, NULL,
262 			      g_cclosure_marshal_VOID__VOID,
263 			      G_TYPE_NONE, 0);
264 
265 	signals[SIGNAL_SAVE_PROGRESS] =
266 		g_signal_new ("save-progress",
267 			      EOG_TYPE_IMAGE,
268 			      G_SIGNAL_RUN_LAST,
269 			      G_STRUCT_OFFSET (EogImageClass, save_progress),
270 			      NULL, NULL,
271 			      g_cclosure_marshal_VOID__FLOAT,
272 			      G_TYPE_NONE, 1,
273 			      G_TYPE_FLOAT);
274  	/**
275  	 * EogImage::next-frame:
276   	 * @img: the object which received the signal.
277 	 * @delay: number of milliseconds the current frame will be displayed.
278 	 *
279 	 * The ::next-frame signal will be emitted each time an animated image
280 	 * advances to the next frame.
281 	 */
282 	signals[SIGNAL_NEXT_FRAME] =
283 		g_signal_new ("next-frame",
284 			      EOG_TYPE_IMAGE,
285 			      G_SIGNAL_RUN_LAST,
286 			      G_STRUCT_OFFSET (EogImageClass, next_frame),
287 			      NULL, NULL,
288 			      g_cclosure_marshal_VOID__INT,
289 			      G_TYPE_NONE, 1,
290 			      G_TYPE_INT);
291 
292 	signals[SIGNAL_FILE_CHANGED] = g_signal_new ("file-changed",
293 						     EOG_TYPE_IMAGE,
294 						     G_SIGNAL_RUN_LAST,
295 						     G_STRUCT_OFFSET (EogImageClass, file_changed),
296 						     NULL, NULL,
297 						     g_cclosure_marshal_VOID__VOID,
298 						     G_TYPE_NONE, 0);
299 }
300 
301 static void
eog_image_init(EogImage * img)302 eog_image_init (EogImage *img)
303 {
304 	img->priv = eog_image_get_instance_private (img);
305 
306 	img->priv->file = NULL;
307 	img->priv->image = NULL;
308 	img->priv->anim = NULL;
309 	img->priv->anim_iter = NULL;
310 	img->priv->is_playing = FALSE;
311 	img->priv->thumbnail = NULL;
312 	img->priv->width = -1;
313 	img->priv->height = -1;
314 	img->priv->modified = FALSE;
315 	img->priv->file_is_changed = FALSE;
316 	g_mutex_init (&img->priv->status_mutex);
317 	img->priv->status = EOG_IMAGE_STATUS_UNKNOWN;
318 	img->priv->metadata_status = EOG_IMAGE_METADATA_NOT_READ;
319 	img->priv->undo_stack = NULL;
320 	img->priv->trans = NULL;
321 	img->priv->trans_autorotate = NULL;
322 	img->priv->data_ref_count = 0;
323 	img->priv->anim_source = 0;
324 #ifdef HAVE_EXIF
325 	img->priv->orientation = 0;
326 	img->priv->autorotate = FALSE;
327 	img->priv->exif = NULL;
328 #endif
329 #ifdef HAVE_EXEMPI
330 	img->priv->xmp = NULL;
331 #endif
332 #ifdef HAVE_LCMS
333 	img->priv->profile = NULL;
334 #endif
335 #ifdef HAVE_RSVG
336 	img->priv->svg = NULL;
337 #endif
338 }
339 
340 EogImage *
eog_image_new_file(GFile * file,const gchar * caption)341 eog_image_new_file (GFile *file, const gchar *caption)
342 {
343 	EogImage *img;
344 
345 	img = EOG_IMAGE (g_object_new (EOG_TYPE_IMAGE, NULL));
346 
347 	img->priv->file = g_object_ref (file);
348 	img->priv->caption = g_strdup (caption);
349 
350 	return img;
351 }
352 
353 GQuark
eog_image_error_quark(void)354 eog_image_error_quark (void)
355 {
356 	static GQuark q = 0;
357 
358 	if (q == 0) {
359 		q = g_quark_from_static_string ("eog-image-error-quark");
360 	}
361 
362 	return q;
363 }
364 
365 static void
eog_image_update_exif_data(EogImage * image)366 eog_image_update_exif_data (EogImage *image)
367 {
368 #ifdef HAVE_EXIF
369 	EogImagePrivate *priv;
370 	ExifEntry *entry;
371 	ExifByteOrder bo;
372 
373 	eog_debug (DEBUG_IMAGE_DATA);
374 
375 	g_return_if_fail (EOG_IS_IMAGE (image));
376 
377 	priv = image->priv;
378 
379 	if (priv->exif == NULL) return;
380 
381 	bo = exif_data_get_byte_order (priv->exif);
382 
383 	/* Update image width */
384 	entry = exif_data_get_entry (priv->exif, EXIF_TAG_PIXEL_X_DIMENSION);
385 	if (entry != NULL && (priv->width >= 0)) {
386 		if (entry->format == EXIF_FORMAT_LONG)
387 			exif_set_long (entry->data, bo, priv->width);
388 		else if (entry->format == EXIF_FORMAT_SHORT)
389 			exif_set_short (entry->data, bo, priv->width);
390 		else
391 			g_warning ("Exif entry has unsupported size");
392 	}
393 
394 	/* Update image height */
395 	entry = exif_data_get_entry (priv->exif, EXIF_TAG_PIXEL_Y_DIMENSION);
396 	if (entry != NULL && (priv->height >= 0)) {
397 		if (entry->format == EXIF_FORMAT_LONG)
398 			exif_set_long (entry->data, bo, priv->height);
399 		else if (entry->format == EXIF_FORMAT_SHORT)
400 			exif_set_short (entry->data, bo, priv->height);
401 		else
402 			g_warning ("Exif entry has unsupported size");
403 	}
404 
405 	/* Update image orientation */
406 	entry = exif_data_get_entry (priv->exif, EXIF_TAG_ORIENTATION);
407 	if (entry != NULL) {
408 		if (entry->format == EXIF_FORMAT_LONG)
409 			exif_set_long (entry->data, bo, 1);
410 		else if (entry->format == EXIF_FORMAT_SHORT)
411 			exif_set_short (entry->data, bo, 1);
412 		else
413 			g_warning ("Exif entry has unsupported size");
414 
415 		priv->orientation = 1;
416 	}
417 #endif
418 }
419 
420 static void
eog_image_real_transform(EogImage * img,EogTransform * trans,gboolean is_undo,EogJob * job)421 eog_image_real_transform (EogImage     *img,
422 			  EogTransform *trans,
423 			  gboolean      is_undo,
424 			  EogJob       *job)
425 {
426 	EogImagePrivate *priv;
427 	GdkPixbuf *transformed;
428 	gboolean modified = FALSE;
429 
430 	g_return_if_fail (EOG_IS_IMAGE (img));
431 	g_return_if_fail (EOG_IS_TRANSFORM (trans));
432 
433 	priv = img->priv;
434 
435 	if (priv->image != NULL) {
436 		transformed = eog_transform_apply (trans, priv->image, job);
437 
438 		g_object_unref (priv->image);
439 		priv->image = transformed;
440 
441 		priv->width = gdk_pixbuf_get_width (transformed);
442 		priv->height = gdk_pixbuf_get_height (transformed);
443 
444 		modified = TRUE;
445 	}
446 
447 	if (priv->thumbnail != NULL) {
448 		transformed = eog_transform_apply (trans, priv->thumbnail, NULL);
449 
450 		g_object_unref (priv->thumbnail);
451 		priv->thumbnail = transformed;
452 
453 		modified = TRUE;
454 	}
455 
456 	if (modified) {
457 		priv->modified = TRUE;
458 		eog_image_update_exif_data (img);
459 	}
460 
461 	if (priv->trans == NULL) {
462 		g_object_ref (trans);
463 		priv->trans = trans;
464 	} else {
465 		EogTransform *composition;
466 
467 		composition = eog_transform_compose (priv->trans, trans);
468 
469 		g_object_unref (priv->trans);
470 
471 		priv->trans = composition;
472 	}
473 
474 	if (!is_undo) {
475 		g_object_ref (trans);
476 		priv->undo_stack = g_slist_prepend (priv->undo_stack, trans);
477 	}
478 }
479 
480 static gboolean
do_emit_size_prepared_signal(EogImage * img)481 do_emit_size_prepared_signal (EogImage *img)
482 {
483 	g_signal_emit (img, signals[SIGNAL_SIZE_PREPARED], 0,
484 		       img->priv->width, img->priv->height);
485 	return FALSE;
486 }
487 
488 static void
eog_image_emit_size_prepared(EogImage * img)489 eog_image_emit_size_prepared (EogImage *img)
490 {
491 	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
492 			 (GSourceFunc) do_emit_size_prepared_signal,
493 			 g_object_ref (img), g_object_unref);
494 }
495 
496 static void
eog_image_size_prepared(GdkPixbufLoader * loader,gint width,gint height,gpointer data)497 eog_image_size_prepared (GdkPixbufLoader *loader,
498 			 gint             width,
499 			 gint             height,
500 			 gpointer         data)
501 {
502 	EogImage *img;
503 
504 	eog_debug (DEBUG_IMAGE_LOAD);
505 
506 	g_return_if_fail (EOG_IS_IMAGE (data));
507 
508 	img = EOG_IMAGE (data);
509 
510 	g_mutex_lock (&img->priv->status_mutex);
511 
512 	img->priv->width = width;
513 	img->priv->height = height;
514 
515 	g_mutex_unlock (&img->priv->status_mutex);
516 
517 #ifdef HAVE_EXIF
518 	if (!img->priv->autorotate || img->priv->exif)
519 #endif
520 		eog_image_emit_size_prepared (img);
521 }
522 
523 static EogMetadataReader*
check_for_metadata_img_format(EogImage * img,guchar * buffer,guint bytes_read)524 check_for_metadata_img_format (EogImage *img, guchar *buffer, guint bytes_read)
525 {
526 	EogMetadataReader *md_reader = NULL;
527 
528 	eog_debug_message (DEBUG_IMAGE_DATA, "Check image format for jpeg: %x%x - length: %i",
529 			   buffer[0], buffer[1], bytes_read);
530 
531 	if (bytes_read >= 2) {
532 		/* SOI (start of image) marker for JPEGs is 0xFFD8 */
533 		if ((buffer[0] == 0xFF) && (buffer[1] == 0xD8)) {
534 			md_reader = eog_metadata_reader_new (EOG_METADATA_JPEG);
535 		}
536 		if (bytes_read >= 8 &&
537 		    memcmp (buffer, "\x89PNG\x0D\x0A\x1a\x0A", 8) == 0) {
538 			md_reader = eog_metadata_reader_new (EOG_METADATA_PNG);
539 		}
540 	}
541 
542 	return md_reader;
543 }
544 
545 static gboolean
eog_image_needs_transformation(EogImage * img)546 eog_image_needs_transformation (EogImage *img)
547 {
548 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
549 
550 	return (img->priv->trans != NULL || img->priv->trans_autorotate != NULL);
551 }
552 
553 static gboolean
eog_image_apply_transformations(EogImage * img,GError ** error)554 eog_image_apply_transformations (EogImage *img, GError **error)
555 {
556 	GdkPixbuf *transformed = NULL;
557 	EogTransform *composition = NULL;
558 	EogImagePrivate *priv;
559 
560 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
561 
562 	priv = img->priv;
563 
564 	if (priv->trans == NULL && priv->trans_autorotate == NULL) {
565 		return TRUE;
566 	}
567 
568 	if (priv->image == NULL) {
569 		g_set_error (error,
570 			     EOG_IMAGE_ERROR,
571 			     EOG_IMAGE_ERROR_NOT_LOADED,
572 			     _("Transformation on unloaded image."));
573 
574 		return FALSE;
575 	}
576 
577 	if (priv->trans != NULL && priv->trans_autorotate != NULL) {
578 		composition = eog_transform_compose (priv->trans,
579 						     priv->trans_autorotate);
580 	} else if (priv->trans != NULL) {
581 		composition = g_object_ref (priv->trans);
582 	} else if (priv->trans_autorotate != NULL) {
583 		composition = g_object_ref (priv->trans_autorotate);
584 	}
585 
586 	if (composition != NULL) {
587 		transformed = eog_transform_apply (composition, priv->image, NULL);
588 	}
589 
590 	g_object_unref (priv->image);
591 	priv->image = transformed;
592 
593 	if (transformed != NULL) {
594 		priv->width = gdk_pixbuf_get_width (priv->image);
595 		priv->height = gdk_pixbuf_get_height (priv->image);
596 	} else {
597 		g_set_error (error,
598 			     EOG_IMAGE_ERROR,
599 			     EOG_IMAGE_ERROR_GENERIC,
600 			     _("Transformation failed."));
601  	}
602 
603 	g_object_unref (composition);
604 
605 	return (transformed != NULL);
606 }
607 
608 static void
eog_image_get_file_info(EogImage * img,goffset * bytes,gchar ** mime_type,GError ** error)609 eog_image_get_file_info (EogImage *img,
610 			 goffset *bytes,
611 			 gchar **mime_type,
612 			 GError **error)
613 {
614 	GFileInfo *file_info;
615 
616 	file_info = g_file_query_info (img->priv->file,
617 				       G_FILE_ATTRIBUTE_STANDARD_SIZE ","
618 				       G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
619 				       0, NULL, error);
620 
621 	if (file_info == NULL) {
622 		if (bytes)
623 			*bytes = 0;
624 
625 		if (mime_type)
626 			*mime_type = NULL;
627 	} else {
628 		if (bytes)
629 			*bytes = g_file_info_get_size (file_info);
630 
631 		if (mime_type)
632 			*mime_type = g_strdup (g_file_info_get_content_type (file_info));
633 		g_object_unref (file_info);
634 	}
635 }
636 
637 #ifdef HAVE_LCMS
638 void
eog_image_apply_display_profile(EogImage * img,cmsHPROFILE screen)639 eog_image_apply_display_profile (EogImage *img, cmsHPROFILE screen)
640 {
641 	EogImagePrivate *priv;
642 	cmsHTRANSFORM transform;
643 	gint row, width, rows, stride;
644 	guchar *p;
645 
646 	g_return_if_fail (img != NULL);
647 
648 	priv = img->priv;
649 
650 	if (screen == NULL) return;
651 
652 	if (priv->profile == NULL) {
653 		/* Check whether GdkPixbuf was able to extract a profile */
654 		const char* data = gdk_pixbuf_get_option (priv->image,
655 		                                          "icc-profile");
656 
657 		if(data) {
658 			gsize   profile_size = 0;
659 			guchar *profile_data = g_base64_decode(data,
660 			                                       &profile_size);
661 
662 			if (profile_data && profile_size > 0) {
663 				eog_debug_message (DEBUG_LCMS,
664 				                   "Using ICC profile "
665 				                   "extracted by GdkPixbuf");
666 				priv->profile =
667 					cmsOpenProfileFromMem(profile_data,
668 					                      profile_size);
669 				g_free(profile_data);
670 			}
671 		}
672 
673 		if(priv->profile == NULL) {
674 			/* Assume sRGB color space for images without ICC profile */
675 			eog_debug_message (DEBUG_LCMS, "Image has no ICC profile. "
676 					   "Assuming sRGB.");
677 			priv->profile = cmsCreate_sRGBProfile ();
678 		}
679 	}
680 
681 	/* TODO: support other colorspaces than RGB */
682 	if (cmsGetColorSpace (priv->profile) != cmsSigRgbData ||
683 	    cmsGetColorSpace (screen) != cmsSigRgbData) {
684 		eog_debug_message (DEBUG_LCMS, "One or both ICC profiles not in RGB colorspace; not correcting");
685 		return;
686 	}
687 
688 	cmsUInt32Number color_type = TYPE_RGB_8;
689 
690 	if (gdk_pixbuf_get_has_alpha (priv->image))
691 		color_type = TYPE_RGBA_8;
692 
693 	transform = cmsCreateTransform (priv->profile,
694 	                                color_type,
695 	                                screen,
696 	                                color_type,
697 	                                INTENT_PERCEPTUAL,
698 	                                0);
699 
700 	if (G_LIKELY (transform != NULL)) {
701 		rows = gdk_pixbuf_get_height (priv->image);
702 		width = gdk_pixbuf_get_width (priv->image);
703 		stride = gdk_pixbuf_get_rowstride (priv->image);
704 		p = gdk_pixbuf_get_pixels (priv->image);
705 
706 		for (row = 0; row < rows; ++row) {
707 			cmsDoTransform (transform, p, p, width);
708 			p += stride;
709 		}
710 		cmsDeleteTransform (transform);
711 	}
712 }
713 
714 static void
eog_image_set_icc_data(EogImage * img,EogMetadataReader * md_reader)715 eog_image_set_icc_data (EogImage *img, EogMetadataReader *md_reader)
716 {
717 	EogImagePrivate *priv = img->priv;
718 
719 	priv->profile = eog_metadata_reader_get_icc_profile (md_reader);
720 
721 
722 }
723 #endif
724 
725 static void
eog_image_set_orientation(EogImage * img)726 eog_image_set_orientation (EogImage *img)
727 {
728 	EogImagePrivate *priv;
729 #ifdef HAVE_EXIF
730 	ExifData* exif;
731 #endif
732 
733 	g_return_if_fail (EOG_IS_IMAGE (img));
734 
735 	priv = img->priv;
736 
737 #ifdef HAVE_EXIF
738 	exif = (ExifData*) eog_image_get_exif_info (img);
739 
740 	if (exif != NULL) {
741 		ExifByteOrder o = exif_data_get_byte_order (exif);
742 
743 		ExifEntry *entry = exif_data_get_entry (exif,
744 							EXIF_TAG_ORIENTATION);
745 
746 		if (entry && entry->data != NULL) {
747 			priv->orientation = exif_get_short (entry->data, o);
748 		}
749 
750 		exif_data_unref (exif);
751 	} else
752 #endif
753 	{
754 		GdkPixbuf *pbuf;
755 
756 		pbuf = eog_image_get_pixbuf (img);
757 
758 		if (pbuf) {
759 			const gchar *o_str;
760 
761 			o_str = gdk_pixbuf_get_option (pbuf, "orientation");
762 			if (o_str) {
763 				short t = (short) g_ascii_strtoll (o_str,
764 								   NULL, 10);
765 				if (t >= 0 && t < 9)
766 					priv->orientation = t;
767 			}
768 			g_object_unref (pbuf);
769 		}
770 	}
771 
772 	if (priv->orientation > 4 &&
773 	    priv->orientation < 9) {
774 		gint tmp;
775 
776 		tmp = priv->width;
777 		priv->width = priv->height;
778 		priv->height = tmp;
779 	}
780 }
781 
782 static void
eog_image_real_autorotate(EogImage * img)783 eog_image_real_autorotate (EogImage *img)
784 {
785 	static const EogTransformType lookup[8] = {EOG_TRANSFORM_NONE,
786 					     EOG_TRANSFORM_FLIP_HORIZONTAL,
787 					     EOG_TRANSFORM_ROT_180,
788 					     EOG_TRANSFORM_FLIP_VERTICAL,
789 					     EOG_TRANSFORM_TRANSPOSE,
790 					     EOG_TRANSFORM_ROT_90,
791 					     EOG_TRANSFORM_TRANSVERSE,
792 					     EOG_TRANSFORM_ROT_270};
793 	EogImagePrivate *priv;
794 	EogTransformType type;
795 
796 	g_return_if_fail (EOG_IS_IMAGE (img));
797 
798 	priv = img->priv;
799 
800 	type = (priv->orientation >= 1 && priv->orientation <= 8 ?
801 		lookup[priv->orientation - 1] : EOG_TRANSFORM_NONE);
802 
803 	if (type != EOG_TRANSFORM_NONE) {
804 		img->priv->trans_autorotate = eog_transform_new (type);
805 	}
806 
807 	/* Disable auto orientation for next loads */
808 	priv->autorotate = FALSE;
809 }
810 
811 void
eog_image_autorotate(EogImage * img)812 eog_image_autorotate (EogImage *img)
813 {
814 	g_return_if_fail (EOG_IS_IMAGE (img));
815 
816 	/* Schedule auto orientation */
817 	img->priv->autorotate = TRUE;
818 }
819 
820 #ifdef HAVE_EXEMPI
821 static void
eog_image_set_xmp_data(EogImage * img,EogMetadataReader * md_reader)822 eog_image_set_xmp_data (EogImage *img, EogMetadataReader *md_reader)
823 {
824 	EogImagePrivate *priv;
825 
826 	g_return_if_fail (EOG_IS_IMAGE (img));
827 
828 	priv = img->priv;
829 
830 	if (priv->xmp) {
831 		xmp_free (priv->xmp);
832 	}
833 	priv->xmp = eog_metadata_reader_get_xmp_data (md_reader);
834 }
835 #endif
836 
837 static void
eog_image_set_exif_data(EogImage * img,EogMetadataReader * md_reader)838 eog_image_set_exif_data (EogImage *img, EogMetadataReader *md_reader)
839 {
840 	EogImagePrivate *priv;
841 
842 	g_return_if_fail (EOG_IS_IMAGE (img));
843 
844 	priv = img->priv;
845 
846 #ifdef HAVE_EXIF
847 	g_mutex_lock (&priv->status_mutex);
848 	if (priv->exif) {
849 		exif_data_unref (priv->exif);
850 	}
851 	priv->exif = eog_metadata_reader_get_exif_data (md_reader);
852 	g_mutex_unlock (&priv->status_mutex);
853 
854 	priv->exif_chunk = NULL;
855 	priv->exif_chunk_len = 0;
856 
857 	/* EXIF data is already available, set the image orientation */
858 	if (priv->autorotate) {
859 		eog_image_set_orientation (img);
860 
861 		/* Emit size prepared signal if we have the size */
862 		if (priv->width > 0 &&
863 		    priv->height > 0) {
864 			eog_image_emit_size_prepared (img);
865 		}
866 	}
867 #else
868 	if (priv->exif_chunk) {
869 		g_free (priv->exif_chunk);
870 	}
871 	eog_metadata_reader_get_exif_chunk (md_reader,
872 					    &priv->exif_chunk,
873 					    &priv->exif_chunk_len);
874 #endif
875 }
876 
877 /*
878  * Attempts to get the image dimensions from the thumbnail.
879  * Returns FALSE if this information is not found.
880  **/
881 static gboolean
eog_image_get_dimension_from_thumbnail(EogImage * image,gint * width,gint * height)882 eog_image_get_dimension_from_thumbnail (EogImage *image,
883 			                gint     *width,
884 			                gint     *height)
885 {
886 	if (image->priv->thumbnail == NULL)
887 		return FALSE;
888 
889 	*width = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (image->priv->thumbnail),
890 						     EOG_THUMBNAIL_ORIGINAL_WIDTH));
891 	*height = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (image->priv->thumbnail),
892 						      EOG_THUMBNAIL_ORIGINAL_HEIGHT));
893 
894 	return (*width || *height);
895 }
896 
897 static GdkPixbufLoader *
eog_image_new_pixbuf_loader(EogImage * img,gboolean * is_svg,gchar * mime_type,GError ** error)898 eog_image_new_pixbuf_loader (EogImage 	*img,
899 			     gboolean   *is_svg,
900 			     gchar 	*mime_type,
901 			     GError 	**error)
902 {
903 	EogImagePrivate *priv = img->priv;
904 	GdkPixbufLoader *loader = NULL;
905 #ifdef HAVE_RSVG
906 	if (priv->svg != NULL) {
907 		g_object_unref (priv->svg);
908 		priv->svg = NULL;
909 	}
910 
911 	if (!g_strcmp0 (mime_type, "image/svg+xml")
912 		    || !g_strcmp0 (mime_type, "image/svg+xml-compressed")
913 	    ) {
914 		/* Keep the object for rendering */
915 		priv->svg = rsvg_handle_new ();
916 		rsvg_handle_set_base_gfile (priv->svg, priv->file);
917 
918 		/* Use 96dpi when rendering SVG documents with units
919 		 * different then pixels. This value is specified in
920 		 * the CSS standard on which SVG depends. */
921 		rsvg_handle_set_dpi_x_y (priv->svg, 96.0, 96.0);
922 		*is_svg = TRUE;
923 	}
924 #endif
925 
926 	if (!(*is_svg)) {
927 		if (G_LIKELY (mime_type))
928 			loader = gdk_pixbuf_loader_new_with_mime_type (mime_type,
929 								       error);
930 
931 		if (loader == NULL) {
932 			g_clear_error (error);
933 
934 			loader = gdk_pixbuf_loader_new ();
935 		}
936 
937 		g_signal_connect_object (G_OBJECT (loader),
938 				"size-prepared",
939 				G_CALLBACK (eog_image_size_prepared),
940 				img,
941 				0);
942 	}
943 	return loader;
944 }
945 
946 static gboolean
eog_image_update_stream(EogImage * img,gchar * old_mime_type,gchar * new_mimetype,GFileInputStream * input_stream)947 eog_image_update_stream (EogImage	   *img,
948 			 gchar   	   *old_mime_type,
949 			 gchar             *new_mimetype,
950 			 GFileInputStream  *input_stream)
951 {
952 	gboolean success = FALSE;
953 
954 	if (new_mimetype != NULL && strcmp (old_mime_type, new_mimetype) != 0) {
955 		success = g_seekable_seek (G_SEEKABLE (input_stream),
956 					   0, G_SEEK_SET, NULL, NULL);
957 	}
958 	return success;
959 }
960 
961 static gboolean
eog_image_real_load(EogImage * img,EogImageData data2read,EogJob * job,GError ** error)962 eog_image_real_load (EogImage     *img,
963 		     EogImageData  data2read,
964 		     EogJob       *job,
965 		     GError      **error)
966 {
967 	EogImagePrivate *priv;
968 	GFileInputStream *input_stream;
969 	EogMetadataReader *md_reader = NULL;
970 	GdkPixbufFormat *format;
971 	gchar *mime_type;
972 	GdkPixbufLoader *loader = NULL;
973 	guchar *buffer;
974 	goffset bytes_read = 0, bytes_read_total = 0;
975 	gboolean failed = FALSE;
976 	gboolean first_run = TRUE;
977 	gboolean set_metadata = TRUE;
978 	gboolean use_rsvg = FALSE;
979 	gboolean read_image_data = (data2read & EOG_IMAGE_DATA_IMAGE);
980 	gboolean read_only_dimension = (data2read & EOG_IMAGE_DATA_DIMENSION) &&
981 				  ((data2read ^ EOG_IMAGE_DATA_DIMENSION) == 0);
982 
983 
984 	priv = img->priv;
985 
986  	g_assert (!read_image_data || priv->image == NULL);
987 
988 	if (read_image_data && priv->file_type != NULL) {
989 		g_free (priv->file_type);
990 		priv->file_type = NULL;
991 	}
992 
993 	eog_image_get_file_info (img, &priv->bytes, &mime_type, error);
994 
995 	if (error && *error) {
996 		g_free (mime_type);
997 		return FALSE;
998 	}
999 
1000 	if (read_only_dimension) {
1001 		gint width, height;
1002 		gboolean done;
1003 
1004 		done = eog_image_get_dimension_from_thumbnail (img,
1005 							       &width,
1006 							       &height);
1007 
1008 		if (done) {
1009 			priv->width = width;
1010 			priv->height = height;
1011 
1012 			g_free (mime_type);
1013 			return TRUE;
1014 		}
1015 	}
1016 
1017 	input_stream = g_file_read (priv->file, NULL, error);
1018 
1019 	if (input_stream == NULL) {
1020 		g_free (mime_type);
1021 
1022 		if (error != NULL) {
1023 			g_clear_error (error);
1024 			g_set_error (error,
1025 				     EOG_IMAGE_ERROR,
1026 				     EOG_IMAGE_ERROR_VFS,
1027 				     "Failed to open input stream for file");
1028 		}
1029 		return FALSE;
1030 	}
1031 
1032 	buffer = g_new0 (guchar, EOG_IMAGE_READ_BUFFER_SIZE);
1033 
1034 	if (read_image_data || read_only_dimension)
1035 		loader = eog_image_new_pixbuf_loader (img, &use_rsvg, mime_type, error);
1036 
1037 	while (!priv->cancel_loading) {
1038 #ifdef HAVE_RSVG
1039 		if (use_rsvg && first_run && (read_image_data || read_only_dimension)) {
1040 			if (rsvg_handle_read_stream_sync (priv->svg,
1041 							   G_INPUT_STREAM (input_stream),
1042 							   NULL,
1043 							   error))
1044 			{
1045 				/* The entire file is read by now */
1046 				bytes_read_total = priv->bytes;
1047 			} else {
1048 				g_error_free (*error);
1049 				*error = NULL;
1050 
1051 				use_rsvg = FALSE;
1052 				g_object_unref (priv->svg);
1053 				priv->svg = NULL;
1054 
1055 				g_object_unref (input_stream);
1056 				input_stream = g_file_read (priv->file, NULL, error);
1057 				if (input_stream != NULL && *error == NULL) {
1058 					if (loader != NULL)
1059 						g_object_unref (loader);
1060 
1061 					/* We cannot call eog_image_new_pixbuf_loader
1062 					* since we don't have a buffer to guess
1063 					* the mime type. */
1064 					loader = gdk_pixbuf_loader_new ();
1065 					continue;
1066 				} else
1067 					failed = TRUE;
1068 			}
1069 			break;
1070 		} else {
1071 #endif
1072 			/* FIXME: make this async */
1073 			bytes_read = g_input_stream_read (G_INPUT_STREAM (input_stream),
1074 							  buffer,
1075 							  EOG_IMAGE_READ_BUFFER_SIZE,
1076 							  NULL, error);
1077 
1078 			if (bytes_read == 0) {
1079 				/* End of the file */
1080 				break;
1081 			} else if (bytes_read == -1) {
1082 				failed = TRUE;
1083 
1084 				g_set_error (error,
1085 					     EOG_IMAGE_ERROR,
1086 					     EOG_IMAGE_ERROR_VFS,
1087 					     "Failed to read from input stream");
1088 
1089 				break;
1090 			}
1091 
1092 			if ((read_image_data || read_only_dimension)) {
1093 				if (!gdk_pixbuf_loader_write (loader, buffer, bytes_read, error)) {
1094 					gboolean uncertain;
1095 					gchar *new_mimetype = g_content_type_guess (NULL,
1096 										    buffer,
1097 										    EOG_IMAGE_READ_BUFFER_SIZE,
1098 										    &uncertain);
1099 
1100 					if (!uncertain &&
1101 					    eog_image_update_stream (img, mime_type, new_mimetype, input_stream)) {
1102 						g_error_free (*error);
1103 						*error = NULL;
1104 						g_free (mime_type);
1105 						mime_type = g_strdup (new_mimetype);
1106 						loader = eog_image_new_pixbuf_loader (img, &use_rsvg, mime_type, error);
1107 						g_free (new_mimetype);
1108 						continue;
1109 					}
1110 					failed = TRUE;
1111 					break;
1112 				}
1113 			}
1114 
1115 			bytes_read_total += bytes_read;
1116 #ifdef HAVE_RSVG
1117 		}
1118 #endif
1119 
1120 		/* For now allow calling from outside of jobs */
1121 		if (job != NULL)
1122 		{
1123 			/* check that load job wasn't cancelled */
1124 			if (eog_job_is_cancelled (job)) {
1125 				eog_image_cancel_load (img);
1126 				continue;
1127 			} else if (priv->bytes > 0.0) {
1128 				float progress = (float) bytes_read_total / (float) priv->bytes;
1129 				eog_job_set_progress (job, progress);
1130 			}
1131 		}
1132 
1133 		if (first_run) {
1134 			md_reader = check_for_metadata_img_format (img, buffer, bytes_read);
1135 
1136 			if (md_reader == NULL) {
1137 				if (data2read == EOG_IMAGE_DATA_EXIF) {
1138 					g_set_error (error,
1139 						     EOG_IMAGE_ERROR,
1140 						     EOG_IMAGE_ERROR_GENERIC,
1141 						     _("EXIF not supported for this file format."));
1142 					break;
1143 				}
1144 
1145 				priv->metadata_status = EOG_IMAGE_METADATA_NOT_AVAILABLE;
1146 			}
1147 
1148 			first_run = FALSE;
1149 		}
1150 
1151 		if (md_reader != NULL) {
1152 			eog_metadata_reader_consume (md_reader, buffer, bytes_read);
1153 
1154 			if (eog_metadata_reader_finished (md_reader)) {
1155 				if (set_metadata) {
1156 					eog_image_set_exif_data (img, md_reader);
1157 
1158 #ifdef HAVE_LCMS
1159 					eog_image_set_icc_data (img, md_reader);
1160 #endif
1161 
1162 #ifdef HAVE_EXEMPI
1163 					eog_image_set_xmp_data (img, md_reader);
1164 #endif
1165 					set_metadata = FALSE;
1166 					priv->metadata_status = EOG_IMAGE_METADATA_READY;
1167 				}
1168 
1169 				if (data2read == EOG_IMAGE_DATA_EXIF)
1170 					break;
1171 			}
1172 		}
1173 
1174 		if (read_only_dimension &&
1175 		    eog_image_has_data (img, EOG_IMAGE_DATA_DIMENSION)) {
1176 			break;
1177 		}
1178 	}
1179 
1180 	if (read_image_data || read_only_dimension) {
1181 		if (!use_rsvg) {
1182 			if (failed) {
1183 				gdk_pixbuf_loader_close (loader, NULL);
1184 			} else if (!gdk_pixbuf_loader_close (loader, error)) {
1185 				if (gdk_pixbuf_loader_get_pixbuf (loader) != NULL) {
1186 					/* Clear error in order to support partial
1187 					 * images as well. */
1188 					g_clear_error (error);
1189 				}
1190 			}
1191 		}
1192 	}
1193 
1194 	g_free (mime_type);
1195 	g_free (buffer);
1196 
1197 	g_object_unref (G_OBJECT (input_stream));
1198 
1199 	failed = (failed ||
1200 		  priv->cancel_loading ||
1201 		  bytes_read_total == 0 ||
1202 		  (error && *error != NULL));
1203 
1204 	if (failed) {
1205 		if (priv->cancel_loading) {
1206 			priv->cancel_loading = FALSE;
1207 			priv->status = EOG_IMAGE_STATUS_UNKNOWN;
1208 		} else {
1209 			priv->status = EOG_IMAGE_STATUS_FAILED;
1210 		}
1211 	} else if (read_image_data) {
1212 		if (priv->image != NULL) {
1213 			g_object_unref (priv->image);
1214 		}
1215 
1216 #ifdef HAVE_RSVG
1217 		if (use_rsvg) {
1218 			priv->image = rsvg_handle_get_pixbuf (priv->svg);
1219 		} else
1220 #endif
1221 		{
1222 
1223 		priv->anim = gdk_pixbuf_loader_get_animation (loader);
1224 
1225 		if (gdk_pixbuf_animation_is_static_image (priv->anim)) {
1226 			priv->image = gdk_pixbuf_animation_get_static_image (priv->anim);
1227 			priv->anim = NULL;
1228 		} else {
1229 			priv->anim_iter = gdk_pixbuf_animation_get_iter (priv->anim,NULL);
1230 			priv->image = gdk_pixbuf_animation_iter_get_pixbuf (priv->anim_iter);
1231 		}
1232 
1233 		}
1234 
1235 		if (G_LIKELY (priv->image != NULL)) {
1236 			if (!use_rsvg)
1237 				g_object_ref (priv->image);
1238 
1239 			priv->width = gdk_pixbuf_get_width (priv->image);
1240 			priv->height = gdk_pixbuf_get_height (priv->image);
1241 
1242 			if (use_rsvg) {
1243 				format = NULL;
1244 				priv->file_type = g_strdup ("svg");
1245 			} else {
1246 				format = gdk_pixbuf_loader_get_format (loader);
1247 			}
1248 
1249 			if (format != NULL) {
1250 				priv->file_type = gdk_pixbuf_format_get_name (format);
1251 			}
1252 
1253 			priv->file_is_changed = FALSE;
1254 
1255 			/* Set orientation again for safety, eg. if we don't
1256 			 * have Exif data or HAVE_EXIF is undefined. */
1257 			if (priv->autorotate) {
1258 				eog_image_set_orientation (img);
1259 				eog_image_emit_size_prepared (img);
1260 			}
1261 		} else {
1262 			/* Some loaders don't report errors correctly.
1263 			 * Error will be set below. */
1264 			failed = TRUE;
1265 			priv->status = EOG_IMAGE_STATUS_FAILED;
1266 		}
1267 	}
1268 
1269 	if (loader != NULL) {
1270 		g_object_unref (loader);
1271 	}
1272 
1273 	if (md_reader != NULL) {
1274 		g_object_unref (md_reader);
1275 		md_reader = NULL;
1276 	}
1277 
1278 	/* Catch-all in case of poor-error reporting */
1279 	if (failed && error && *error == NULL) {
1280 		g_set_error (error,
1281 			     EOG_IMAGE_ERROR,
1282 			     EOG_IMAGE_ERROR_GENERIC,
1283 			     _("Image loading failed."));
1284 	}
1285 
1286 	return !failed;
1287 }
1288 
1289 gboolean
eog_image_has_data(EogImage * img,EogImageData req_data)1290 eog_image_has_data (EogImage *img, EogImageData req_data)
1291 {
1292 	EogImagePrivate *priv;
1293 	gboolean has_data = TRUE;
1294 
1295 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
1296 
1297 	priv = img->priv;
1298 
1299 	if ((req_data & EOG_IMAGE_DATA_IMAGE) > 0) {
1300 		req_data = (req_data & ~EOG_IMAGE_DATA_IMAGE);
1301 		has_data = has_data && (priv->image != NULL);
1302 	}
1303 
1304 	if ((req_data & EOG_IMAGE_DATA_DIMENSION) > 0 ) {
1305 		req_data = (req_data & ~EOG_IMAGE_DATA_DIMENSION);
1306 		has_data = has_data && (priv->width >= 0) && (priv->height >= 0);
1307 	}
1308 
1309 	if ((req_data & EOG_IMAGE_DATA_EXIF) > 0) {
1310 		req_data = (req_data & ~EOG_IMAGE_DATA_EXIF);
1311 #ifdef HAVE_EXIF
1312 		has_data = has_data && (priv->exif != NULL);
1313 #else
1314 		has_data = has_data && (priv->exif_chunk != NULL);
1315 #endif
1316 	}
1317 
1318 	if ((req_data & EOG_IMAGE_DATA_XMP) > 0) {
1319 		req_data = (req_data & ~EOG_IMAGE_DATA_XMP);
1320 #ifdef HAVE_EXEMPI
1321 		has_data = has_data && (priv->xmp != NULL);
1322 #endif
1323 	}
1324 
1325 	if (req_data != 0) {
1326 		g_warning ("Asking for unknown data, remaining: %i\n", req_data);
1327 		has_data = FALSE;
1328 
1329 	}
1330 
1331 	return has_data;
1332 }
1333 
1334 gboolean
eog_image_load(EogImage * img,EogImageData data2read,EogJob * job,GError ** error)1335 eog_image_load (EogImage *img, EogImageData data2read, EogJob *job, GError **error)
1336 {
1337 	EogImagePrivate *priv;
1338 	gboolean success = FALSE;
1339 
1340 	eog_debug (DEBUG_IMAGE_LOAD);
1341 
1342 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
1343 
1344 	priv = EOG_IMAGE (img)->priv;
1345 
1346 	if (data2read == 0) {
1347 		return TRUE;
1348 	}
1349 
1350 	if (eog_image_has_data (img, data2read)) {
1351 		return TRUE;
1352 	}
1353 
1354 	priv->status = EOG_IMAGE_STATUS_LOADING;
1355 
1356 	success = eog_image_real_load (img, data2read, job, error);
1357 
1358 
1359 	/* Check that the metadata was loaded at least once before
1360 	 * trying to autorotate. Also only an image load job should try to
1361 	 * autorotate an image. */
1362 	if (priv->autorotate &&
1363 #ifdef HAVE_EXIF
1364 	    priv->metadata_status != EOG_IMAGE_METADATA_NOT_READ &&
1365 #endif
1366 	    data2read & EOG_IMAGE_DATA_IMAGE) {
1367 		eog_image_real_autorotate (img);
1368 	}
1369 
1370 	if (success && eog_image_needs_transformation (img)) {
1371 		success = eog_image_apply_transformations (img, error);
1372 	}
1373 
1374 	if (success) {
1375 		priv->status = EOG_IMAGE_STATUS_LOADED;
1376 	} else {
1377 		priv->status = EOG_IMAGE_STATUS_FAILED;
1378 	}
1379 
1380 	return success;
1381 }
1382 
1383 void
eog_image_set_thumbnail(EogImage * img,GdkPixbuf * thumbnail)1384 eog_image_set_thumbnail (EogImage *img, GdkPixbuf *thumbnail)
1385 {
1386 	EogImagePrivate *priv;
1387 
1388 	g_return_if_fail (EOG_IS_IMAGE (img));
1389 	g_return_if_fail (GDK_IS_PIXBUF (thumbnail) || thumbnail == NULL);
1390 
1391 	priv = img->priv;
1392 
1393 	if (priv->thumbnail != NULL) {
1394 		g_object_unref (priv->thumbnail);
1395 		priv->thumbnail = NULL;
1396 	}
1397 
1398 	if (thumbnail != NULL && priv->trans != NULL) {
1399 		priv->thumbnail = eog_transform_apply (priv->trans, thumbnail, NULL);
1400 	} else {
1401 		priv->thumbnail = thumbnail;
1402 
1403 		if (thumbnail != NULL) {
1404 			g_object_ref (priv->thumbnail);
1405 		}
1406 	}
1407 
1408 	if (priv->thumbnail != NULL) {
1409 		g_signal_emit (img, signals[SIGNAL_THUMBNAIL_CHANGED], 0);
1410 	}
1411 }
1412 
1413 /**
1414  * eog_image_get_pixbuf:
1415  * @img: a #EogImage
1416  *
1417  * Gets the #GdkPixbuf of the image
1418  *
1419  * Returns: (transfer full): a #GdkPixbuf
1420  **/
1421 GdkPixbuf *
eog_image_get_pixbuf(EogImage * img)1422 eog_image_get_pixbuf (EogImage *img)
1423 {
1424 	GdkPixbuf *image = NULL;
1425 
1426 	g_return_val_if_fail (EOG_IS_IMAGE (img), NULL);
1427 
1428 	g_mutex_lock (&img->priv->status_mutex);
1429 	image = img->priv->image;
1430 	g_mutex_unlock (&img->priv->status_mutex);
1431 
1432 	if (image != NULL) {
1433 		g_object_ref (image);
1434 	}
1435 
1436 	return image;
1437 }
1438 
1439 #ifdef HAVE_LCMS
1440 cmsHPROFILE
eog_image_get_profile(EogImage * img)1441 eog_image_get_profile (EogImage *img)
1442 {
1443 	g_return_val_if_fail (EOG_IS_IMAGE (img), NULL);
1444 
1445 	return img->priv->profile;
1446 }
1447 #endif
1448 
1449 /**
1450  * eog_image_get_thumbnail:
1451  * @img: a #EogImage
1452  *
1453  * Gets the thumbnail pixbuf for @img
1454  *
1455  * Returns: (transfer full): a #GdkPixbuf with a thumbnail
1456  **/
1457 GdkPixbuf *
eog_image_get_thumbnail(EogImage * img)1458 eog_image_get_thumbnail (EogImage *img)
1459 {
1460 	g_return_val_if_fail (EOG_IS_IMAGE (img), NULL);
1461 
1462 	if (img->priv->thumbnail != NULL) {
1463 		return g_object_ref (img->priv->thumbnail);
1464 	}
1465 
1466 	return NULL;
1467 }
1468 
1469 void
eog_image_get_size(EogImage * img,int * width,int * height)1470 eog_image_get_size (EogImage *img, int *width, int *height)
1471 {
1472 	EogImagePrivate *priv;
1473 
1474 	g_return_if_fail (EOG_IS_IMAGE (img));
1475 
1476 	priv = img->priv;
1477 
1478 	*width = priv->width;
1479 	*height = priv->height;
1480 }
1481 
1482 void
eog_image_transform(EogImage * img,EogTransform * trans,EogJob * job)1483 eog_image_transform (EogImage *img, EogTransform *trans, EogJob *job)
1484 {
1485 	eog_image_real_transform (img, trans, FALSE, job);
1486 }
1487 
1488 void
eog_image_undo(EogImage * img)1489 eog_image_undo (EogImage *img)
1490 {
1491 	EogImagePrivate *priv;
1492 	EogTransform *trans;
1493 	EogTransform *inverse;
1494 
1495 	g_return_if_fail (EOG_IS_IMAGE (img));
1496 
1497 	priv = img->priv;
1498 
1499 	if (priv->undo_stack != NULL) {
1500 		trans = EOG_TRANSFORM (priv->undo_stack->data);
1501 
1502 		inverse = eog_transform_reverse (trans);
1503 
1504 		eog_image_real_transform (img, inverse, TRUE, NULL);
1505 
1506 		priv->undo_stack = g_slist_delete_link (priv->undo_stack, priv->undo_stack);
1507 
1508 		g_object_unref (trans);
1509 		g_object_unref (inverse);
1510 
1511 		if (eog_transform_is_identity (priv->trans)) {
1512 			g_object_unref (priv->trans);
1513 			priv->trans = NULL;
1514 		}
1515 	}
1516 
1517 	priv->modified = (priv->undo_stack != NULL);
1518 }
1519 
1520 static GFile *
tmp_file_get(void)1521 tmp_file_get (void)
1522 {
1523 	GFile *tmp_file;
1524 	char *tmp_file_path;
1525 	gint fd;
1526 
1527 	tmp_file_path = g_build_filename (g_get_tmp_dir (), "eog-save-XXXXXX", NULL);
1528 	fd = g_mkstemp (tmp_file_path);
1529 	if (fd == -1) {
1530 		g_free (tmp_file_path);
1531 		return NULL;
1532 	}
1533 	else {
1534 		tmp_file = g_file_new_for_path (tmp_file_path);
1535 		g_free (tmp_file_path);
1536 		return tmp_file;
1537 	}
1538 }
1539 
1540 static void
transfer_progress_cb(goffset cur_bytes,goffset total_bytes,gpointer user_data)1541 transfer_progress_cb (goffset cur_bytes,
1542 		      goffset total_bytes,
1543 		      gpointer user_data)
1544 {
1545 	EogImage *image = EOG_IMAGE (user_data);
1546 
1547 	if (cur_bytes > 0) {
1548 		g_signal_emit (G_OBJECT(image),
1549 			       signals[SIGNAL_SAVE_PROGRESS],
1550 			       0,
1551 			       (gfloat) cur_bytes / (gfloat) total_bytes);
1552 	}
1553 }
1554 
1555 static void
tmp_file_restore_unix_attributes(GFile * temp_file,GFile * target_file)1556 tmp_file_restore_unix_attributes (GFile *temp_file,
1557 				  GFile *target_file)
1558 {
1559 	GFileInfo *file_info;
1560 	guint      uid;
1561 	guint      gid;
1562 	guint      mode;
1563 	guint      mode_mask = 00600;
1564 
1565 	GError    *error = NULL;
1566 
1567 	g_return_if_fail (G_IS_FILE (temp_file));
1568 	g_return_if_fail (G_IS_FILE (target_file));
1569 
1570 	/* check if file exists */
1571 	if (!g_file_query_exists (target_file, NULL)) {
1572 		eog_debug_message (DEBUG_IMAGE_SAVE,
1573 				   "Target file doesn't exist. Setting default attributes.");
1574 		return;
1575 	}
1576 
1577 	/* retrieve UID, GID, and MODE of the original file info */
1578 	file_info = g_file_query_info (target_file,
1579 				       "unix::uid,unix::gid,unix::mode",
1580 				       G_FILE_QUERY_INFO_NONE,
1581 				       NULL,
1582 				       &error);
1583 
1584 	/* check that there aren't any error */
1585 	if (error != NULL) {
1586 		eog_debug_message (DEBUG_IMAGE_SAVE,
1587 				   "File information not available. Setting default attributes.");
1588 
1589 		/* free objects */
1590 		g_object_unref (file_info);
1591 		g_clear_error (&error);
1592 
1593 		return;
1594 	}
1595 
1596 	/* save UID, GID and MODE values */
1597 	uid = g_file_info_get_attribute_uint32 (file_info,
1598 						G_FILE_ATTRIBUTE_UNIX_UID);
1599 
1600 	gid = g_file_info_get_attribute_uint32 (file_info,
1601 						G_FILE_ATTRIBUTE_UNIX_GID);
1602 
1603 	mode = g_file_info_get_attribute_uint32 (file_info,
1604 						 G_FILE_ATTRIBUTE_UNIX_MODE);
1605 
1606 	/* apply default mode mask to file mode */
1607 	mode |= mode_mask;
1608 
1609 	/* restore original UID, GID, and MODE into the temporal file */
1610 	g_file_set_attribute_uint32 (temp_file,
1611 				     G_FILE_ATTRIBUTE_UNIX_UID,
1612 				     uid,
1613 				     G_FILE_QUERY_INFO_NONE,
1614 				     NULL,
1615 				     &error);
1616 
1617 	/* check that there aren't any error */
1618 	if (error != NULL) {
1619 		eog_debug_message (DEBUG_IMAGE_SAVE,
1620 				   "You do not have the permissions necessary to change the file UID.");
1621 
1622 		g_clear_error (&error);
1623 	}
1624 
1625 	g_file_set_attribute_uint32 (temp_file,
1626 				     G_FILE_ATTRIBUTE_UNIX_GID,
1627 				     gid,
1628 				     G_FILE_QUERY_INFO_NONE,
1629 				     NULL,
1630 				     &error);
1631 
1632 	/* check that there aren't any error */
1633 	if (error != NULL) {
1634 		eog_debug_message (DEBUG_IMAGE_SAVE,
1635 				   "You do not have the permissions necessary to change the file GID. Setting user default GID.");
1636 
1637 		g_clear_error (&error);
1638 	}
1639 
1640 	g_file_set_attribute_uint32 (temp_file,
1641 				     G_FILE_ATTRIBUTE_UNIX_MODE,
1642 				     mode,
1643 				     G_FILE_QUERY_INFO_NONE,
1644 				     NULL,
1645 				     &error);
1646 
1647 	/* check that there aren't any error */
1648 	if (error != NULL) {
1649 		eog_debug_message (DEBUG_IMAGE_SAVE,
1650 				   "You do not have the permissions necessary to change the file MODE.");
1651 
1652 		g_clear_error (&error);
1653 	}
1654 
1655 	/* free objects */
1656 	g_object_unref (file_info);
1657 }
1658 
1659 static gboolean
tmp_file_move_to_uri(EogImage * image,GFile * tmpfile,GFile * file,gboolean overwrite,GError ** error)1660 tmp_file_move_to_uri (EogImage *image,
1661 		      GFile *tmpfile,
1662 		      GFile *file,
1663 		      gboolean overwrite,
1664 		      GError **error)
1665 {
1666 	gboolean result;
1667 	GError *ioerror = NULL;
1668 
1669 	/* try to restore target file unix attributes */
1670 	tmp_file_restore_unix_attributes (tmpfile, file);
1671 
1672 	/* replace target file with temporal file */
1673 	result = g_file_move (tmpfile,
1674 			      file,
1675 			      (overwrite ? G_FILE_COPY_OVERWRITE : 0) |
1676 			      G_FILE_COPY_ALL_METADATA,
1677 			      NULL,
1678 			      (GFileProgressCallback) transfer_progress_cb,
1679 			      image,
1680 			      &ioerror);
1681 
1682 	if (result == FALSE) {
1683 		if (g_error_matches (ioerror, G_IO_ERROR,
1684 				     G_IO_ERROR_EXISTS)) {
1685 			g_set_error (error, EOG_IMAGE_ERROR,
1686 				     EOG_IMAGE_ERROR_FILE_EXISTS,
1687 				     "File exists");
1688 		} else {
1689 			g_set_error (error, EOG_IMAGE_ERROR,
1690 				     EOG_IMAGE_ERROR_VFS,
1691 				     "VFS error moving the temp file");
1692 		}
1693 		g_clear_error (&ioerror);
1694 	}
1695 
1696 	return result;
1697 }
1698 
1699 static gboolean
tmp_file_delete(GFile * tmpfile)1700 tmp_file_delete (GFile *tmpfile)
1701 {
1702 	gboolean result;
1703 	GError *err = NULL;
1704 
1705 	if (tmpfile == NULL) return FALSE;
1706 
1707 	result = g_file_delete (tmpfile, NULL, &err);
1708 	if (result == FALSE) {
1709 		char *tmpfile_path;
1710 		if (err != NULL) {
1711 			if (err->code == G_IO_ERROR_NOT_FOUND) {
1712 				g_error_free (err);
1713 				return TRUE;
1714 			}
1715 			g_error_free (err);
1716 		}
1717 		tmpfile_path = g_file_get_path (tmpfile);
1718 		g_warning ("Couldn't delete temporary file: %s", tmpfile_path);
1719 		g_free (tmpfile_path);
1720 	}
1721 
1722 	return result;
1723 }
1724 
1725 static void
eog_image_reset_modifications(EogImage * image)1726 eog_image_reset_modifications (EogImage *image)
1727 {
1728 	EogImagePrivate *priv;
1729 
1730 	g_return_if_fail (EOG_IS_IMAGE (image));
1731 
1732 	priv = image->priv;
1733 
1734 	g_slist_foreach (priv->undo_stack, (GFunc) g_object_unref, NULL);
1735 	g_slist_free (priv->undo_stack);
1736 	priv->undo_stack = NULL;
1737 
1738 	if (priv->trans != NULL) {
1739 		g_object_unref (priv->trans);
1740 		priv->trans = NULL;
1741 	}
1742 
1743 	if (priv->trans_autorotate != NULL) {
1744 		g_object_unref (priv->trans_autorotate);
1745 		priv->trans_autorotate = NULL;
1746 	}
1747 
1748 	priv->modified = FALSE;
1749 }
1750 
1751 static void
eog_image_link_with_target(EogImage * image,EogImageSaveInfo * target)1752 eog_image_link_with_target (EogImage *image, EogImageSaveInfo *target)
1753 {
1754 	EogImagePrivate *priv;
1755 
1756 	g_return_if_fail (EOG_IS_IMAGE (image));
1757 	g_return_if_fail (EOG_IS_IMAGE_SAVE_INFO (target));
1758 
1759 	priv = image->priv;
1760 
1761 	/* update file location */
1762 	if (priv->file != NULL) {
1763 		g_object_unref (priv->file);
1764 	}
1765 	priv->file = g_object_ref (target->file);
1766 
1767 	/* Clear caption and caption key, these will be
1768 	 * updated on next eog_image_get_caption call.
1769 	 */
1770 	if (priv->caption != NULL) {
1771 		g_free (priv->caption);
1772 		priv->caption = NULL;
1773 	}
1774 	if (priv->collate_key != NULL) {
1775 		g_free (priv->collate_key);
1776 		priv->collate_key = NULL;
1777 	}
1778 
1779 	/* update file format */
1780 	if (priv->file_type != NULL) {
1781 		g_free (priv->file_type);
1782 	}
1783 	priv->file_type = g_strdup (target->format);
1784 }
1785 
1786 static gboolean
check_if_file_is_writable(GFile * file)1787 check_if_file_is_writable (GFile *file)
1788 {
1789 	GFile           *file_to_check;
1790 	GFileInfo	*file_info;
1791 	GError		*error = NULL;
1792 	gboolean	 is_writable, has_writable;
1793 
1794 	g_return_val_if_fail (G_IS_FILE (file), FALSE);
1795 
1796 	/* check if file exists */
1797 	if (!g_file_query_exists (file, NULL)) {
1798 		eog_debug_message (DEBUG_IMAGE_SAVE, "File doesn't exist. "
1799 				   "Checking parent directory.");
1800 
1801 		file_to_check = g_file_get_parent (file);
1802 	} else {
1803 		/* Add another ref so we don't need to split between file and
1804 		 * parent file again after querying and can simply unref it. */
1805 		file_to_check = g_object_ref (file);
1806 	}
1807 
1808 	/* recover file information */
1809 	file_info = g_file_query_info (file_to_check,
1810 				       G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
1811 				       G_FILE_QUERY_INFO_NONE,
1812 				       NULL,
1813 				       &error);
1814 
1815 	/* we assume that the image can't be saved when
1816 	   we can't retrieve any file information */
1817 	if (G_UNLIKELY (file_info == NULL)) {
1818 		eog_debug_message (DEBUG_IMAGE_SAVE,
1819 				   "Couldn't query file info: %s",
1820 				   error->message);
1821 		g_error_free (error);
1822 		g_object_unref (file_to_check);
1823 		return FALSE;
1824 	}
1825 
1826 	/* check if file can be written */
1827 	has_writable = g_file_info_has_attribute (file_info,
1828 					          G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
1829 	if (has_writable) {
1830 		is_writable = g_file_info_get_attribute_boolean (file_info,
1831 								 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
1832 	} else {
1833 		/* try writing the file when the writable attribute is absent */
1834 		is_writable = TRUE;
1835 	}
1836 
1837 	/* free objects */
1838 	g_object_unref (file_info);
1839 	g_object_unref (file_to_check);
1840 
1841 	return is_writable;
1842 }
1843 
1844 gboolean
eog_image_save_by_info(EogImage * img,EogImageSaveInfo * source,GError ** error)1845 eog_image_save_by_info (EogImage *img, EogImageSaveInfo *source, GError **error)
1846 {
1847 	EogImagePrivate *priv;
1848 	EogImageStatus prev_status;
1849 	gboolean success = FALSE;
1850 	GFile *tmp_file;
1851 	char *tmp_file_path;
1852 
1853 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
1854 	g_return_val_if_fail (EOG_IS_IMAGE_SAVE_INFO (source), FALSE);
1855 
1856 	priv = img->priv;
1857 
1858 	prev_status = priv->status;
1859 
1860 	/* Image is now being saved */
1861 	priv->status = EOG_IMAGE_STATUS_SAVING;
1862 
1863 	/* see if we need any saving at all */
1864 	if (source->exists && !source->modified) {
1865 		return TRUE;
1866 	}
1867 
1868 	/* fail if there is no image to save */
1869 	if (priv->image == NULL) {
1870 		g_set_error (error, EOG_IMAGE_ERROR,
1871 			     EOG_IMAGE_ERROR_NOT_LOADED,
1872 			     _("No image loaded."));
1873 		return FALSE;
1874 	}
1875 
1876 	/* fail if there is not write rights to save */
1877 	if (!check_if_file_is_writable (priv->file)) {
1878 		g_set_error (error, EOG_IMAGE_ERROR,
1879 			     EOG_IMAGE_ERROR_NOT_SAVED,
1880 			     _("You do not have the permissions necessary to save the file."));
1881 		return FALSE;
1882 	}
1883 
1884 	/* generate temporary file */
1885 	tmp_file = tmp_file_get ();
1886 
1887 	if (tmp_file == NULL) {
1888 		g_set_error (error, EOG_IMAGE_ERROR,
1889 			     EOG_IMAGE_ERROR_TMP_FILE_FAILED,
1890 			     _("Temporary file creation failed."));
1891 		return FALSE;
1892 	}
1893 
1894 	tmp_file_path = g_file_get_path (tmp_file);
1895 
1896 #ifdef HAVE_JPEG
1897 	/* determine kind of saving */
1898 	if ((g_ascii_strcasecmp (source->format, EOG_FILE_FORMAT_JPEG) == 0) &&
1899 	    source->exists && source->modified)
1900 	{
1901 		success = eog_image_jpeg_save_file (img, tmp_file_path, source, NULL, error);
1902 	}
1903 #endif
1904 
1905 	if (!success && (*error == NULL)) {
1906 		success = gdk_pixbuf_save (priv->image, tmp_file_path, source->format, error, NULL);
1907 	}
1908 
1909 	if (success) {
1910 		/* try to move result file to target uri */
1911 		success = tmp_file_move_to_uri (img, tmp_file, priv->file, TRUE /*overwrite*/, error);
1912 	}
1913 
1914 	if (success) {
1915 		eog_image_reset_modifications (img);
1916 	}
1917 
1918 	tmp_file_delete (tmp_file);
1919 
1920 	g_free (tmp_file_path);
1921 	g_object_unref (tmp_file);
1922 
1923 	priv->status = prev_status;
1924 
1925 	return success;
1926 }
1927 
1928 static gboolean
eog_image_copy_file(EogImage * image,EogImageSaveInfo * source,EogImageSaveInfo * target,GError ** error)1929 eog_image_copy_file (EogImage *image, EogImageSaveInfo *source, EogImageSaveInfo *target, GError **error)
1930 {
1931 	gboolean result;
1932 	GError *ioerror = NULL;
1933 
1934 	g_return_val_if_fail (EOG_IS_IMAGE_SAVE_INFO (source), FALSE);
1935 	g_return_val_if_fail (EOG_IS_IMAGE_SAVE_INFO (target), FALSE);
1936 
1937 	/* copy the image */
1938 	result = g_file_copy (source->file,
1939 			      target->file,
1940 			      (target->overwrite ? G_FILE_COPY_OVERWRITE : 0) |
1941 			      G_FILE_COPY_ALL_METADATA,
1942 			      NULL,
1943 			      EOG_IS_IMAGE (image) ? transfer_progress_cb :NULL,
1944 			      image,
1945 			      &ioerror);
1946 
1947 	if (result == FALSE) {
1948 		if (ioerror->code == G_IO_ERROR_EXISTS) {
1949 			g_set_error (error, EOG_IMAGE_ERROR,
1950 				     EOG_IMAGE_ERROR_FILE_EXISTS,
1951 				     "%s", ioerror->message);
1952 		} else {
1953 		g_set_error (error, EOG_IMAGE_ERROR,
1954 			     EOG_IMAGE_ERROR_VFS,
1955 			     "%s", ioerror->message);
1956 		}
1957 		g_error_free (ioerror);
1958 	} else {
1959 		/* reset NAUTILUS-ICON-POSITION metadata attribute */
1960 		g_file_set_attribute (target->file,
1961 				      "metadata::nautilus-icon-position",
1962 				      G_FILE_ATTRIBUTE_TYPE_INVALID,
1963 				      NULL,
1964 				      G_FILE_QUERY_INFO_NONE,
1965 				      NULL,
1966 				      NULL);
1967 	}
1968 
1969 	return result;
1970 }
1971 
1972 gboolean
eog_image_save_as_by_info(EogImage * img,EogImageSaveInfo * source,EogImageSaveInfo * target,GError ** error)1973 eog_image_save_as_by_info (EogImage *img, EogImageSaveInfo *source, EogImageSaveInfo *target, GError **error)
1974 {
1975 	EogImagePrivate *priv;
1976 	gboolean success = FALSE;
1977 	char *tmp_file_path;
1978 	GFile *tmp_file;
1979 	gboolean direct_copy = FALSE;
1980 
1981 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
1982 	g_return_val_if_fail (EOG_IS_IMAGE_SAVE_INFO (source), FALSE);
1983 	g_return_val_if_fail (EOG_IS_IMAGE_SAVE_INFO (target), FALSE);
1984 
1985 	priv = img->priv;
1986 
1987 	/* fail if there is no image to save */
1988 	if (priv->image == NULL) {
1989 		g_set_error (error,
1990 			     EOG_IMAGE_ERROR,
1991 			     EOG_IMAGE_ERROR_NOT_LOADED,
1992 			     _("No image loaded."));
1993 
1994 		return FALSE;
1995 	}
1996 
1997 	/* fail if there is not write rights to save on target */
1998 	if (!check_if_file_is_writable (target->file)) {
1999 		g_set_error (error, EOG_IMAGE_ERROR,
2000 			     EOG_IMAGE_ERROR_NOT_SAVED,
2001 			     _("You do not have the permissions necessary to save the file."));
2002 		return FALSE;
2003 	}
2004 
2005 	/* generate temporary file name */
2006 	tmp_file = tmp_file_get ();
2007 
2008 	if (tmp_file == NULL) {
2009 		g_set_error (error,
2010 			     EOG_IMAGE_ERROR,
2011 			     EOG_IMAGE_ERROR_TMP_FILE_FAILED,
2012 			     _("Temporary file creation failed."));
2013 
2014 		return FALSE;
2015 	}
2016 	tmp_file_path = g_file_get_path (tmp_file);
2017 
2018 	/* determine kind of saving */
2019 	if (g_ascii_strcasecmp (source->format, target->format) == 0 && !source->modified) {
2020 		success = eog_image_copy_file (img, source, target, error);
2021 		direct_copy = success;
2022 	}
2023 
2024 #ifdef HAVE_JPEG
2025 	else if ((g_ascii_strcasecmp (source->format, EOG_FILE_FORMAT_JPEG) == 0 && source->exists) ||
2026 		 (g_ascii_strcasecmp (target->format, EOG_FILE_FORMAT_JPEG) == 0))
2027 	{
2028 		success = eog_image_jpeg_save_file (img, tmp_file_path, source, target, error);
2029 	}
2030 #endif
2031 
2032 	if (!success && (*error == NULL)) {
2033 		success = gdk_pixbuf_save (priv->image, tmp_file_path, target->format, error, NULL);
2034 	}
2035 
2036 	if (success && !direct_copy) { /* not required if we already copied the file directly */
2037 		/* try to move result file to target uri */
2038 		success = tmp_file_move_to_uri (img, tmp_file, target->file, target->overwrite, error);
2039 	}
2040 
2041 	if (success) {
2042 		/* update image information to new uri */
2043 		eog_image_reset_modifications (img);
2044 		eog_image_link_with_target (img, target);
2045 	}
2046 
2047 	tmp_file_delete (tmp_file);
2048 	g_object_unref (tmp_file);
2049 	g_free (tmp_file_path);
2050 
2051 	priv->status = EOG_IMAGE_STATUS_UNKNOWN;
2052 
2053 	return success;
2054 }
2055 
2056 /*
2057  * This function is inspired by
2058  * nautilus/libnautilus-private/nautilus-file.c:nautilus_file_get_display_name_nocopy
2059  * Revision: 1.309
2060  * Author: Darin Adler <darin@bentspoon.com>
2061  */
2062 const gchar*
eog_image_get_caption(EogImage * img)2063 eog_image_get_caption (EogImage *img)
2064 {
2065 	EogImagePrivate *priv;
2066 	GFileInfo *info;
2067 
2068 	g_return_val_if_fail (EOG_IS_IMAGE (img), NULL);
2069 
2070 	priv = img->priv;
2071 
2072 	if (priv->file == NULL) return NULL;
2073 
2074 	if (priv->caption != NULL)
2075 		/* Use cached caption string */
2076 		return priv->caption;
2077 
2078 	info = g_file_query_info (priv->file,
2079 				  G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
2080 				  G_FILE_QUERY_INFO_NONE,
2081 				  NULL,
2082 				  NULL);
2083 
2084 	if (G_LIKELY (info != NULL))
2085 	{
2086 		priv->caption = g_strdup (g_file_info_get_display_name (info));
2087 		g_object_unref(info);
2088 	}
2089 
2090 	if (G_UNLIKELY (priv->caption == NULL)) {
2091 		char *short_str;
2092 
2093 		short_str = g_file_get_basename (priv->file);
2094 		if (g_utf8_validate (short_str, -1, NULL)) {
2095 			priv->caption = g_strdup (short_str);
2096 		} else {
2097 			priv->caption = g_filename_to_utf8 (short_str, -1, NULL, NULL, NULL);
2098 		}
2099 		g_free (short_str);
2100 	}
2101 
2102 	return priv->caption;
2103 }
2104 
2105 const gchar*
eog_image_get_collate_key(EogImage * img)2106 eog_image_get_collate_key (EogImage *img)
2107 {
2108 	EogImagePrivate *priv;
2109 
2110 	g_return_val_if_fail (EOG_IS_IMAGE (img), NULL);
2111 
2112 	priv = img->priv;
2113 
2114 	if (priv->collate_key == NULL) {
2115 		const char *caption;
2116 
2117 		caption = eog_image_get_caption (img);
2118 
2119 		priv->collate_key = g_utf8_collate_key_for_filename (caption, -1);
2120 	}
2121 
2122 	return priv->collate_key;
2123 }
2124 
2125 void
eog_image_cancel_load(EogImage * img)2126 eog_image_cancel_load (EogImage *img)
2127 {
2128 	EogImagePrivate *priv;
2129 
2130 	g_return_if_fail (EOG_IS_IMAGE (img));
2131 
2132 	priv = img->priv;
2133 
2134 	g_mutex_lock (&priv->status_mutex);
2135 
2136 	if (priv->status == EOG_IMAGE_STATUS_LOADING) {
2137 		priv->cancel_loading = TRUE;
2138 	}
2139 
2140 	g_mutex_unlock (&priv->status_mutex);
2141 }
2142 
2143 #ifdef HAVE_EXIF
2144 ExifData *
eog_image_get_exif_info(EogImage * img)2145 eog_image_get_exif_info (EogImage *img)
2146 {
2147 	EogImagePrivate *priv;
2148 	ExifData *data = NULL;
2149 
2150 	g_return_val_if_fail (EOG_IS_IMAGE (img), NULL);
2151 
2152 	priv = img->priv;
2153 
2154 	g_mutex_lock (&priv->status_mutex);
2155 
2156 	exif_data_ref (priv->exif);
2157 	data = priv->exif;
2158 
2159 	g_mutex_unlock (&priv->status_mutex);
2160 
2161 	return data;
2162 }
2163 #endif
2164 
2165 /**
2166  * eog_image_get_xmp_info:
2167  * @img: a #EogImage
2168  *
2169  * Gets the XMP info for @img or NULL if compiled without
2170  * libexempi support.
2171  *
2172  * Returns: (transfer full): the xmp data
2173  **/
2174 gpointer
eog_image_get_xmp_info(EogImage * img)2175 eog_image_get_xmp_info (EogImage *img)
2176 {
2177  	gpointer data = NULL;
2178 
2179  	g_return_val_if_fail (EOG_IS_IMAGE (img), NULL);
2180 
2181 #ifdef HAVE_EXEMPI
2182 	EogImagePrivate *priv;
2183  	priv = img->priv;
2184 
2185 	g_mutex_lock (&priv->status_mutex);
2186  	data = (gpointer) xmp_copy (priv->xmp);
2187 	g_mutex_unlock (&priv->status_mutex);
2188 #endif
2189 
2190  	return data;
2191 }
2192 
2193 
2194 /**
2195  * eog_image_get_file:
2196  * @img: a #EogImage
2197  *
2198  * Gets the #GFile associated with @img
2199  *
2200  * Returns: (transfer full): a #GFile
2201  **/
2202 GFile *
eog_image_get_file(EogImage * img)2203 eog_image_get_file (EogImage *img)
2204 {
2205 	g_return_val_if_fail (EOG_IS_IMAGE (img), NULL);
2206 
2207 	return g_object_ref (img->priv->file);
2208 }
2209 
2210 gboolean
eog_image_is_modified(EogImage * img)2211 eog_image_is_modified (EogImage *img)
2212 {
2213 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
2214 
2215 	return img->priv->modified;
2216 }
2217 
2218 goffset
eog_image_get_bytes(EogImage * img)2219 eog_image_get_bytes (EogImage *img)
2220 {
2221 	g_return_val_if_fail (EOG_IS_IMAGE (img), 0);
2222 
2223 	return img->priv->bytes;
2224 }
2225 
2226 void
eog_image_modified(EogImage * img)2227 eog_image_modified (EogImage *img)
2228 {
2229 	g_return_if_fail (EOG_IS_IMAGE (img));
2230 
2231 	g_signal_emit (G_OBJECT (img), signals[SIGNAL_CHANGED], 0);
2232 }
2233 
2234 gchar*
eog_image_get_uri_for_display(EogImage * img)2235 eog_image_get_uri_for_display (EogImage *img)
2236 {
2237 	EogImagePrivate *priv;
2238 	gchar *uri_str = NULL;
2239 	gchar *str = NULL;
2240 
2241 	g_return_val_if_fail (EOG_IS_IMAGE (img), NULL);
2242 
2243 	priv = img->priv;
2244 
2245 	if (priv->file != NULL) {
2246 		uri_str = g_file_get_uri (priv->file);
2247 
2248 		if (uri_str != NULL) {
2249 			str = g_uri_unescape_string (uri_str, NULL);
2250 			g_free (uri_str);
2251 		}
2252 	}
2253 
2254 	return str;
2255 }
2256 
2257 EogImageStatus
eog_image_get_status(EogImage * img)2258 eog_image_get_status (EogImage *img)
2259 {
2260 	g_return_val_if_fail (EOG_IS_IMAGE (img), EOG_IMAGE_STATUS_UNKNOWN);
2261 
2262 	return img->priv->status;
2263 }
2264 
2265 /**
2266  * eog_image_get_metadata_status:
2267  * @img: a #EogImage
2268  *
2269  * Returns the current status of the image metadata, that is,
2270  * whether the metadata has not been read yet, is ready, or not available at all.
2271  *
2272  * Returns: one of #EogImageMetadataStatus
2273  **/
2274 EogImageMetadataStatus
eog_image_get_metadata_status(EogImage * img)2275 eog_image_get_metadata_status (EogImage *img)
2276 {
2277         g_return_val_if_fail (EOG_IS_IMAGE (img), EOG_IMAGE_METADATA_NOT_AVAILABLE);
2278 
2279         return img->priv->metadata_status;
2280 }
2281 
2282 void
eog_image_data_ref(EogImage * img)2283 eog_image_data_ref (EogImage *img)
2284 {
2285 	g_return_if_fail (EOG_IS_IMAGE (img));
2286 
2287 	g_object_ref (G_OBJECT (img));
2288 	img->priv->data_ref_count++;
2289 
2290 	g_assert (img->priv->data_ref_count <= G_OBJECT (img)->ref_count);
2291 }
2292 
2293 void
eog_image_data_unref(EogImage * img)2294 eog_image_data_unref (EogImage *img)
2295 {
2296 	g_return_if_fail (EOG_IS_IMAGE (img));
2297 
2298 	if (img->priv->data_ref_count > 0) {
2299 		img->priv->data_ref_count--;
2300 	} else {
2301 		g_warning ("More image data unrefs than refs.");
2302 	}
2303 
2304 	if (img->priv->data_ref_count == 0) {
2305 		eog_image_free_mem_private (img);
2306 	}
2307 
2308 	g_object_unref (G_OBJECT (img));
2309 
2310 	g_assert (img->priv->data_ref_count <= G_OBJECT (img)->ref_count);
2311 }
2312 
2313 static gint
compare_quarks(gconstpointer a,gconstpointer b)2314 compare_quarks (gconstpointer a, gconstpointer b)
2315 {
2316 	GQuark quark;
2317 
2318 	quark = g_quark_from_string ((const gchar *) a);
2319 
2320 	return quark - GPOINTER_TO_INT (b);
2321 }
2322 
2323 /**
2324  * eog_image_get_supported_mime_types:
2325  *
2326  * Gets the list of supported mimetypes
2327  *
2328  * Returns: (transfer none)(element-type utf8): a #GList of supported mimetypes
2329  **/
2330 GList *
eog_image_get_supported_mime_types(void)2331 eog_image_get_supported_mime_types (void)
2332 {
2333 	GSList *format_list, *it;
2334 	gchar **mime_types;
2335 	int i;
2336 
2337 	if (!supported_mime_types) {
2338 		format_list = gdk_pixbuf_get_formats ();
2339 
2340 		for (it = format_list; it != NULL; it = it->next) {
2341 			mime_types =
2342 				gdk_pixbuf_format_get_mime_types ((GdkPixbufFormat *) it->data);
2343 
2344 			for (i = 0; mime_types[i] != NULL; i++) {
2345 				supported_mime_types =
2346 					g_list_prepend (supported_mime_types,
2347 							g_strdup (mime_types[i]));
2348 			}
2349 
2350 			g_strfreev (mime_types);
2351 		}
2352 
2353 		supported_mime_types = g_list_sort (supported_mime_types,
2354 						    (GCompareFunc) compare_quarks);
2355 
2356 		g_slist_free (format_list);
2357 	}
2358 
2359 	return supported_mime_types;
2360 }
2361 
2362 gboolean
eog_image_is_supported_mime_type(const char * mime_type)2363 eog_image_is_supported_mime_type (const char *mime_type)
2364 {
2365 	GList *supported_mime_types, *result;
2366 	GQuark quark;
2367 
2368 	if (mime_type == NULL) {
2369 		return FALSE;
2370 	}
2371 
2372 	supported_mime_types = eog_image_get_supported_mime_types ();
2373 
2374 	quark = g_quark_from_string (mime_type);
2375 
2376 	result = g_list_find_custom (supported_mime_types,
2377 				     GINT_TO_POINTER (quark),
2378 				     (GCompareFunc) compare_quarks);
2379 
2380 	return (result != NULL);
2381 }
2382 
2383 static gboolean
eog_image_iter_advance(EogImage * img)2384 eog_image_iter_advance (EogImage *img)
2385 {
2386 	EogImagePrivate *priv;
2387  	gboolean new_frame;
2388 
2389 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
2390 	g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION_ITER (img->priv->anim_iter), FALSE);
2391 
2392 	priv = img->priv;
2393 
2394 	if ((new_frame = gdk_pixbuf_animation_iter_advance (img->priv->anim_iter, NULL)) == TRUE)
2395 	  {
2396 		g_mutex_lock (&priv->status_mutex);
2397 		g_object_unref (priv->image);
2398 		priv->image = gdk_pixbuf_animation_iter_get_pixbuf (priv->anim_iter);
2399 	 	g_object_ref (priv->image);
2400 		/* keep the transformation over time */
2401 		if (EOG_IS_TRANSFORM (priv->trans)) {
2402 			GdkPixbuf* transformed = eog_transform_apply (priv->trans, priv->image, NULL);
2403 			g_object_unref (priv->image);
2404 			priv->image = transformed;
2405 			priv->width = gdk_pixbuf_get_width (transformed);
2406 			priv->height = gdk_pixbuf_get_height (transformed);
2407 		}
2408 		g_mutex_unlock (&priv->status_mutex);
2409 		/* Emit next frame signal so we can update the display */
2410 		g_signal_emit (img, signals[SIGNAL_NEXT_FRAME], 0,
2411 			       gdk_pixbuf_animation_iter_get_delay_time (priv->anim_iter));
2412 	  }
2413 
2414 	return new_frame;
2415 }
2416 
2417 /**
2418  * eog_image_is_animation:
2419  * @img: a #EogImage
2420  *
2421  * Checks whether a given image is animated.
2422  *
2423  * Returns: #TRUE if it is an animated image, #FALSE otherwise.
2424  *
2425  **/
2426 gboolean
eog_image_is_animation(EogImage * img)2427 eog_image_is_animation (EogImage *img)
2428 {
2429 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
2430 	return img->priv->anim != NULL;
2431 }
2432 
2433 static gboolean
private_timeout(gpointer data)2434 private_timeout (gpointer data)
2435 {
2436 	EogImage *img = EOG_IMAGE (data);
2437 	EogImagePrivate *priv = img->priv;
2438 
2439 	if (eog_image_is_animation (img) &&
2440 	    !g_source_is_destroyed (g_main_current_source ()) &&
2441 	    priv->is_playing) {
2442 		while (eog_image_iter_advance (img) != TRUE) {}; /* cpu-sucking ? */
2443 		priv->anim_source = g_timeout_add (
2444 			gdk_pixbuf_animation_iter_get_delay_time (priv->anim_iter),
2445 			private_timeout, img);
2446 		return FALSE;
2447 	}
2448 	priv->is_playing = FALSE;
2449 	priv->anim_source = 0;
2450 	return FALSE; /* stop playing */
2451 }
2452 
2453 /**
2454  * eog_image_start_animation:
2455  * @img: a #EogImage
2456  *
2457  * Starts playing an animated image.
2458  *
2459  * Returns: %TRUE on success, %FALSE if @img is already playing or isn't an animated image.
2460  **/
2461 gboolean
eog_image_start_animation(EogImage * img)2462 eog_image_start_animation (EogImage *img)
2463 {
2464 	EogImagePrivate *priv;
2465 
2466 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
2467 	priv = img->priv;
2468 
2469 	if (!eog_image_is_animation (img) || priv->is_playing)
2470 		return FALSE;
2471 
2472 	g_mutex_lock (&priv->status_mutex);
2473 	g_object_ref (priv->anim_iter);
2474 	priv->is_playing = TRUE;
2475 	g_mutex_unlock (&priv->status_mutex);
2476 
2477 	priv->anim_source =
2478 		g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (priv->anim_iter),
2479 		               private_timeout, img);
2480 
2481 	return TRUE;
2482 }
2483 
2484 #ifdef HAVE_RSVG
2485 gboolean
eog_image_is_svg(EogImage * img)2486 eog_image_is_svg (EogImage *img)
2487 {
2488 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
2489 
2490 	return (img->priv->svg != NULL);
2491 }
2492 
2493 RsvgHandle *
eog_image_get_svg(EogImage * img)2494 eog_image_get_svg (EogImage *img)
2495 {
2496 	g_return_val_if_fail (EOG_IS_IMAGE (img), NULL);
2497 
2498 	return img->priv->svg;
2499 }
2500 #endif
2501 
2502 /**
2503  * eog_image_get_transform:
2504  * @img: a #EogImage
2505  *
2506  * Get @img transform.
2507  *
2508  * Returns: (transfer none): A #EogTransform.
2509  */
2510 
2511 EogTransform *
eog_image_get_transform(EogImage * img)2512 eog_image_get_transform (EogImage *img)
2513 {
2514 	g_return_val_if_fail (EOG_IS_IMAGE (img), NULL);
2515 
2516 	return img->priv->trans;
2517 }
2518 
2519 /**
2520  * eog_image_get_autorotate_transform:
2521  * @img: a #EogImage
2522  *
2523  * Get @img autorotate transform.
2524  *
2525  * Returns: (transfer none): A #EogTransform.
2526  */
2527 
2528 EogTransform*
eog_image_get_autorotate_transform(EogImage * img)2529 eog_image_get_autorotate_transform (EogImage *img)
2530 {
2531 	g_return_val_if_fail (EOG_IS_IMAGE (img), NULL);
2532 
2533 	return img->priv->trans_autorotate;
2534 }
2535 
2536 /**
2537  * eog_image_file_changed:
2538  * @img: a #EogImage
2539  *
2540  * Marks the image file contents as changed. Also, emits
2541  * EogImage::file-changed signal.
2542  **/
2543 void
eog_image_file_changed(EogImage * img)2544 eog_image_file_changed (EogImage *img)
2545 {
2546 	g_return_if_fail (EOG_IS_IMAGE (img));
2547 
2548 	img->priv->file_is_changed = TRUE;
2549 	g_signal_emit (img, signals[SIGNAL_FILE_CHANGED], 0);
2550 }
2551 
2552 gboolean
eog_image_is_file_changed(EogImage * img)2553 eog_image_is_file_changed (EogImage *img)
2554 {
2555 	g_return_val_if_fail (EOG_IS_IMAGE (img), TRUE);
2556 
2557 	return img->priv->file_is_changed;
2558 }
2559 
2560 /**
2561  * eog_image_is_file_writable:
2562  * @img: a #EogImage
2563  *
2564  * Evaluate if the user has write permission on the image file.
2565  *
2566  * Returns: %TRUE on success, %FALSE if the user hasn't write permissions on it,
2567  * or @img is not an #EogImage.
2568  **/
2569 gboolean
eog_image_is_file_writable(EogImage * img)2570 eog_image_is_file_writable (EogImage *img)
2571 {
2572 	gboolean is_writable;
2573 
2574 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
2575 
2576 	is_writable = check_if_file_is_writable (img->priv->file);
2577 
2578 	return is_writable;
2579 }
2580 
2581 gboolean
eog_image_is_jpeg(EogImage * img)2582 eog_image_is_jpeg (EogImage *img)
2583 {
2584 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
2585 
2586 	return ((img->priv->file_type != NULL) && (g_ascii_strcasecmp (img->priv->file_type, EOG_FILE_FORMAT_JPEG) == 0));
2587 }
2588 
2589 /**
2590  * eog_image_is_multipaged:
2591  * @img: an #EogImage
2592  *
2593  * Check whether the image actually contains multiple images/pages.
2594  * This can happen for TIFF files. GIF animations are not multipaged.
2595  *
2596  * Note that this only works if the image data is loaded.
2597  *
2598  * Returns: %TRUE if @img is multipaged, %FALSE if not or the image data wasn't loaded.
2599  * Since: 3.18
2600  **/
2601 gboolean
eog_image_is_multipaged(EogImage * img)2602 eog_image_is_multipaged (EogImage *img)
2603 {
2604 	gboolean result = FALSE;
2605 
2606 	g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
2607 
2608 	if (img->priv->image != NULL)
2609 	{
2610 		const gchar* value = gdk_pixbuf_get_option (img->priv->image,
2611 							    "multipage");
2612 
2613 		result = (g_strcmp0 ("yes", value) == 0);
2614 	}
2615 
2616 	return result;
2617 }
2618