/***************************************************************************
                          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 <tiffio.h>
#include <tiff.h>
#include "config.h"
/**
  *@author Klaas Freitag
  */


KookaImage::KookaImage( )
   : QImage(),
     m_subImages(-1),
     m_subNo(0),
     m_parent(0),
     m_fileBound(false),
     m_tileCols(0)
{

}

/* constructor for subimages */
KookaImage::KookaImage( int subNo, KookaImage *p )
   : QImage(),
     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)
{
    QImage::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 QImage& img)
{
    QImage::operator=(img);
    return *this;
}

KFileItem* KookaImage::fileItem() const
{
    return m_fileItem;
}

void KookaImage::setFileItem( KFileItem* it )
{
    m_fileItem = it;
}

const KFileMetaInfo KookaImage::fileMetaInfo( )
{
    QString filename = localFileName( );
    if( ! filename.isEmpty() )
    {
        kdDebug(28000) << "Fetching metainfo for " << filename << endl;
        const KFileMetaInfo info( filename );
        return info;
    }
    else
        return KFileMetaInfo();
}

QString KookaImage::localFileName( ) const
{

    if( ! m_url.isEmpty() )
        return( m_url.directory() + "/" + m_url.fileName());
    else
        return QString();
}

bool KookaImage::loadFromUrl( const KURL& url )
{
   bool ret = true;
   m_url = url;
   QString filename = localFileName( );
   QString 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 QImage& img )
   : QImage( img )
   /* m_subImages( 1 ) */
{
   m_subImages = 0;

   /* Load one QImage, 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 QString& 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), QImage::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, QImage::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 QSize maxSize, int& rows, int& cols, TileMode  )
{
    QSize 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( QRect( 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();
}



QRect KookaImage::getTileRect( int rowPos, int colPos ) const
{
    int indx = rowPos*m_tileCols+colPos;
    kdDebug(28000) << "Tile Index: " << indx << endl;
    const QRect r = m_tileVector[(rowPos)*m_tileCols + colPos];

    return r;
}
