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