]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/imagtiff.cpp
OS/2 updates for statusbar processing and easier VA debugging
[wxWidgets.git] / src / common / imagtiff.cpp
... / ...
CommitLineData
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"
30extern "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
44IMPLEMENT_DYNAMIC_CLASS(wxTIFFHandler,wxImageHandler)
45
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
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 );
59 return stream->LastRead();
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 );
67 return stream->LastWrite();
68}
69
70static 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
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
102static int
103_tiffCloseProc(thandle_t WXUNUSED(handle))
104{
105 return 0; // ?
106}
107
108static toff_t
109_tiffSizeProc(thandle_t handle)
110{
111 wxStreamBase *stream = (wxStreamBase*) handle;
112 return (toff_t) stream->GetSize();
113}
114
115static int
116_tiffMapProc(thandle_t WXUNUSED(handle),
117 tdata_t* WXUNUSED(pbase),
118 toff_t* WXUNUSED(psize))
119{
120 return 0;
121}
122
123static void
124_tiffUnmapProc(thandle_t WXUNUSED(handle),
125 tdata_t WXUNUSED(base),
126 toff_t WXUNUSED(size))
127{
128}
129
130TIFF*
131TIFFwxOpen(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
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}
153
154bool 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
267int 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
284bool 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
357bool 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