mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-25 01:14:07 +00:00
171 lines
3.9 KiB
C++
171 lines
3.9 KiB
C++
/* 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
|
|
|
|
|