]> git.saurik.com Git - wxWidgets.git/blob - src/common/imagtiff.cpp
Added chapter on collection and container classes to contents
[wxWidgets.git] / src / common / imagtiff.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: imagtiff.cpp
3 // Purpose: wxImage TIFF handler
4 // Author: Robert Roebling
5 // RCS-ID: $Id$
6 // Copyright: (c) Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "imagtiff.h"
12 #endif
13
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #include "wx/defs.h"
22
23 #if wxUSE_LIBTIFF
24
25 #include "wx/imagtiff.h"
26 #include "wx/bitmap.h"
27 #include "wx/debug.h"
28 #include "wx/log.h"
29 #include "wx/app.h"
30 extern "C"
31 {
32 #include "tiff.h"
33 #include "tiffio.h"
34 }
35 #include "wx/filefn.h"
36 #include "wx/wfstream.h"
37 #include "wx/intl.h"
38 #include "wx/module.h"
39
40 //-----------------------------------------------------------------------------
41 // wxTIFFHandler
42 //-----------------------------------------------------------------------------
43
44 IMPLEMENT_DYNAMIC_CLASS(wxTIFFHandler,wxImageHandler)
45
46 static tsize_t
47 _tiffNullProc(thandle_t WXUNUSED(handle),
48 tdata_t WXUNUSED(buf),
49 tsize_t WXUNUSED(size))
50 {
51 return (tsize_t) -1;
52 }
53
54 static tsize_t
55 _tiffReadProc(thandle_t handle, tdata_t buf, tsize_t size)
56 {
57 wxInputStream *stream = (wxInputStream*) handle;
58 stream->Read( (void*) buf, (size_t) size );
59 return stream->LastRead();
60 }
61
62 static tsize_t
63 _tiffWriteProc(thandle_t handle, tdata_t buf, tsize_t size)
64 {
65 wxOutputStream *stream = (wxOutputStream*) handle;
66 stream->Write( (void*) buf, (size_t) size );
67 return stream->LastWrite();
68 }
69
70 static toff_t
71 _tiffSeekIProc(thandle_t handle, toff_t off, int whence)
72 {
73 wxInputStream *stream = (wxInputStream*) handle;
74 wxSeekMode mode;
75 switch (whence)
76 {
77 case SEEK_SET: mode = wxFromStart; break;
78 case SEEK_CUR: mode = wxFromCurrent; break;
79 case SEEK_END: mode = wxFromEnd; break;
80 default: mode = wxFromCurrent; break;
81 }
82
83 return (toff_t)stream->SeekI( (off_t)off, mode );
84 }
85
86 static toff_t
87 _tiffSeekOProc(thandle_t handle, toff_t off, int whence)
88 {
89 wxOutputStream *stream = (wxOutputStream*) handle;
90 wxSeekMode mode;
91 switch (whence)
92 {
93 case SEEK_SET: mode = wxFromStart; break;
94 case SEEK_CUR: mode = wxFromCurrent; break;
95 case SEEK_END: mode = wxFromEnd; break;
96 default: mode = wxFromCurrent; break;
97 }
98
99 return (toff_t)stream->SeekO( (off_t)off, mode );
100 }
101
102 static int
103 _tiffCloseProc(thandle_t WXUNUSED(handle))
104 {
105 return 0; // ?
106 }
107
108 static toff_t
109 _tiffSizeProc(thandle_t handle)
110 {
111 wxStreamBase *stream = (wxStreamBase*) handle;
112 return (toff_t) stream->GetSize();
113 }
114
115 static int
116 _tiffMapProc(thandle_t WXUNUSED(handle),
117 tdata_t* WXUNUSED(pbase),
118 toff_t* WXUNUSED(psize))
119 {
120 return 0;
121 }
122
123 static void
124 _tiffUnmapProc(thandle_t WXUNUSED(handle),
125 tdata_t WXUNUSED(base),
126 toff_t WXUNUSED(size))
127 {
128 }
129
130 TIFF*
131 TIFFwxOpen(wxInputStream &stream, const char* name, const char* mode)
132 {
133 TIFF* tif = TIFFClientOpen(name, mode,
134 (thandle_t) &stream,
135 _tiffReadProc, _tiffNullProc,
136 _tiffSeekIProc, _tiffCloseProc, _tiffSizeProc,
137 _tiffMapProc, _tiffUnmapProc);
138
139 return tif;
140 }
141
142 TIFF*
143 TIFFwxOpen(wxOutputStream &stream, const char* name, const char* mode)
144 {
145 TIFF* tif = TIFFClientOpen(name, mode,
146 (thandle_t) &stream,
147 _tiffNullProc, _tiffWriteProc,
148 _tiffSeekOProc, _tiffCloseProc, _tiffSizeProc,
149 _tiffMapProc, _tiffUnmapProc);
150
151 return tif;
152 }
153
154 bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int index )
155 {
156 image->Destroy();
157
158 TIFF *tif = TIFFwxOpen( stream, "image", "r" );
159
160 if (!tif)
161 {
162 if (verbose)
163 wxLogError( _("TIFF: Error loading image.") );
164
165 return FALSE;
166 }
167
168 if (!TIFFSetDirectory( tif, (tdir_t)index ))
169 {
170 if (verbose)
171 wxLogError( _("Invalid TIFF image index.") );
172
173 TIFFClose( tif );
174
175 return FALSE;
176 }
177
178 uint32 w, h;
179 uint32 npixels;
180 uint32 *raster;
181
182 TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &w );
183 TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &h );
184
185 npixels = w * h;
186
187 raster = (uint32*) _TIFFmalloc( npixels * sizeof(uint32) );
188
189 if (!raster)
190 {
191 if (verbose)
192 wxLogError( _("TIFF: Couldn't allocate memory.") );
193
194 TIFFClose( tif );
195
196 return FALSE;
197 }
198
199 image->Create( (int)w, (int)h );
200 if (!image->Ok())
201 {
202 if (verbose)
203 wxLogError( _("TIFF: Couldn't allocate memory.") );
204
205 _TIFFfree( raster );
206 TIFFClose( tif );
207
208 return FALSE;
209 }
210
211 if (!TIFFReadRGBAImage( tif, w, h, raster, 0 ))
212 {
213 if (verbose)
214 wxLogError( _("TIFF: Error reading image.") );
215
216 _TIFFfree( raster );
217 image->Destroy();
218 TIFFClose( tif );
219
220 return FALSE;
221 }
222
223 bool hasmask = FALSE;
224
225 unsigned char *ptr = image->GetData();
226 ptr += w*3*(h-1);
227 uint32 pos = 0;
228
229 for (uint32 i = 0; i < h; i++)
230 {
231 for (uint32 j = 0; j < w; j++)
232 {
233 unsigned char alpha = (unsigned char)TIFFGetA(raster[pos]);
234 if (alpha < 127)
235 {
236 hasmask = TRUE;
237 ptr[0] = image->GetMaskRed();
238 ptr++;
239 ptr[0] = image->GetMaskGreen();
240 ptr++;
241 ptr[0] = image->GetMaskBlue();
242 ptr++;
243 }
244 else
245 {
246 ptr[0] = (unsigned char)TIFFGetR(raster[pos]);
247 ptr++;
248 ptr[0] = (unsigned char)TIFFGetG(raster[pos]);
249 ptr++;
250 ptr[0] = (unsigned char)TIFFGetB(raster[pos]);
251 ptr++;
252 }
253 pos++;
254 }
255 ptr -= 2*w*3; // subtract line we just added plus one line
256 }
257
258 _TIFFfree( raster );
259
260 TIFFClose( tif );
261
262 image->SetMask( hasmask );
263
264 return TRUE;
265 }
266
267 int wxTIFFHandler::GetImageCount( wxInputStream& stream )
268 {
269 TIFF *tif = TIFFwxOpen( stream, "image", "r" );
270
271 if (!tif)
272 return 0;
273
274 int dircount = 0; // according to the libtiff docs, dircount should be set to 1 here???
275 do {
276 dircount++;
277 } while (TIFFReadDirectory(tif));
278
279 TIFFClose( tif );
280
281 return dircount;
282 }
283
284 bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )
285 {
286 TIFF *tif = TIFFwxOpen( stream, "image", "w" );
287
288 if (!tif)
289 {
290 if (verbose)
291 wxLogError( _("TIFF: Error saving image.") );
292
293 return FALSE;
294 }
295
296 TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32)image->GetWidth());
297 TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32)image->GetHeight());
298 TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
299 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3);
300 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
301 TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
302 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
303 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
304
305 tsize_t linebytes = (tsize_t)image->GetWidth() * 3;
306 unsigned char *buf;
307
308 if (TIFFScanlineSize(tif) > linebytes)
309 {
310 buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(tif));
311 if (!buf)
312 {
313 if (verbose)
314 wxLogError( _("TIFF: Couldn't allocate memory.") );
315
316 TIFFClose( tif );
317
318 return FALSE;
319 }
320 }
321 else
322 {
323 buf = NULL;
324 }
325
326 TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP,
327 TIFFDefaultStripSize(tif, (uint32) -1));
328
329 unsigned char *ptr = image->GetData();
330 for (int row = 0; row < image->GetHeight(); row++)
331 {
332 if (buf)
333 memcpy(buf, ptr, image->GetWidth());
334
335 if (TIFFWriteScanline(tif, buf ? buf : ptr, (uint32)row, 0) < 0)
336 {
337 if (verbose)
338 wxLogError( _("TIFF: Error writing image.") );
339
340 TIFFClose( tif );
341 if (buf)
342 _TIFFfree(buf);
343
344 return FALSE;
345 }
346 ptr += image->GetWidth()*3;
347 }
348
349 (void) TIFFClose(tif);
350
351 if (buf)
352 _TIFFfree(buf);
353
354 return TRUE;
355 }
356
357 bool wxTIFFHandler::DoCanRead( wxInputStream& stream )
358 {
359 unsigned char hdr[2];
360
361 stream.Read(&hdr, 2);
362 stream.SeekI(-2, wxFromCurrent);
363
364 return ((hdr[0] == 0x49 && hdr[1] == 0x49) ||
365 (hdr[0] == 0x4D && hdr[1] == 0x4D));
366 }
367
368
369 #endif
370 // wxUSE_LIBTIFF
371
372