1 /* This file is (c) 2014 Abs62
2  * Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
3 
4 #ifdef MAKE_EXTRA_TIFF_HANDLER
5 
6 #include "tiff.hh"
7 
8 #if defined (Q_OS_MAC) || defined (Q_OS_WIN)
9 #include "tiff/tiff.h"
10 #include "tiff/tiffio.h"
11 #else
12 #include "tiff.h"
13 #include "tiffio.h"
14 #endif
15 
16 #include <QBuffer>
17 
18 namespace GdTiff
19 {
20 
tiffReadProc(thandle_t fd,tdata_t buf,tsize_t size)21 tsize_t tiffReadProc( thandle_t fd, tdata_t buf, tsize_t size )
22 {
23   return static_cast< QIODevice * >( fd )->read( static_cast< char * >( buf ), size );
24 }
25 
tiffWriteProc(thandle_t fd,tdata_t buf,tsize_t size)26 tsize_t tiffWriteProc( thandle_t fd, tdata_t buf, tsize_t size )
27 {
28 Q_UNUSED( fd )
29 Q_UNUSED( buf )
30 Q_UNUSED( size )
31   return 0;
32 }
33 
tiffSeekProc(thandle_t fd,toff_t off,int whence)34 toff_t tiffSeekProc( thandle_t fd, toff_t off, int whence )
35 {
36   QIODevice * device = static_cast< QIODevice * >( fd );
37   switch (whence) {
38     case SEEK_SET:
39         device->seek( off );
40         break;
41     case SEEK_CUR:
42         device->seek( device->pos() + off );
43         break;
44     case SEEK_END:
45         device->seek( device->size() + off );
46         break;
47   }
48 
49   return device->pos();
50 }
51 
tiffCloseProc(thandle_t fd)52 int tiffCloseProc( thandle_t fd )
53 {
54 Q_UNUSED( fd )
55   return 0;
56 }
57 
tiffSizeProc(thandle_t fd)58 toff_t tiffSizeProc( thandle_t fd )
59 {
60   return static_cast< QIODevice * >( fd )->size();
61 }
62 
tiffMapProc(thandle_t fd,tdata_t * pbase,toff_t * psize)63 int tiffMapProc( thandle_t fd, tdata_t * pbase, toff_t * psize )
64 {
65 Q_UNUSED( fd )
66 Q_UNUSED( pbase )
67 Q_UNUSED( psize )
68   return 0;
69 }
70 
tiffUnmapProc(thandle_t fd,tdata_t base,toff_t size)71 void tiffUnmapProc( thandle_t fd, tdata_t base, toff_t size )
72 {
73 Q_UNUSED( fd )
74 Q_UNUSED( base )
75 Q_UNUSED( size )
76 }
77 
78 
tiffToQImage(const char * data,int size,QImage & image)79 bool tiffToQImage( const char * data, int size, QImage & image )
80 {
81   QByteArray arr = QByteArray::fromRawData( data, size );
82   QBuffer buf;
83   buf.setData( arr );
84   buf.open( QIODevice::ReadOnly );
85 
86   TIFF *const tiff = TIFFClientOpen( "foo",
87                                      "r",
88                                      &buf,
89                                      tiffReadProc,
90                                      tiffWriteProc,
91                                      tiffSeekProc,
92                                      tiffCloseProc,
93                                      tiffSizeProc,
94                                      tiffMapProc,
95                                      tiffUnmapProc );
96   if( !tiff )
97     return false;
98 
99   uint32 width, height;
100   if( !TIFFGetField( tiff, TIFFTAG_IMAGEWIDTH, &width )
101       || !TIFFGetField( tiff, TIFFTAG_IMAGELENGTH, &height ) )
102   {
103     TIFFClose( tiff );
104     return false;
105   }
106 
107   uint16 bitPerSample;
108   if( !TIFFGetField( tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample ) )
109     bitPerSample = 1;
110 
111   uint16 samplesPerPixel; // they may be e.g. grayscale with 2 samples per pixel
112   if( !TIFFGetField( tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel ) )
113     samplesPerPixel = 1;
114 
115   if( bitPerSample == 1 && samplesPerPixel == 1 )
116   {
117     QImage tiffImage( width, height, QImage::Format_Mono );
118 
119     QVector<QRgb> colortable( 2 );
120     colortable[0] = 0xffffffff;
121     colortable[1] = 0xff000000;
122     tiffImage.setColorTable( colortable );
123 
124     for ( uint32 y = 0; y < height; ++y )
125     {
126       if( TIFFReadScanline( tiff, tiffImage.scanLine( y ), y, 0 ) < 0 )
127       {
128         TIFFClose( tiff );
129         return false;
130       }
131     }
132 
133     image = tiffImage;
134     TIFFClose( tiff );
135     return true;
136   }
137 
138   TIFFClose( tiff );
139   return false;
140 }
141 
142 } // namespace
143 
144 #endif
145