Removed dependency on tiffiop.h
[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_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 //-----------------------------------------------------------------------------
41 // wxTIFFHandler
42 //-----------------------------------------------------------------------------
43
44 IMPLEMENT_DYNAMIC_CLASS(wxTIFFHandler,wxImageHandler)
45
46 static tsize_t
47 _tiffReadProc(thandle_t handle, tdata_t buf, tsize_t size)
48 {
49 wxInputStream *stream = (wxInputStream*) handle;
50 stream->Read( (void*) buf, (size_t) size );
51 return stream->LastRead();
52 }
53
54 static tsize_t
55 _tiffWriteProc(thandle_t handle, tdata_t buf, tsize_t size)
56 {
57 wxOutputStream *stream = (wxOutputStream*) handle;
58 stream->Write( (void*) buf, (size_t) size );
59 return stream->LastWrite();
60 }
61
62 static toff_t
63 _tiffSeekProc(thandle_t handle, toff_t off, int whence)
64 {
65 wxInputStream *stream = (wxInputStream*) handle;
66 wxSeekMode mode;
67 switch (whence)
68 {
69 case SEEK_SET: mode = wxFromStart; break;
70 case SEEK_CUR: mode = wxFromCurrent; break;
71 case SEEK_END: mode = wxFromEnd; break;
72 default: mode = wxFromCurrent; break;
73 }
74
75 return (toff_t)stream->SeekI( (off_t)off, mode );
76 }
77
78 static int
79 _tiffCloseProc(thandle_t WXUNUSED(handle))
80 {
81 return 0; // ?
82 }
83
84 static toff_t
85 _tiffSizeProc(thandle_t handle)
86 {
87 wxInputStream *stream = (wxInputStream*) handle;
88 return (toff_t) stream->GetSize();
89 }
90
91 static int
92 _tiffMapProc(thandle_t WXUNUSED(handle),
93 tdata_t* WXUNUSED(pbase),
94 toff_t* WXUNUSED(psize))
95 {
96 return 0;
97 }
98
99 static void
100 _tiffUnmapProc(thandle_t WXUNUSED(handle),
101 tdata_t WXUNUSED(base),
102 toff_t WXUNUSED(size))
103 {
104 }
105
106 TIFF*
107 TIFFwxOpen(wxInputStream &stream, const char* name, const char* mode)
108 {
109 TIFF* tif = TIFFClientOpen(name, mode,
110 (thandle_t) &stream,
111 _tiffReadProc, _tiffWriteProc,
112 _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
113 _tiffMapProc, _tiffUnmapProc);
114
115 return tif;
116 }
117
118
119 bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int index )
120 {
121 image->Destroy();
122
123 TIFF *tif = TIFFwxOpen( stream, "image", "r" );
124
125 if (!tif)
126 {
127 if (verbose)
128 wxLogError( _("TIFF: Error loading image.") );
129
130 return FALSE;
131 }
132
133 if (!TIFFSetDirectory( tif, (tdir_t)index ))
134 {
135 if (verbose)
136 wxLogError( _("Invalid TIFF image index.") );
137
138 TIFFClose( tif );
139
140 return FALSE;
141 }
142
143 uint32 w, h;
144 uint32 npixels;
145 uint32 *raster;
146
147 TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &w );
148 TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &h );
149
150 npixels = w * h;
151
152 raster = (uint32*) _TIFFmalloc( npixels * sizeof(uint32) );
153
154 if (!raster)
155 {
156 if (verbose)
157 wxLogError( _("TIFF: Couldn't allocate memory.") );
158
159 return FALSE;
160 }
161
162 image->Create( (int)w, (int)h );
163 if (!image->Ok())
164 {
165 if (verbose)
166 wxLogError( _("TIFF: Couldn't allocate memory.") );
167
168 _TIFFfree( raster );
169
170 return FALSE;
171 }
172
173 if (!TIFFReadRGBAImage( tif, w, h, raster, 0 ))
174 {
175 if (verbose)
176 wxLogError( _("TIFF: Error reading image.") );
177
178 _TIFFfree( raster );
179 image->Destroy();
180
181 return FALSE;
182 }
183
184 bool hasmask = FALSE;
185
186 unsigned char *ptr = image->GetData();
187 ptr += w*3*(h-1);
188 uint32 pos = 0;
189
190 for (uint32 i = 0; i < h; i++)
191 {
192 for (uint32 j = 0; j < w; j++)
193 {
194 unsigned char alpha = (unsigned char)TIFFGetA(raster[pos]);
195 if (alpha < 127)
196 {
197 hasmask = TRUE;
198 ptr[0] = image->GetMaskRed();
199 ptr++;
200 ptr[0] = image->GetMaskGreen();
201 ptr++;
202 ptr[0] = image->GetMaskBlue();
203 ptr++;
204 }
205 else
206 {
207 ptr[0] = (unsigned char)TIFFGetR(raster[pos]);
208 ptr++;
209 ptr[0] = (unsigned char)TIFFGetG(raster[pos]);
210 ptr++;
211 ptr[0] = (unsigned char)TIFFGetB(raster[pos]);
212 ptr++;
213 }
214 pos++;
215 }
216 ptr -= 2*w*3; // subtract line we just added plus one line
217 }
218
219 _TIFFfree( raster );
220
221 TIFFClose( tif );
222
223 image->SetMask( hasmask );
224
225 return TRUE;
226 }
227
228 int wxTIFFHandler::GetImageCount( wxInputStream& stream )
229 {
230 TIFF *tif = TIFFwxOpen( stream, "image", "r" );
231
232 if (!tif)
233 return 0;
234
235 int dircount = 0; // according to the libtiff docs, dircount should be set to 1 here???
236 do {
237 dircount++;
238 } while (TIFFReadDirectory(tif));
239
240 TIFFClose( tif );
241
242 return dircount;
243 }
244
245 bool wxTIFFHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream), bool WXUNUSED(verbose) )
246 {
247 return FALSE;
248 }
249
250 bool wxTIFFHandler::DoCanRead( wxInputStream& stream )
251 {
252 unsigned char hdr[2];
253
254 stream.Read(&hdr, 2);
255 stream.SeekI(-2, wxFromCurrent);
256
257 return ((hdr[0] == 0x49 && hdr[1] == 0x49) ||
258 (hdr[0] == 0x4D && hdr[1] == 0x4D));
259 }
260
261
262 #endif
263 // wxUSE_LIBTIFF
264
265
266
267
268
269