/[pcsx2_0.9.7]/trunk/3rdparty/wxWidgets/src/common/imagtiff.cpp
ViewVC logotype

Annotation of /trunk/3rdparty/wxWidgets/src/common/imagtiff.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations) (download)
Mon Sep 6 11:40:06 2010 UTC (9 years, 10 months ago) by william
File size: 13578 byte(s)
exported r3113 from ./upstream/trunk
1 william 10 /////////////////////////////////////////////////////////////////////////////
2     // Name: src/common/imagtiff.cpp
3     // Purpose: wxImage TIFF handler
4     // Author: Robert Roebling
5     // RCS-ID: $Id: imagtiff.cpp 48694 2007-09-14 23:21:29Z VZ $
6     // Copyright: (c) Robert Roebling
7     // Licence: wxWindows licence
8     /////////////////////////////////////////////////////////////////////////////
9    
10     // For compilers that support precompilation, includes "wx.h".
11     #include "wx/wxprec.h"
12    
13     #ifdef __BORLANDC__
14     #pragma hdrstop
15     #endif
16    
17     #if wxUSE_IMAGE && wxUSE_LIBTIFF
18    
19     #include "wx/imagtiff.h"
20    
21     #ifndef WX_PRECOMP
22     #include "wx/log.h"
23     #include "wx/app.h"
24     #include "wx/intl.h"
25     #include "wx/bitmap.h"
26     #include "wx/module.h"
27     #endif
28    
29     extern "C"
30     {
31     #include "tiff.h"
32     #include "tiffio.h"
33     }
34     #include "wx/filefn.h"
35     #include "wx/wfstream.h"
36    
37     #ifndef TIFFLINKAGEMODE
38     #if defined(__WATCOMC__) && defined(__WXMGL__)
39     #define TIFFLINKAGEMODE cdecl
40     #else
41     #define TIFFLINKAGEMODE LINKAGEMODE
42     #endif
43     #endif
44    
45     //-----------------------------------------------------------------------------
46     // wxTIFFHandler
47     //-----------------------------------------------------------------------------
48    
49     IMPLEMENT_DYNAMIC_CLASS(wxTIFFHandler,wxImageHandler)
50    
51     #if wxUSE_STREAMS
52    
53     // helper to translate our, possibly 64 bit, wxFileOffset to TIFF, always 32
54     // bit, toff_t
55     static toff_t wxFileOffsetToTIFF(wxFileOffset ofs)
56     {
57     if ( ofs == wxInvalidOffset )
58     return (toff_t)-1;
59    
60     toff_t tofs = wx_truncate_cast(toff_t, ofs);
61     wxCHECK_MSG( (wxFileOffset)tofs == ofs, (toff_t)-1,
62     _T("TIFF library doesn't support large files") );
63    
64     return tofs;
65     }
66    
67     // another helper to convert standard seek mode to our
68     static wxSeekMode wxSeekModeFromTIFF(int whence)
69     {
70     switch ( whence )
71     {
72     case SEEK_SET:
73     return wxFromStart;
74    
75     case SEEK_CUR:
76     return wxFromCurrent;
77    
78     case SEEK_END:
79     return wxFromEnd;
80    
81     default:
82     return wxFromCurrent;
83     }
84     }
85    
86     extern "C"
87     {
88    
89     tsize_t TIFFLINKAGEMODE
90     wxTIFFNullProc(thandle_t WXUNUSED(handle),
91     tdata_t WXUNUSED(buf),
92     tsize_t WXUNUSED(size))
93     {
94     return (tsize_t) -1;
95     }
96    
97     tsize_t TIFFLINKAGEMODE
98     wxTIFFReadProc(thandle_t handle, tdata_t buf, tsize_t size)
99     {
100     wxInputStream *stream = (wxInputStream*) handle;
101     stream->Read( (void*) buf, (size_t) size );
102     return wx_truncate_cast(tsize_t, stream->LastRead());
103     }
104    
105     tsize_t TIFFLINKAGEMODE
106     wxTIFFWriteProc(thandle_t handle, tdata_t buf, tsize_t size)
107     {
108     wxOutputStream *stream = (wxOutputStream*) handle;
109     stream->Write( (void*) buf, (size_t) size );
110     return wx_truncate_cast(tsize_t, stream->LastWrite());
111     }
112    
113     toff_t TIFFLINKAGEMODE
114     wxTIFFSeekIProc(thandle_t handle, toff_t off, int whence)
115     {
116     wxInputStream *stream = (wxInputStream*) handle;
117    
118     return wxFileOffsetToTIFF(stream->SeekI((wxFileOffset)off,
119     wxSeekModeFromTIFF(whence)));
120     }
121    
122     toff_t TIFFLINKAGEMODE
123     wxTIFFSeekOProc(thandle_t handle, toff_t off, int whence)
124     {
125     wxOutputStream *stream = (wxOutputStream*) handle;
126    
127     return wxFileOffsetToTIFF(stream->SeekO((wxFileOffset)off,
128     wxSeekModeFromTIFF(whence)));
129     }
130    
131     int TIFFLINKAGEMODE
132     wxTIFFCloseIProc(thandle_t WXUNUSED(handle))
133     {
134     // there is no need to close the input stream
135     return 0;
136     }
137    
138     int TIFFLINKAGEMODE
139     wxTIFFCloseOProc(thandle_t handle)
140     {
141     wxOutputStream *stream = (wxOutputStream*) handle;
142    
143     return stream->Close() ? 0 : -1;
144     }
145    
146     toff_t TIFFLINKAGEMODE
147     wxTIFFSizeProc(thandle_t handle)
148     {
149     wxStreamBase *stream = (wxStreamBase*) handle;
150     return (toff_t) stream->GetSize();
151     }
152    
153     int TIFFLINKAGEMODE
154     wxTIFFMapProc(thandle_t WXUNUSED(handle),
155     tdata_t* WXUNUSED(pbase),
156     toff_t* WXUNUSED(psize))
157     {
158     return 0;
159     }
160    
161     void TIFFLINKAGEMODE
162     wxTIFFUnmapProc(thandle_t WXUNUSED(handle),
163     tdata_t WXUNUSED(base),
164     toff_t WXUNUSED(size))
165     {
166     }
167    
168     static void
169     TIFFwxWarningHandler(const char* module,
170     const char* WXUNUSED_IN_UNICODE(fmt),
171     va_list WXUNUSED_IN_UNICODE(ap))
172     {
173     if (module != NULL)
174     wxLogWarning(_("tiff module: %s"), wxString::FromAscii(module).c_str());
175    
176     // FIXME: this is not terrible informative but better than crashing!
177     #if wxUSE_UNICODE
178     wxLogWarning(_("TIFF library warning."));
179     #else
180     wxVLogWarning(fmt, ap);
181     #endif
182     }
183    
184     static void
185     TIFFwxErrorHandler(const char* module,
186     const char* WXUNUSED_IN_UNICODE(fmt),
187     va_list WXUNUSED_IN_UNICODE(ap))
188     {
189     if (module != NULL)
190     wxLogError(_("tiff module: %s"), wxString::FromAscii(module).c_str());
191    
192     // FIXME: as above
193     #if wxUSE_UNICODE
194     wxLogError(_("TIFF library error."));
195     #else
196     wxVLogError(fmt, ap);
197     #endif
198     }
199    
200     } // extern "C"
201    
202     TIFF*
203     TIFFwxOpen(wxInputStream &stream, const char* name, const char* mode)
204     {
205     TIFF* tif = TIFFClientOpen(name, mode,
206     (thandle_t) &stream,
207     wxTIFFReadProc, wxTIFFNullProc,
208     wxTIFFSeekIProc, wxTIFFCloseIProc, wxTIFFSizeProc,
209     wxTIFFMapProc, wxTIFFUnmapProc);
210    
211     return tif;
212     }
213    
214     TIFF*
215     TIFFwxOpen(wxOutputStream &stream, const char* name, const char* mode)
216     {
217     TIFF* tif = TIFFClientOpen(name, mode,
218     (thandle_t) &stream,
219     wxTIFFNullProc, wxTIFFWriteProc,
220     wxTIFFSeekOProc, wxTIFFCloseOProc, wxTIFFSizeProc,
221     wxTIFFMapProc, wxTIFFUnmapProc);
222    
223     return tif;
224     }
225    
226     wxTIFFHandler::wxTIFFHandler()
227     {
228     m_name = wxT("TIFF file");
229     m_extension = wxT("tif");
230     m_type = wxBITMAP_TYPE_TIF;
231     m_mime = wxT("image/tiff");
232     TIFFSetWarningHandler((TIFFErrorHandler) TIFFwxWarningHandler);
233     TIFFSetErrorHandler((TIFFErrorHandler) TIFFwxErrorHandler);
234     }
235    
236     bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int index )
237     {
238     if (index == -1)
239     index = 0;
240    
241     image->Destroy();
242    
243     TIFF *tif = TIFFwxOpen( stream, "image", "r" );
244    
245     if (!tif)
246     {
247     if (verbose)
248     wxLogError( _("TIFF: Error loading image.") );
249    
250     return false;
251     }
252    
253     if (!TIFFSetDirectory( tif, (tdir_t)index ))
254     {
255     if (verbose)
256     wxLogError( _("Invalid TIFF image index.") );
257    
258     TIFFClose( tif );
259    
260     return false;
261     }
262    
263     uint32 w, h;
264     uint32 npixels;
265     uint32 *raster;
266    
267     TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &w );
268     TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &h );
269    
270     uint16 extraSamples;
271     uint16* samplesInfo;
272     TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
273     &extraSamples, &samplesInfo);
274     const bool hasAlpha = (extraSamples == 1 &&
275     (samplesInfo[0] == EXTRASAMPLE_ASSOCALPHA ||
276     samplesInfo[0] == EXTRASAMPLE_UNASSALPHA));
277    
278     npixels = w * h;
279    
280     raster = (uint32*) _TIFFmalloc( npixels * sizeof(uint32) );
281    
282     if (!raster)
283     {
284     if (verbose)
285     wxLogError( _("TIFF: Couldn't allocate memory.") );
286    
287     TIFFClose( tif );
288    
289     return false;
290     }
291    
292     image->Create( (int)w, (int)h );
293     if (!image->Ok())
294     {
295     if (verbose)
296     wxLogError( _("TIFF: Couldn't allocate memory.") );
297    
298     _TIFFfree( raster );
299     TIFFClose( tif );
300    
301     return false;
302     }
303    
304     if ( hasAlpha )
305     image->SetAlpha();
306    
307     if (!TIFFReadRGBAImage( tif, w, h, raster, 0 ))
308     {
309     if (verbose)
310     wxLogError( _("TIFF: Error reading image.") );
311    
312     _TIFFfree( raster );
313     image->Destroy();
314     TIFFClose( tif );
315    
316     return false;
317     }
318    
319     unsigned char *ptr = image->GetData();
320     ptr += w*3*(h-1);
321    
322     unsigned char *alpha = hasAlpha ? image->GetAlpha() : NULL;
323     if ( hasAlpha )
324     alpha += w*(h-1);
325    
326     uint32 pos = 0;
327    
328     for (uint32 i = 0; i < h; i++)
329     {
330     for (uint32 j = 0; j < w; j++)
331     {
332     *(ptr++) = (unsigned char)TIFFGetR(raster[pos]);
333     *(ptr++) = (unsigned char)TIFFGetG(raster[pos]);
334     *(ptr++) = (unsigned char)TIFFGetB(raster[pos]);
335     if ( hasAlpha )
336     *(alpha++) = (unsigned char)TIFFGetA(raster[pos]);
337    
338     pos++;
339     }
340    
341     // subtract line we just added plus one line:
342     ptr -= 2*w*3;
343     if ( hasAlpha )
344     alpha -= 2*w;
345     }
346    
347     _TIFFfree( raster );
348    
349     TIFFClose( tif );
350    
351     return true;
352     }
353    
354     int wxTIFFHandler::GetImageCount( wxInputStream& stream )
355     {
356     TIFF *tif = TIFFwxOpen( stream, "image", "r" );
357    
358     if (!tif)
359     return 0;
360    
361     int dircount = 0; // according to the libtiff docs, dircount should be set to 1 here???
362     do {
363     dircount++;
364     } while (TIFFReadDirectory(tif));
365    
366     TIFFClose( tif );
367    
368     return dircount;
369     }
370    
371     bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )
372     {
373     TIFF *tif = TIFFwxOpen( stream, "image", "w" );
374    
375     if (!tif)
376     {
377     if (verbose)
378     wxLogError( _("TIFF: Error saving image.") );
379    
380     return false;
381     }
382    
383     TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
384     TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32)image->GetWidth());
385     TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32)image->GetHeight());
386     TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
387     TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
388    
389     if ( image->HasOption(wxIMAGE_OPTION_RESOLUTIONX) &&
390     image->HasOption(wxIMAGE_OPTION_RESOLUTIONY) )
391     {
392     TIFFSetField(tif, TIFFTAG_XRESOLUTION,
393     (float)image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX));
394     TIFFSetField(tif, TIFFTAG_YRESOLUTION,
395     (float)image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY));
396     }
397    
398     int spp = image->GetOptionInt(wxIMAGE_OPTION_SAMPLESPERPIXEL);
399     if ( !spp )
400     spp = 3;
401    
402     int bpp = image->GetOptionInt(wxIMAGE_OPTION_BITSPERSAMPLE);
403     if ( !bpp )
404     bpp=8;
405    
406     int compression = image->GetOptionInt(wxIMAGE_OPTION_COMPRESSION);
407     if ( !compression )
408     {
409     // we can't use COMPRESSION_LZW because current version of libtiff
410     // doesn't implement it ("no longer implemented due to Unisys patent
411     // enforcement") and other compression methods are lossy so we
412     // shouldn't use them by default -- and the only remaining one is none
413     compression = COMPRESSION_NONE;
414     }
415    
416     TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, spp);
417     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bpp);
418     TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, spp*bpp == 1 ? PHOTOMETRIC_MINISBLACK
419     : PHOTOMETRIC_RGB);
420     TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);
421    
422     // scanlinesize if determined by spp and bpp
423     tsize_t linebytes = (tsize_t)image->GetWidth() * spp * bpp / 8;
424    
425     if ( (image->GetWidth() % 8 > 0) && (spp * bpp < 8) )
426     linebytes+=1;
427    
428     unsigned char *buf;
429    
430     if (TIFFScanlineSize(tif) > linebytes || (spp * bpp < 24))
431     {
432     buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(tif));
433     if (!buf)
434     {
435     if (verbose)
436     wxLogError( _("TIFF: Couldn't allocate memory.") );
437    
438     TIFFClose( tif );
439    
440     return false;
441     }
442     }
443     else
444     {
445     buf = NULL;
446     }
447    
448     TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP,TIFFDefaultStripSize(tif, (uint32) -1));
449    
450     unsigned char *ptr = image->GetData();
451     for ( int row = 0; row < image->GetHeight(); row++ )
452     {
453     if ( buf )
454     {
455     if ( spp * bpp > 1 )
456     {
457     // color image
458     memcpy(buf, ptr, image->GetWidth());
459     }
460     else // black and white image
461     {
462     for ( int column = 0; column < linebytes; column++ )
463     {
464     uint8 reverse = 0;
465     for ( int bp = 0; bp < 8; bp++ )
466     {
467     if ( ptr[column*24 + bp*3] > 0 )
468     {
469     // check only red as this is sufficient
470     reverse = (uint8)(reverse | 128 >> bp);
471     }
472     }
473    
474     buf[column] = reverse;
475     }
476     }
477     }
478    
479     if ( TIFFWriteScanline(tif, buf ? buf : ptr, (uint32)row, 0) < 0 )
480     {
481     if (verbose)
482     wxLogError( _("TIFF: Error writing image.") );
483    
484     TIFFClose( tif );
485     if (buf)
486     _TIFFfree(buf);
487    
488     return false;
489     }
490    
491     ptr += image->GetWidth()*3;
492     }
493    
494     (void) TIFFClose(tif);
495    
496     if (buf)
497     _TIFFfree(buf);
498    
499     return true;
500     }
501    
502     bool wxTIFFHandler::DoCanRead( wxInputStream& stream )
503     {
504     unsigned char hdr[2];
505    
506     if ( !stream.Read(&hdr[0], WXSIZEOF(hdr)) )
507     return false;
508    
509     return (hdr[0] == 'I' && hdr[1] == 'I') ||
510     (hdr[0] == 'M' && hdr[1] == 'M');
511     }
512    
513     #endif // wxUSE_STREAMS
514    
515     #endif // wxUSE_LIBTIFF

  ViewVC Help
Powered by ViewVC 1.1.22