]> git.saurik.com Git - wxWidgets.git/blame - src/common/imagtiff.cpp
Added chapter on collection and container classes to contents
[wxWidgets.git] / src / common / imagtiff.cpp
CommitLineData
257bcf28 1/////////////////////////////////////////////////////////////////////////////
8f493002
VS
2// Name: imagtiff.cpp
3// Purpose: wxImage TIFF handler
4// Author: Robert Roebling
257bcf28 5// RCS-ID: $Id$
8f493002 6// Copyright: (c) Robert Roebling
257bcf28
RR
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
8f493002
VS
10#ifdef __GNUG__
11#pragma implementation "imagtiff.h"
12#endif
257bcf28
RR
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
8f493002 25#include "wx/imagtiff.h"
257bcf28
RR
26#include "wx/bitmap.h"
27#include "wx/debug.h"
28#include "wx/log.h"
29#include "wx/app.h"
30extern "C"
31{
32 #include "tiff.h"
33 #include "tiffio.h"
257bcf28
RR
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
257bcf28 44IMPLEMENT_DYNAMIC_CLASS(wxTIFFHandler,wxImageHandler)
257bcf28 45
f6bcfd97
BP
46static 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
257bcf28
RR
54static 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 );
0b72db08 59 return stream->LastRead();
257bcf28
RR
60}
61
62static 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 );
0b72db08 67 return stream->LastWrite();
257bcf28
RR
68}
69
70static toff_t
f6bcfd97 71_tiffSeekIProc(thandle_t handle, toff_t off, int whence)
257bcf28
RR
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 }
13111b2a 82
257bcf28
RR
83 return (toff_t)stream->SeekI( (off_t)off, mode );
84}
85
f6bcfd97
BP
86static 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
257bcf28
RR
102static int
103_tiffCloseProc(thandle_t WXUNUSED(handle))
104{
105 return 0; // ?
106}
107
108static toff_t
109_tiffSizeProc(thandle_t handle)
110{
f6bcfd97 111 wxStreamBase *stream = (wxStreamBase*) handle;
0b72db08 112 return (toff_t) stream->GetSize();
257bcf28
RR
113}
114
115static int
13111b2a
VZ
116_tiffMapProc(thandle_t WXUNUSED(handle),
117 tdata_t* WXUNUSED(pbase),
118 toff_t* WXUNUSED(psize))
257bcf28
RR
119{
120 return 0;
121}
122
123static void
13111b2a
VZ
124_tiffUnmapProc(thandle_t WXUNUSED(handle),
125 tdata_t WXUNUSED(base),
126 toff_t WXUNUSED(size))
257bcf28
RR
127{
128}
129
130TIFF*
131TIFFwxOpen(wxInputStream &stream, const char* name, const char* mode)
132{
133 TIFF* tif = TIFFClientOpen(name, mode,
134 (thandle_t) &stream,
f6bcfd97
BP
135 _tiffReadProc, _tiffNullProc,
136 _tiffSeekIProc, _tiffCloseProc, _tiffSizeProc,
257bcf28
RR
137 _tiffMapProc, _tiffUnmapProc);
138
257bcf28
RR
139 return tif;
140}
141
f6bcfd97
BP
142TIFF*
143TIFFwxOpen(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}
257bcf28 153
700ec454 154bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int index )
257bcf28
RR
155{
156 image->Destroy();
13111b2a 157
0b72db08 158 TIFF *tif = TIFFwxOpen( stream, "image", "r" );
13111b2a 159
257bcf28
RR
160 if (!tif)
161 {
162 if (verbose)
58c837a4 163 wxLogError( _("TIFF: Error loading image.") );
13111b2a
VZ
164
165 return FALSE;
257bcf28 166 }
13111b2a 167
700ec454
RR
168 if (!TIFFSetDirectory( tif, (tdir_t)index ))
169 {
170 if (verbose)
171 wxLogError( _("Invalid TIFF image index.") );
13111b2a 172
700ec454 173 TIFFClose( tif );
13111b2a
VZ
174
175 return FALSE;
700ec454 176 }
257bcf28
RR
177
178 uint32 w, h;
13111b2a 179 uint32 npixels;
257bcf28 180 uint32 *raster;
13111b2a 181
257bcf28
RR
182 TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &w );
183 TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &h );
13111b2a 184
257bcf28 185 npixels = w * h;
13111b2a 186
257bcf28 187 raster = (uint32*) _TIFFmalloc( npixels * sizeof(uint32) );
13111b2a 188
257bcf28
RR
189 if (!raster)
190 {
191 if (verbose)
58c837a4 192 wxLogError( _("TIFF: Couldn't allocate memory.") );
f6bcfd97
BP
193
194 TIFFClose( tif );
13111b2a
VZ
195
196 return FALSE;
257bcf28
RR
197 }
198
479cd5de 199 image->Create( (int)w, (int)h );
13111b2a 200 if (!image->Ok())
257bcf28
RR
201 {
202 if (verbose)
58c837a4 203 wxLogError( _("TIFF: Couldn't allocate memory.") );
13111b2a
VZ
204
205 _TIFFfree( raster );
f6bcfd97 206 TIFFClose( tif );
13111b2a 207
257bcf28
RR
208 return FALSE;
209 }
13111b2a 210
257bcf28
RR
211 if (!TIFFReadRGBAImage( tif, w, h, raster, 0 ))
212 {
213 if (verbose)
58c837a4 214 wxLogError( _("TIFF: Error reading image.") );
13111b2a
VZ
215
216 _TIFFfree( raster );
217 image->Destroy();
f6bcfd97 218 TIFFClose( tif );
13111b2a
VZ
219
220 return FALSE;
257bcf28 221 }
13111b2a 222
257bcf28 223 bool hasmask = FALSE;
13111b2a 224
257bcf28 225 unsigned char *ptr = image->GetData();
5c5ab9eb 226 ptr += w*3*(h-1);
257bcf28 227 uint32 pos = 0;
13111b2a 228
257bcf28
RR
229 for (uint32 i = 0; i < h; i++)
230 {
ff7c6c9c 231 for (uint32 j = 0; j < w; j++)
13111b2a 232 {
5c5ab9eb 233 unsigned char alpha = (unsigned char)TIFFGetA(raster[pos]);
13111b2a
VZ
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 {
5c5ab9eb 246 ptr[0] = (unsigned char)TIFFGetR(raster[pos]);
13111b2a 247 ptr++;
5c5ab9eb 248 ptr[0] = (unsigned char)TIFFGetG(raster[pos]);
13111b2a 249 ptr++;
5c5ab9eb 250 ptr[0] = (unsigned char)TIFFGetB(raster[pos]);
13111b2a
VZ
251 ptr++;
252 }
253 pos++;
254 }
5c5ab9eb 255 ptr -= 2*w*3; // subtract line we just added plus one line
257bcf28 256 }
13111b2a 257
257bcf28 258 _TIFFfree( raster );
13111b2a 259
257bcf28 260 TIFFClose( tif );
13111b2a 261
257bcf28 262 image->SetMask( hasmask );
13111b2a 263
257bcf28
RR
264 return TRUE;
265}
266
700ec454
RR
267int wxTIFFHandler::GetImageCount( wxInputStream& stream )
268{
269 TIFF *tif = TIFFwxOpen( stream, "image", "r" );
13111b2a 270
700ec454 271 if (!tif)
13111b2a 272 return 0;
257bcf28 273
700ec454
RR
274 int dircount = 0; // according to the libtiff docs, dircount should be set to 1 here???
275 do {
276 dircount++;
277 } while (TIFFReadDirectory(tif));
13111b2a 278
700ec454 279 TIFFClose( tif );
13111b2a 280
700ec454
RR
281 return dircount;
282}
257bcf28 283
f6bcfd97 284bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )
257bcf28 285{
f6bcfd97
BP
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;
257bcf28
RR
355}
356
357bool wxTIFFHandler::DoCanRead( wxInputStream& stream )
358{
0b72db08 359 unsigned char hdr[2];
257bcf28 360
0b72db08
RR
361 stream.Read(&hdr, 2);
362 stream.SeekI(-2, wxFromCurrent);
13111b2a 363
0b72db08
RR
364 return ((hdr[0] == 0x49 && hdr[1] == 0x49) ||
365 (hdr[0] == 0x4D && hdr[1] == 0x4D));
257bcf28
RR
366}
367
368
369#endif
370 // wxUSE_LIBTIFF
371
372