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