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