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