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