]> www.fi.muni.cz Git - evince.git/blob - tiff/tiff-document.c
Rough TIFF backend.
[evince.git] / tiff / tiff-document.c
1
2 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
3 /*
4  * Copyright (C) 2005, Jonathan Blandford <jrb@gnome.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 /* FIXME: Shoudl probably buffer calls to libtiff with TIFFSetWarningHandler
22  */
23 #include "tiffio.h"
24 #include "tiff-document.h"
25 #include "ev-document-thumbnails.h"
26 #include "ev-document-misc.h"
27
28 struct _TiffDocumentClass
29 {
30   GObjectClass parent_class;
31 };
32
33 struct _TiffDocument
34 {
35   GObject parent_instance;
36
37   TIFF *tiff;
38   gint n_pages;
39 };
40
41 typedef struct _TiffDocumentClass TiffDocumentClass;
42
43 static void tiff_document_document_iface_init (EvDocumentIface *iface);
44 static void tiff_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
45
46 G_DEFINE_TYPE_WITH_CODE (TiffDocument, tiff_document, G_TYPE_OBJECT,
47                          { G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
48                                                   tiff_document_document_iface_init);
49                            G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
50                                                   tiff_document_document_thumbnails_iface_init);
51                          });
52
53 static TIFFErrorHandler orig_error_handler = NULL;
54 static TIFFErrorHandler orig_warning_handler = NULL;
55
56 static void
57 push_handlers (void)
58 {
59   orig_error_handler = TIFFSetErrorHandler (NULL);
60   orig_warning_handler = TIFFSetWarningHandler (NULL);
61 }
62
63 static void
64 pop_handlers (void)
65 {
66   TIFFSetErrorHandler (orig_error_handler);
67   TIFFSetWarningHandler (orig_warning_handler);
68 }
69
70 static gboolean
71 tiff_document_load (EvDocument  *document,
72                     const char  *uri,
73                     GError     **error)
74 {
75   TiffDocument *tiff_document = TIFF_DOCUMENT (document);
76   gchar *filename;
77   TIFF *tiff;
78
79   push_handlers ();
80   /* FIXME: We could actually load uris  */
81   filename = g_filename_from_uri (uri, NULL, error);
82   if (!filename)
83     {
84       pop_handlers ();
85       return FALSE;
86     }
87
88   tiff = TIFFOpen (filename, "r");
89   if (tiff)
90     {
91       guint32 w, h;
92       
93       TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
94       TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
95     }
96   if (!tiff)
97     {
98       pop_handlers ();
99       return FALSE;
100     }
101   tiff_document->tiff = tiff;
102
103   pop_handlers ();
104   return TRUE;
105 }
106
107 static gboolean
108 tiff_document_save (EvDocument  *document,
109                       const char  *uri,
110                       GError     **error)
111 {
112         return FALSE;
113 }
114
115 static int
116 tiff_document_get_n_pages (EvDocument  *document)
117 {
118   TiffDocument *tiff_document = TIFF_DOCUMENT (document);
119
120   g_return_val_if_fail (TIFF_IS_DOCUMENT (document), 0);
121   g_return_val_if_fail (tiff_document->tiff != NULL, 0);
122
123   if (tiff_document->n_pages == -1)
124     {
125       push_handlers ();
126       tiff_document->n_pages = 0;
127       do
128         {
129           tiff_document->n_pages ++;
130         }
131       while (TIFFReadDirectory (tiff_document->tiff));
132       pop_handlers ();
133     }
134
135   return tiff_document->n_pages;
136 }
137
138 static void
139 tiff_document_get_page_size (EvDocument   *document,
140                              int           page,
141                              double       *width,
142                              double       *height)
143 {
144   guint32 w, h;
145   TiffDocument *tiff_document = TIFF_DOCUMENT (document);
146
147   g_return_if_fail (TIFF_IS_DOCUMENT (document));
148   g_return_if_fail (tiff_document->tiff != NULL);
149
150   push_handlers ();
151   if (TIFFSetDirectory (tiff_document->tiff, page) != 1)
152     {
153       pop_handlers ();
154       return;
155     }
156
157   TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &w);
158   TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &h);
159
160   *width = w;
161   *height = h;
162   pop_handlers ();
163 }
164
165 static GdkPixbuf *
166 tiff_document_render_pixbuf (EvDocument  *document, int page, double scale)
167 {
168   TiffDocument *tiff_document = TIFF_DOCUMENT (document);
169   int width, height;
170   GdkPixbuf *pixbuf;
171   GdkPixbuf *scaled_pixbuf;
172
173   g_return_val_if_fail (TIFF_IS_DOCUMENT (document), 0);
174   g_return_val_if_fail (tiff_document->tiff != NULL, 0);
175
176   push_handlers ();
177   if (TIFFSetDirectory (tiff_document->tiff, page) != 1)
178     {
179       pop_handlers ();
180       return NULL;
181     }
182
183   TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &width);
184   TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &height);
185
186   pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
187   TIFFReadRGBAImageOriented (tiff_document->tiff, width, height, (uint32 *)gdk_pixbuf_get_pixels (pixbuf), ORIENTATION_TOPLEFT, 1);
188   pop_handlers ();
189
190   scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
191                                            width * scale,
192                                            height * scale,
193                                            GDK_INTERP_BILINEAR);
194   g_object_unref (pixbuf);
195
196   return scaled_pixbuf;
197 }
198
199 static void
200 tiff_document_finalize (GObject *object)
201 {
202         TiffDocument *tiff_document = TIFF_DOCUMENT (object);
203
204         TIFFClose (tiff_document->tiff);
205
206         G_OBJECT_CLASS (tiff_document_parent_class)->finalize (object);
207 }
208
209 static void
210 tiff_document_class_init (TiffDocumentClass *klass)
211 {
212         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
213
214         gobject_class->finalize = tiff_document_finalize;
215 }
216
217 static gboolean
218 tiff_document_can_get_text (EvDocument *document)
219 {
220         return FALSE;
221 }
222
223 static EvDocumentInfo *
224 tiff_document_get_info (EvDocument *document)
225 {
226         EvDocumentInfo *info;
227
228         info = g_new0 (EvDocumentInfo, 1);
229         info->fields_mask = 0;
230
231         return info;
232 }
233
234 static void
235 tiff_document_document_iface_init (EvDocumentIface *iface)
236 {
237         iface->load = tiff_document_load;
238         iface->save = tiff_document_save;
239         iface->can_get_text = tiff_document_can_get_text;
240         iface->get_n_pages = tiff_document_get_n_pages;
241         iface->get_page_size = tiff_document_get_page_size;
242         iface->render_pixbuf = tiff_document_render_pixbuf;
243         iface->get_info = tiff_document_get_info;
244 }
245
246 static GdkPixbuf *
247 tiff_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document,
248                                         gint                  page,
249                                         gint                  size,
250                                         gboolean              border)
251 {
252   GdkPixbuf *pixbuf;
253   gdouble w, h;
254
255   tiff_document_get_page_size (EV_DOCUMENT (document),
256                                page,
257                                &w, &h);
258
259   pixbuf = tiff_document_render_pixbuf (EV_DOCUMENT (document),
260                                         page,
261                                         size/w);
262
263   if (border)
264     {
265       GdkPixbuf *tmp_pixbuf = pixbuf;
266       pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, tmp_pixbuf);
267       g_object_unref (tmp_pixbuf);
268     }
269
270   return pixbuf;
271 }
272
273 static void
274 tiff_document_thumbnails_get_dimensions (EvDocumentThumbnails *document,
275                                          gint                  page,
276                                          gint                  suggested_width,
277                                          gint                 *width,
278                                          gint                 *height)
279 {
280   gdouble page_ratio;
281   gdouble w, h;
282
283   tiff_document_get_page_size (EV_DOCUMENT (document),
284                                page,
285                                &w, &h);
286   g_return_if_fail (w > 0);
287   page_ratio = h/w;
288   *width = suggested_width;
289   *height = (gint) (suggested_width * page_ratio);
290 }
291
292 static void
293 tiff_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
294 {
295   iface->get_thumbnail = tiff_document_thumbnails_get_thumbnail;
296   iface->get_dimensions = tiff_document_thumbnails_get_dimensions;
297 }
298
299
300 static void
301 tiff_document_init (TiffDocument *tiff_document)
302 {
303   tiff_document->n_pages = -1;
304 }