/* This file is (c) 2014 Abs62
 * Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */

#ifdef MAKE_EXTRA_TIFF_HANDLER

#include "tiff.hh"

#if defined (Q_OS_MAC) || defined (Q_OS_WIN)
#include "tiff/tiff.h"
#include "tiff/tiffio.h"
#else
#include "tiff.h"
#include "tiffio.h"
#endif

#include <QBuffer>

namespace GdTiff
{

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;
}

} // namespace

#endif