You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegraphics/kooka/kookaimage.cpp

414 lines
10 KiB

/***************************************************************************
kookaimage.cpp - Kooka's Image
-------------------
begin : Thu Nov 20 2001
copyright : (C) 1999 by Klaas Freitag
email : freitag@suse.de
***************************************************************************/
/***************************************************************************
* *
* This file may be distributed and/or modified under the terms of the *
* GNU General Public License version 2 as published by the Free Software *
* Foundation and appearing in the file COPYING included in the *
* packaging of this file. *
*
* As a special exception, permission is given to link this program *
* with any version of the KADMOS ocr/icr engine of reRecognition GmbH, *
* Kreuzlingen and distribute the resulting executable without *
* including the source code for KADMOS in the source distribution. *
*
* As a special exception, permission is given to link this program *
* with any edition of Qt, and distribute the resulting executable, *
* without including the source code for Qt in the source distribution. *
* *
***************************************************************************/
#include <kdebug.h>
#include <kurl.h>
#include <kfileitem.h>
#include "kookaimage.h"
#include "config.h"
#ifdef HAVE_LIBTIFF
#include <tiffio.h>
#include <tiff.h>
#endif
/**
*@author Klaas Freitag
*/
KookaImage::KookaImage( )
: TQImage(),
m_subImages(-1),
m_subNo(0),
m_parent(0),
m_fileBound(false),
m_tileCols(0)
{
}
/* constructor for subimages */
KookaImage::KookaImage( int subNo, KookaImage *p )
: TQImage(),
m_subImages(-1),
m_subNo(subNo),
m_parent( p ),
m_fileItem(0L),
m_fileBound(false),
m_tileCols(0)
{
kdDebug(28000) << "Setting subimageNo to " << subNo << endl;
}
KookaImage& KookaImage::operator=(const KookaImage& img)
{
TQImage::operator=(img);
m_subImages = img.subImagesCount();
m_subNo = img.m_subNo;
m_parent = img.m_parent;
m_url = img.m_url;
m_fileItem = img.m_fileItem;
return *this;
}
KookaImage& KookaImage::operator=(const TQImage& img)
{
TQImage::operator=(img);
return *this;
}
KFileItem* KookaImage::fileItem() const
{
return m_fileItem;
}
void KookaImage::setFileItem( KFileItem* it )
{
m_fileItem = it;
}
const KFileMetaInfo KookaImage::fileMetaInfo( )
{
TQString filename = localFileName( );
if( ! filename.isEmpty() )
{
kdDebug(28000) << "Fetching metainfo for " << filename << endl;
const KFileMetaInfo info( filename );
return info;
}
else
return KFileMetaInfo();
}
TQString KookaImage::localFileName( ) const
{
if( ! m_url.isEmpty() )
return( m_url.directory() + "/" + m_url.fileName());
else
return TQString();
}
bool KookaImage::loadFromUrl( const KURL& url )
{
bool ret = true;
m_url = url;
TQString filename = localFileName( );
TQString format ( imageFormat( filename ));
/* if the format was not recogniseable, check the extension, if it is tif, try to read it by
* tifflib */
if( format.isNull() )
{
if( filename.endsWith( "tif" ) || filename.endsWith( "tiff" ) ||
filename.endsWith( "TIF" ) || filename.endsWith( "TIFF" ) )
{
format = "tif";
kdDebug(28000) << "Setting format to tif by extension" << endl;
}
}
kdDebug(28000) << "Image format to load: <" << format << "> from file <" << filename << ">" << endl;
bool haveTiff = false;
if( !m_url.isLocalFile() )
{
kdDebug(28000)<<"ERROR: Can not laod non-local images -> not yet implemented!" << endl;
return false;
}
#ifdef HAVE_LIBTIFF
TIFF* tif = 0;
m_subImages = 0;
if( format == "tif" ||
format == "TIF" ||
format == "TIFF" ||
format == "tiff" )
{
/* if it is tiff, check with Tifflib if it is multiple sided */
kdDebug(28000) << "Trying to load TIFF!" << endl;
tif = TIFFOpen(filename.latin1(), "r");
if (tif)
{
do {
m_subImages++;
} while (TIFFReadDirectory(tif));
kdDebug(28000) << m_subImages << " TIFF-directories found" << endl;
haveTiff = true;
}
}
#endif
if( !haveTiff )
{
/* Qt can only read one image */
ret = load(filename);
if( ret )
{
m_subImages = 0;
m_subNo = 0;
}
}
#ifdef HAVE_LIBTIFF
else
{
loadTiffDir( filename, 0);
/* its a tiff, read by tifflib directly */
// Find the width and height of the image
}
#endif
m_fileBound = ret;
return( ret );
}
KookaImage::KookaImage( const TQImage& img )
: TQImage( img )
/* m_subImages( 1 ) */
{
m_subImages = 0;
/* Load one TQImage, can not be Tiff yet. */
kdDebug(28000) << "constructor from other image here " << endl;
}
/* loads the number stored in m_subNo */
void KookaImage::extractNow()
{
kdDebug(28000) << "extracting a subimage number " << m_subNo << endl;
KookaImage *parent = parentImage();
if( parent )
{
loadTiffDir( parent->localFileName(), m_subNo );
}
else
{
kdDebug(28000) << "ERR: No parent defined - can not laod subimage" << endl;
}
}
KURL KookaImage::url() const
{
return m_url;
}
bool KookaImage::loadTiffDir( const TQString& filename, int no )
{
#ifdef HAVE_LIBTIFF
int imgWidth, imgHeight;
TIFF* tif = 0;
/* if it is tiff, check with Tifflib if it is multiple sided */
kdDebug(28000) << "Trying to load TIFF, subimage number "<< no << endl;
tif = TIFFOpen(filename.latin1(), "r");
if (!tif)
return false;
if( ! TIFFSetDirectory( tif, no ) )
{
kdDebug(28000) << "ERR: could not set Directory " << no << endl;
TIFFClose(tif);
return false;
}
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imgWidth);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imgHeight);
/* TODO: load bw-image correctly only 2 bit */
// KookaImage tmpImg;
create( imgWidth, imgHeight, 32 );
if (TIFFReadRGBAImage(tif, imgWidth, imgHeight, (uint32*) bits(),0))
{
// successfully read. now convert.
// reverse red and blue
uint32 *data;
data = (uint32 *)bits();
for( unsigned i = 0; i < unsigned(imgWidth * imgHeight); ++i )
{
uint32 red = ( 0x00FF0000 & data[i] ) >> 16;
uint32 blue = ( 0x000000FF & data[i] ) << 16;
data[i] &= 0xFF00FF00;
data[i] += red + blue;
}
// reverse image (it's upside down)
unsigned h = unsigned(imgHeight);
for( unsigned ctr = 0; ctr < h>>1; )
{
unsigned *line1 = (unsigned *)scanLine( ctr );
unsigned *line2 = (unsigned *)scanLine( imgHeight
- ( ++ctr ) );
unsigned w = unsigned(imgWidth);
for( unsigned x = 0; x < w; x++ )
{
int temp = *line1;
*line1 = *line2;
*line2 = temp;
line1++;
line2++;
}
}
}
/* fetch the x- and y-resolutions to adjust images */
float xReso, yReso;
bool resosFound;
resosFound = TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xReso );
resosFound &= TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yReso );
kdDebug(28000)<< "Tiff image: X-Resol.: " << xReso << " and Y-Resol.: " << yReso << endl;
TIFFClose(tif);
/* Check now if resolution in x- and y-direction differ. If so, stretch the image
* accordingly.
*/
if( resosFound && xReso != yReso )
{
if( xReso > yReso )
{
float yScalefactor = xReso / yReso;
kdDebug(28000) << "Different resolution x/y, rescaling with factor " << yScalefactor << endl;
/* rescale the image */
*this = smoothScale( imgWidth, int(imgHeight*yScalefactor), TQImage::ScaleFree );
}
else
{
/* yReso > xReso */
float scalefactor = yReso / xReso;
kdDebug(28000) << "Different resolution x/y, rescaling x with factor " << scalefactor << endl;
/* rescale the image */
*this = smoothScale( int(imgWidth*scalefactor), imgHeight, TQImage::ScaleFree );
}
}
#endif
return true;
}
int KookaImage::subImagesCount() const
{
return( m_subImages );
}
KookaImage::~KookaImage()
{
}
KookaImage* KookaImage::parentImage() const
{
return( m_parent );
}
bool KookaImage::isSubImage() const
{
return( subImagesCount() );
}
/*
* tiling
*/
int KookaImage::cutToTiles( const TQSize maxSize, int& rows, int& cols, TileMode )
{
TQSize imgSize = size();
int w = imgSize.width();
if( w > maxSize.width() )
{
// image is wider than paper
w = maxSize.width();
}
int h = imgSize.height();
if( h > maxSize.height() )
{
// image is wider than paper
h = maxSize.height();
}
int absX = 0; // absolute x position from where to start print
int absY = 0; // on the image, left top corner of the part to print
rows = 0;
while( h ) // Loop over height, cut in vertical direction
{
rows++;
cols = 0;
while( w ) // Loop over width, cut in horizontal direction
{
cols++;
m_tileVector.append( TQRect( absX, absY, w, h ));
absX += w+1;
w = imgSize.width() - absX;
// if w < 0, this was the last loop, set w to zero to stop loop
if( w < 0 ) w = 0;
// if > 0 here, a new page is required
if( w > 0 )
{
if( w > maxSize.width() ) w = maxSize.width();
}
}
// Reset the X-values to start on the left border again
absX = 0;
// start with full width again
w = imgSize.width();
if( w > maxSize.width() )
w = maxSize.width();
absY += h+1;
h = imgSize.height() - absY;
if( h < 0 ) h = 0; // be sure to meet the break condition
if( h > maxSize.height()) h = maxSize.height(); // limit to page height
}
m_tileCols = cols;
return m_tileVector.count();
}
TQRect KookaImage::getTileRect( int rowPos, int colPos ) const
{
int indx = rowPos*m_tileCols+colPos;
kdDebug(28000) << "Tile Index: " << indx << endl;
const TQRect r = m_tileVector[(rowPos)*m_tileCols + colPos];
return r;
}