A new backend: TIFF.

It uses directly the libTIFF, and actually can load TIFF documents even better than the fax generator (that uses libkfaximage).
The generator can also rotate the images, but it is not tested as the menus with the current kdelibs snapshot don't work.

svn path=/trunk/playground/graphics/okular/; revision=559514
This commit is contained in:
Pino Toscano 2006-07-07 14:58:12 +00:00
parent e40af42c63
commit b43f2c4d28
5 changed files with 379 additions and 0 deletions

View file

@ -15,6 +15,9 @@ if(DJVULIBRE_FOUND)
add_subdirectory(djvu)
endif(DJVULIBRE_FOUND)
add_subdirectory(dvi)
if(TIFF_FOUND)
add_subdirectory(tiff)
endif(TIFF_FOUND)
#original Makefile.am contents follow:

View file

@ -0,0 +1,27 @@
include_directories(
${CMAKE_SOURCE_DIR}/okular
${TIFF_INCLUDE_DIR}
)
########### next target ###############
set(okularGenerator_tiff_SRCS
generator_tiff.cpp
)
kde4_automoc(${okularGenerator_tiff_SRCS})
kde4_add_plugin(okularGenerator_tiff WITH_PREFIX ${okularGenerator_tiff_SRCS})
kde4_install_libtool_file( ${PLUGIN_INSTALL_DIR} okularGenerator_tiff )
target_link_libraries(okularGenerator_tiff ${KDE4_KDECORE_LIBS} okularcore ${TIFF_LIBRARIES} ${KDE4_KDEUI_LIBS} )
install(TARGETS okularGenerator_tiff DESTINATION ${PLUGIN_INSTALL_DIR})
########### install files ###############
install( FILES libokularGenerator_tiff.desktop DESTINATION ${SERVICES_INSTALL_DIR} )

View file

@ -0,0 +1,292 @@
/***************************************************************************
* Copyright (C) 2006 by Pino Toscano <toscano.pino@tiscali.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include <qfile.h>
#include <qimage.h>
#include <qlist.h>
#include <qpixmap.h>
#include <qthread.h>
#include <kimageeffect.h>
#include "core/page.h"
#include "generator_tiff.h"
#include <tiff.h>
#include <tiffio.h>
class TIFFGenerator::Private
{
public:
Private()
: tiff( 0 ) {}
TIFF* tiff;
};
class TIFFGeneratorThread : public QThread
{
public:
TIFFGeneratorThread();
void startGeneration( PixmapRequest* request, TIFF* tiff );
void endGeneration();
PixmapRequest *request() const;
QPixmap * takePixmap();
private:
void run();
PixmapRequest* m_request;
QPixmap* m_pix;
TIFF* m_tiff;
};
TIFFGeneratorThread::TIFFGeneratorThread()
: QThread(), m_request( 0 ), m_pix( 0 ), m_tiff( 0 )
{
}
void TIFFGeneratorThread::startGeneration( PixmapRequest* request, TIFF* tiff )
{
m_request = request;
m_tiff = tiff;
start( QThread::InheritPriority );
}
void TIFFGeneratorThread::endGeneration()
{
m_request = 0;
m_tiff = 0;
}
PixmapRequest* TIFFGeneratorThread::request() const
{
return m_request;
}
QPixmap* TIFFGeneratorThread::takePixmap()
{
QPixmap* p = m_pix;
m_pix = 0;
return p;
}
void TIFFGeneratorThread::run()
{
bool generated = false;
m_pix = new QPixmap( m_request->width, m_request->height );
if ( TIFFSetDirectory( m_tiff, m_request->page->number() ) )
{
int rotation = m_request->documentRotation;
uint32 width = (uint32)m_request->page->width();
uint32 height = (uint32)m_request->page->height();
if ( rotation % 2 == 1 )
qSwap( width, height );
QImage image( width, height, QImage::Format_RGB32 );
uint32 * data = (uint32 *)image.bits();
// read data
if ( TIFFReadRGBAImageOriented( m_tiff, width, height, data, ORIENTATION_TOPLEFT ) != 0 )
{
// an image read by ReadRGBAImage is ABGR, we need ARGB, so swap red and blue
uint32 size = width * height;
for ( uint32 i = 0; i < size; ++i )
{
uint32 red = ( data[i] & 0x00FF0000 ) >> 16;
uint32 blue = ( data[i] & 0x000000FF ) << 16;
data[i] = ( data[i] & 0xFF00FF00 ) + red + blue;
}
int reqwidth = m_request->width;
int reqheight = m_request->height;
if ( rotation % 2 == 1 )
qSwap( reqwidth, reqheight );
QImage smoothImage = image.scaled( reqwidth, reqheight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
QImage finalImage = rotation > 0
? KImageEffect::rotate( smoothImage, (KImageEffect::RotateDirection)( rotation - 1 ) )
: smoothImage;
*m_pix = QPixmap::fromImage( finalImage );
generated = true;
}
}
if ( !generated )
{
m_pix->fill();
}
}
OKULAR_EXPORT_PLUGIN(TIFFGenerator)
TIFFGenerator::TIFFGenerator( KPDFDocument * document ) : Generator( document ),
d( new Private ), ready( false )
{
thread = new TIFFGeneratorThread();
connect( thread, SIGNAL( finished() ), this, SLOT( slotThreadFinished() ), Qt::QueuedConnection );
}
TIFFGenerator::~TIFFGenerator()
{
if ( d->tiff )
{
TIFFClose( d->tiff );
d->tiff = 0;
}
if ( thread )
{
thread->wait();
}
delete thread;
delete d;
}
bool TIFFGenerator::loadDocument( const QString & fileName, QVector<KPDFPage*> & pagesVector )
{
// closing the old document
if ( d->tiff )
{
TIFFClose( d->tiff );
d->tiff = 0;
}
d->tiff = TIFFOpen( QFile::encodeName( fileName ), "r" );
if ( !d->tiff )
return false;
loadPages( pagesVector, 0 );
ready = true;
return true;
}
bool TIFFGenerator::canGeneratePixmap( bool /*async*/ )
{
return ready;
}
void TIFFGenerator::generatePixmap( PixmapRequest * request )
{
ready = false;
if ( request->async )
{
thread->startGeneration( request, d->tiff );
return;
}
bool generated = false;
QPixmap * p = new QPixmap( request->width, request->height );
if ( TIFFSetDirectory( d->tiff, request->page->number() ) )
{
int rotation = request->documentRotation;
uint32 width = (uint32)request->page->width();
uint32 height = (uint32)request->page->height();
if ( rotation % 2 == 1 )
qSwap( width, height );
QImage image( width, height, QImage::Format_RGB32 );
uint32 * data = (uint32 *)image.bits();
// read data
if ( TIFFReadRGBAImageOriented( d->tiff, width, height, data, ORIENTATION_TOPLEFT ) != 0 )
{
// an image read by ReadRGBAImage is ABGR, we need ARGB, so swap red and blue
uint32 size = width * height;
for ( uint32 i = 0; i < size; ++i )
{
uint32 red = ( data[i] & 0x00FF0000 ) >> 16;
uint32 blue = ( data[i] & 0x000000FF ) << 16;
data[i] = ( data[i] & 0xFF00FF00 ) + red + blue;
}
int reqwidth = request->width;
int reqheight = request->height;
if ( rotation % 2 == 1 )
qSwap( reqwidth, reqheight );
QImage smoothImage = image.scaled( reqwidth, reqheight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
QImage finalImage = rotation > 0
? KImageEffect::rotate( smoothImage, (KImageEffect::RotateDirection)( rotation - 1 ) )
: smoothImage;
*p = QPixmap::fromImage( finalImage );
generated = true;
}
}
if ( !generated )
{
p->fill();
}
request->page->setPixmap( request->id, p );
ready = true;
// signal that the request has been accomplished
signalRequestDone( request );
}
void TIFFGenerator::setOrientation( QVector<KPDFPage*> & pagesVector, int orientation )
{
loadPages( pagesVector, orientation );
}
void TIFFGenerator::slotThreadFinished()
{
PixmapRequest * request = thread->request();
thread->endGeneration();
request->page->setPixmap( request->id, thread->takePixmap() );
ready = true;
signalRequestDone( request );
}
void TIFFGenerator::loadPages( QVector<KPDFPage*> & pagesVector, int rotation )
{
if ( !d->tiff )
return;
tdir_t dirs = TIFFNumberOfDirectories( d->tiff );
pagesVector.resize( dirs );
uint32 width = 0;
uint32 height = 0;
for ( tdir_t i = 0; i < dirs; ++i )
{
if ( !TIFFSetDirectory( d->tiff, i ) )
continue;
if ( TIFFGetField( d->tiff, TIFFTAG_IMAGEWIDTH, &width ) != 1 ||
TIFFGetField( d->tiff, TIFFTAG_IMAGELENGTH, &height ) != 1 )
continue;
if ( rotation % 2 == 1 )
qSwap( width, height );
delete pagesVector[i];
KPDFPage * page = new KPDFPage( i, width, height, rotation );
pagesVector[i] = page;
}
}
#include "generator_tiff.moc"

View file

@ -0,0 +1,46 @@
/***************************************************************************
* Copyright (C) 2006 by Pino Toscano <toscano.pino@tiscali.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#ifndef _OKULAR_GENERATOR_TIFF_H_
#define _OKULAR_GENERATOR_TIFF_H_
#include "core/generator.h"
class TIFFGeneratorThread;
class TIFFGenerator : public Generator
{
Q_OBJECT
public:
TIFFGenerator( KPDFDocument * document );
virtual ~TIFFGenerator();
bool loadDocument( const QString & fileName, QVector<KPDFPage*> & pagesVector );
bool canGeneratePixmap( bool async );
void generatePixmap( PixmapRequest * request );
bool supportsRotation() { return true; };
void setOrientation( QVector<KPDFPage*> & pagesVector, int orientation );
private slots:
void slotThreadFinished();
private:
class Private;
Private * const d;
TIFFGeneratorThread* thread;
void loadPages( QVector<KPDFPage*> & pagesVector, int rotation );
bool ready;
};
#endif

View file

@ -0,0 +1,11 @@
[Desktop Entry]
Encoding=UTF-8
Type=Service
Name=okular TIFF Library
Comment=TIFF backend for okular
ServiceTypes=okular/Generator
MimeType=image/tiff;
X-KDE-Library=libokularGenerator_tiff
X-KDE-Priority=4
X-KDE-okularAPIVersion=1
X-KDE-okularHasInternalSettings=false