LCOV - code coverage report
Current view: top level - filter/source/graphicfilter/itiff - itiff.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 431 698 61.7 %
Date: 2015-06-13 12:38:46 Functions: 14 17 82.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <sal/config.h>
      21             : 
      22             : #include <vcl/FilterConfigItem.hxx>
      23             : #include <vcl/graph.hxx>
      24             : #include <vcl/bmpacc.hxx>
      25             : #include <vcl/animate.hxx>
      26             : #include <tools/fract.hxx>
      27             : #include "lzwdecom.hxx"
      28             : #include "ccidecom.hxx"
      29             : 
      30             : namespace {
      31             : 
      32           0 : template< typename T > T BYTESWAP(T nByte) {
      33             :     return ( nByte << 7 ) | ( ( nByte & 2 ) << 5 ) | ( ( nByte & 4 ) << 3 ) |
      34             :         ( ( nByte & 8 ) << 1 ) | ( ( nByte & 16 ) >> 1 ) |
      35             :         ( ( nByte & 32 ) >> 3 ) | ( ( nByte & 64 ) >> 5 ) |
      36           0 :         ( ( nByte & 128 ) >> 7 );
      37             : }
      38             : 
      39             : }
      40             : 
      41             : //============================ TIFFReader ==================================
      42             : 
      43             : class TIFFReader
      44             : {
      45             : 
      46             : private:
      47             : 
      48             :     bool                bStatus;                    // Whether until now no error occurred
      49             :     Animation               aAnimation;
      50             :     sal_uLong               nLastPercent;
      51             : 
      52             :     SvStream*               pTIFF;                      // the TIFF file that should be read
      53             :     Bitmap                  aBitmap;
      54             :     BitmapWriteAccess*      pAcc;
      55             :     sal_uInt16              nDstBitsPerPixel;
      56             :     AlphaMask*              pAlphaMask;
      57             :     BitmapWriteAccess*      pMaskAcc;
      58             : 
      59             :     sal_uLong               nOrigPos;                   // start position in pTIFF
      60             : 
      61             : 
      62             :     sal_uInt16              nDataType;
      63             :     // Data taken from the TIFF tags:
      64             :     bool                bByteSwap;                  // sal_True if bits 0..7 -> 7..0 should get converted ( FILLORDER = 2 );
      65             : 
      66             :     sal_uLong               nNewSubFile;
      67             :     sal_uLong               nSubFile;
      68             :     sal_uLong               nImageWidth;                // picture width in pixels
      69             :     sal_uLong               nImageLength;               // picture height in pixels
      70             :     sal_uLong               nBitsPerSample;             // bits per pixel per layer
      71             :     sal_uLong               nCompression;               // kind of compression
      72             :     sal_uLong               nPhotometricInterpretation;
      73             :     sal_uLong               nThresholding;
      74             :     sal_uLong               nCellWidth;
      75             :     sal_uLong               nCellLength;
      76             :     sal_uLong               nFillOrder;
      77             :     sal_uLong*              pStripOffsets;              // field of offsets to the Bitmap-Data-"Strips"
      78             :     sal_uLong               nNumStripOffsets;           // size of the field above
      79             :     sal_uLong               nOrientation;
      80             :     sal_uLong               nSamplesPerPixel;           // number of layers
      81             :     sal_uLong               nRowsPerStrip;              // if it's not compressed: number of rows per Strip
      82             :     sal_uLong*              pStripByteCounts;           // if compressed (in a certain way): size of the strips
      83             :     sal_uLong               nNumStripByteCounts;        // number of entries in the field above
      84             :     sal_uLong               nMinSampleValue;
      85             :     sal_uLong               nMaxSampleValue;
      86             :     double                  fXResolution;               // X-resolution or 0.0
      87             :     double                  fYResolution;               // Y-resolution or 0.0
      88             :     sal_uLong               nPlanarConfiguration;
      89             :     sal_uLong               nGroup3Options;
      90             :     sal_uLong               nGroup4Options;
      91             :     sal_uLong               nResolutionUnit;            // unit of fX/YResolution: 1=unknown, 2(default)=inch, 3=cm
      92             :     sal_uLong               nPredictor;
      93             :     sal_uLong*              pColorMap;                  // color palette
      94             :     sal_uLong               nNumColors;                 // number of colors within the color palette
      95             : 
      96             :     sal_uLong               nPlanes;                    // number of layers within the Tiff file
      97             :     sal_uLong               nStripsPerPlane;            // number of Strips per layer
      98             :     sal_uLong               nBytesPerRow;               // Bytes per line per Layer in the Tiff file ( uncompressed )
      99             :     sal_uInt8*              pMap[ 4 ];                  // temporary Scanline
     100             : 
     101             : 
     102             :     sal_uLong   DataTypeSize();
     103             :     sal_uLong   ReadIntData();
     104             :     double  ReadDoubleData();
     105             : 
     106             :     void    ReadHeader();
     107             :     void    ReadTagData( sal_uInt16 nTagType, sal_uInt32 nDataLen );
     108             : 
     109             :     bool    ReadMap();
     110             :         // reads/decompresses the bitmap data and fills pMap
     111             : 
     112             :     sal_uLong   GetBits( const sal_uInt8 * pSrc, sal_uLong nBitsPos, sal_uLong nBitsCount );
     113             :         // fetches BitsCount bits from pSrc[..] at the position nBitsPos
     114             : 
     115             :     void    MakePalCol();
     116             :         // Create the bitmap from the temporary bitmap pMap
     117             :         // and partly deletes pMap while doing this.
     118             : 
     119             :     bool    ConvertScanline( sal_uLong nY );
     120             :         // converts a Scanline to the Windows-BMP format
     121             : 
     122             :     bool HasAlphaChannel() const;
     123             : public:
     124             : 
     125          17 :     TIFFReader()
     126             :         : bStatus(false)
     127             :         , nLastPercent(0)
     128             :         , pTIFF(NULL)
     129             :         , pAcc(NULL)
     130             :         , nDstBitsPerPixel(0)
     131             :         , pAlphaMask(NULL)
     132             :         , pMaskAcc(NULL)
     133             :         , nOrigPos(0)
     134             :         , nDataType(0)
     135             :         , bByteSwap(false)
     136             :         , nNewSubFile(0)
     137             :         , nSubFile(0)
     138             :         , nImageWidth(0)
     139             :         , nImageLength(0)
     140             :         , nBitsPerSample(1)
     141             :         , nCompression(1)
     142             :         , nPhotometricInterpretation(0)
     143             :         , nThresholding(1)
     144             :         , nCellWidth(1)
     145             :         , nCellLength(1)
     146             :         , nFillOrder(1)
     147             :         , pStripOffsets(NULL)
     148             :         , nNumStripOffsets(0)
     149             :         , nOrientation(1)
     150             :         , nSamplesPerPixel(1)
     151             :         , nRowsPerStrip(0xffffffff)
     152             :         , pStripByteCounts(NULL)
     153             :         , nNumStripByteCounts(0)
     154             :         , nMinSampleValue(0)
     155             :         , nMaxSampleValue(0)
     156             :         , fXResolution(0.0)
     157             :         , fYResolution(0.0)
     158             :         , nPlanarConfiguration(1)
     159             :         , nGroup3Options(0)
     160             :         , nGroup4Options(0)
     161             :         , nResolutionUnit(2)
     162             :         , nPredictor(0)
     163             :         , pColorMap(NULL)
     164             :         , nNumColors(0)
     165             :         , nPlanes(0)
     166             :         , nStripsPerPlane(0)
     167          17 :         , nBytesPerRow(0)
     168             :     {
     169          17 :         pMap[ 0 ] = pMap[ 1 ] = pMap[ 2 ] = pMap[ 3 ] = NULL;
     170          17 :     }
     171             : 
     172          17 :     ~TIFFReader()
     173          17 :     {
     174          17 :         delete pAlphaMask;
     175          17 :     }
     176             : 
     177        7242 :     sal_uLong GetRowsPerStrip() const
     178             :     {
     179             :         //Rows Per Strip:
     180             :         //
     181             :         //(TIFF format only) The number of rows of pixels per strip to use for
     182             :         //encoding the TIFF image. A value greater than zero specifies the
     183             :         //number of rows per strip. A value of 0 sets the rows per strip equal
     184             :         //to the image length, resulting in a single strip. A value of -1 (the
     185             :         //default) sets the rows per strip equal to infinity, resulting in a
     186             :         //single strip.
     187        7242 :         return nRowsPerStrip == 0 ? nImageLength : nRowsPerStrip;
     188             :     }
     189             : 
     190             :     bool ReadTIFF( SvStream & rTIFF, Graphic & rGraphic );
     191             : };
     192             : 
     193             : //=================== Methods of TIFFReader ==============================
     194             : 
     195         566 : sal_uLong TIFFReader::DataTypeSize()
     196             : {
     197             :     sal_uLong nSize;
     198         566 :     switch ( nDataType )
     199             :     {
     200             :         case 1 :            // BYTE
     201             :         case 2 :            // ASCII
     202             :         case 6 :            // SIGNED Byte
     203             :         case 7 :            // UNDEFINED
     204           9 :             nSize = 1;
     205           9 :             break;
     206             :         case 3 :            // UINT16
     207             :         case 8 :            // INT16
     208         291 :             nSize = 2;
     209         291 :             break;
     210             :         case 4 :            // UINT32
     211             :         case 9 :            // INT32
     212             :         case 11 :           // FLOAT
     213         130 :             nSize = 4;
     214         130 :             break;
     215             :         case 5 :            // RATIONAL
     216             :         case 10 :           // SIGNED RATIONAL
     217             :         case 12 :           // DOUBLE
     218          90 :             nSize = 8;
     219          90 :             break;
     220             :         default:
     221          46 :             pTIFF->SetError(SVSTREAM_FILEFORMAT_ERROR);
     222          46 :             nSize=1;
     223             :     }
     224         566 :     return nSize;
     225             : }
     226             : 
     227        1387 : sal_uLong TIFFReader::ReadIntData()
     228             : {
     229        1387 :     double  nDOUBLE(0.0);
     230        1387 :     float   nFLOAT(0);
     231        1387 :     sal_uInt32  nUINT32a(0), nUINT32b(0);
     232        1387 :     sal_Int32   nINT32(0);
     233        1387 :     sal_uInt16  nUINT16(0);
     234        1387 :     sal_Int16   nINT16(0);
     235        1387 :     sal_uInt8   nBYTE(0);
     236        1387 :     char    nCHAR(0);
     237             : 
     238        1387 :     switch( nDataType )
     239             :     {
     240             :         case 0 :    //??
     241             :         case 1 :
     242             :         case 2 :
     243             :         case 7 :
     244           0 :             pTIFF->ReadUChar( nBYTE );
     245           0 :             nUINT32a = (sal_uLong)nBYTE;
     246           0 :         break;
     247             :         case 3 :
     248         133 :              pTIFF->ReadUInt16( nUINT16 );
     249         133 :              nUINT32a = (sal_uLong)nUINT16;
     250         133 :         break;
     251             :         case 9 :
     252             :         case 4 :
     253        1253 :             pTIFF->ReadUInt32( nUINT32a );
     254        1253 :         break;
     255             :         case  5 :
     256           0 :             pTIFF->ReadUInt32( nUINT32a ).ReadUInt32( nUINT32b );
     257           0 :             if ( nUINT32b != 0 )
     258           0 :                 nUINT32a /= nUINT32b;
     259           0 :         break;
     260             :         case 6 :
     261           0 :             pTIFF->ReadChar( nCHAR );
     262           0 :             nUINT32a = (sal_Int32)nCHAR;
     263           0 :         break;
     264             :         case 8 :
     265           0 :             pTIFF->ReadInt16( nINT16 );
     266           0 :             nUINT32a = (sal_Int32)nINT16;
     267           0 :         break;
     268             :         case 10 :
     269           0 :             pTIFF->ReadUInt32( nUINT32a ).ReadInt32( nINT32 );
     270           0 :             if ( nINT32 != 0 )
     271           0 :                 nUINT32a /= nINT32;
     272           0 :         break;
     273             :         case 11 :
     274           0 :             pTIFF->ReadFloat( nFLOAT );
     275           0 :             nUINT32a = (sal_Int32)nFLOAT;
     276           0 :         break;
     277             :         case 12 :
     278           0 :             pTIFF->ReadDouble( nDOUBLE );
     279           0 :             nUINT32a = (sal_Int32)nDOUBLE;
     280           0 :         break;
     281             :         default:
     282           1 :             pTIFF->ReadUInt32( nUINT32a );
     283           1 :         break;
     284             :     }
     285        1387 :     return nUINT32a;
     286             : }
     287             : 
     288          24 : double TIFFReader::ReadDoubleData()
     289             : {
     290             :     double  nd;
     291             : 
     292          24 :     if ( nDataType == 5 )
     293             :     {
     294          24 :         sal_uInt32 nulong(0);
     295          24 :         pTIFF->ReadUInt32( nulong );
     296          24 :         nd = (double)nulong;
     297          24 :         nulong = 0;
     298          24 :         pTIFF->ReadUInt32( nulong );
     299          24 :         if ( nulong != 0 )
     300          24 :             nd /= (double)nulong;
     301             :     }
     302             :     else
     303           0 :         nd = (double)ReadIntData();
     304          24 :     return nd;
     305             : }
     306             : 
     307         225 : void TIFFReader::ReadTagData( sal_uInt16 nTagType, sal_uInt32 nDataLen)
     308             : {
     309         225 :     if ( !bStatus )
     310         225 :         return;
     311             : 
     312         225 :     switch ( nTagType )
     313             :     {
     314             :         case 0x00fe:   // New Sub File
     315           8 :             nNewSubFile = ReadIntData();
     316             :             SAL_INFO("filter.tiff","NewSubFile: " << nNewSubFile);
     317           8 :             break;
     318             : 
     319             :         case 0x00ff:   // Sub File
     320           0 :             nSubFile = ReadIntData();
     321             :             SAL_INFO("filter.tiff","SubFile: " << nSubFile);
     322           0 :             break;
     323             : 
     324             :         case 0x0100:   // Image Width
     325          16 :             nImageWidth = ReadIntData();
     326             :             SAL_INFO("filter.tiff","ImageWidth: " << nImageWidth);
     327          16 :             break;
     328             : 
     329             :         case 0x0101:   // Image Length
     330          16 :             nImageLength = ReadIntData();
     331             :             SAL_INFO("filter.tiff","ImageLength: " << nImageLength);
     332          16 :             break;
     333             : 
     334             :         case 0x0102:   // Bits Per Sample
     335          15 :             nBitsPerSample = ReadIntData();
     336             :             SAL_INFO("filter.tiff","BitsPerSample: " << nBitsPerSample);
     337          15 :             if ( nBitsPerSample >= 32 ) // 32 bit and larger samples are not supported
     338           0 :                 bStatus = false;
     339          15 :             break;
     340             : 
     341             :         case 0x0103:   // Compression
     342          16 :             nCompression = ReadIntData();
     343             :             SAL_INFO("filter.tiff","Compression: " << nCompression);
     344          16 :             break;
     345             : 
     346             :         case 0x0106:   // Photometric Interpreation
     347          15 :             nPhotometricInterpretation = ReadIntData();
     348             :             SAL_INFO("filter.tiff","PhotometricInterpretation: " << nPhotometricInterpretation);
     349          15 :             break;
     350             : 
     351             :         case 0x0107:   // Thresholding
     352           0 :             nThresholding = ReadIntData();
     353             :             SAL_INFO("filter.tiff","Thresholding: " << nThresholding);
     354           0 :             break;
     355             : 
     356             :         case 0x0108:   // Cell Width
     357           0 :             nCellWidth = ReadIntData();
     358           0 :             break;
     359             : 
     360             :         case 0x0109:   // Cell Length
     361           0 :             nCellLength = ReadIntData();
     362           0 :             break;
     363             : 
     364             :         case 0x010a:   // Fill Order
     365           1 :             nFillOrder = ReadIntData();
     366             :             SAL_INFO("filter.tiff","FillOrder: " << nFillOrder);
     367           1 :             break;
     368             : 
     369             :         case 0x0111: { // Strip Offset(s)
     370             :             sal_uLong nOldNumSO, i, * pOldSO;
     371          15 :             pOldSO = pStripOffsets;
     372          15 :             if ( pOldSO == NULL )
     373          15 :                 nNumStripOffsets = 0;
     374          15 :             nOldNumSO = nNumStripOffsets;
     375          15 :             nDataLen += nOldNumSO;
     376          15 :             if ( ( nDataLen > nOldNumSO ) && ( nDataLen < SAL_MAX_UINT32 / sizeof( sal_uInt32 ) ) )
     377             :             {
     378          15 :                 nNumStripOffsets = nDataLen;
     379             :                 try
     380             :                 {
     381          15 :                     pStripOffsets = new sal_uLong[ nNumStripOffsets ];
     382             :                 }
     383           0 :                     catch (const std::bad_alloc &)
     384             :                 {
     385           0 :                     pStripOffsets = NULL;
     386           0 :                     nNumStripOffsets = 0;
     387             :                 }
     388          15 :                 if ( pStripOffsets )
     389             :                 {
     390          15 :                     for ( i = 0; i < nOldNumSO; i++ )
     391           0 :                         pStripOffsets[ i ] = pOldSO[ i ] + nOrigPos;
     392         631 :                     for ( i = nOldNumSO; i < nNumStripOffsets; i++ )
     393         616 :                         pStripOffsets[ i ] = ReadIntData() + nOrigPos;
     394             :                 }
     395          15 :                 delete[] pOldSO;
     396             :             }
     397             :             SAL_INFO("filter.tiff","StripOffsets (Number:) " << nDataLen);
     398          15 :             break;
     399             :         }
     400             :         case 0x0112:   // Orientation
     401           6 :             nOrientation = ReadIntData();
     402             :             SAL_INFO("filter.tiff","Orientation: " << nOrientation);
     403           6 :             break;
     404             : 
     405             :         case 0x0115:   // Samples Per Pixel
     406          14 :             nSamplesPerPixel = ReadIntData();
     407             :             SAL_INFO("filter.tiff","SamplesPerPixel: " << nSamplesPerPixel);
     408          14 :             break;
     409             : 
     410             :         case 0x0116:   // Rows Per Strip
     411          14 :             nRowsPerStrip = ReadIntData();
     412             :             SAL_INFO("filter.tiff","RowsPerStrip: " << nRowsPerStrip);
     413          14 :             break;
     414             : 
     415             :         case 0x0117: { // Strip Byte Counts
     416             :             sal_uLong nOldNumSBC, i, * pOldSBC;
     417          15 :             pOldSBC = pStripByteCounts;
     418          15 :             if ( pOldSBC == NULL )
     419          15 :                 nNumStripByteCounts = 0; // to be on the safe side
     420          15 :             nOldNumSBC = nNumStripByteCounts;
     421          15 :             nDataLen += nOldNumSBC;
     422          15 :             if ( ( nDataLen > nOldNumSBC ) && ( nDataLen < SAL_MAX_UINT32 / sizeof( sal_uInt32 ) ) )
     423             :             {
     424          15 :                 nNumStripByteCounts = nDataLen;
     425             :                 try
     426             :                 {
     427          15 :                     pStripByteCounts = new sal_uLong[ nNumStripByteCounts ];
     428             :                 }
     429           0 :                     catch (const std::bad_alloc &)
     430             :                 {
     431           0 :                     pStripByteCounts = NULL;
     432           0 :                     nNumStripByteCounts = 0;
     433             :                 }
     434          15 :                 if ( pStripByteCounts )
     435             :                 {
     436          15 :                     for ( i = 0; i < nOldNumSBC; i++ )
     437           0 :                         pStripByteCounts[ i ] = pOldSBC[ i ];
     438         631 :                     for ( i = nOldNumSBC; i < nNumStripByteCounts; i++)
     439         616 :                         pStripByteCounts[ i ] = ReadIntData();
     440             :                 }
     441          15 :                 delete[] pOldSBC;
     442             :             }
     443             :             SAL_INFO("filter.tiff","StripByteCounts (Number:) " << nDataLen);
     444          15 :             break;
     445             :         }
     446             :         case 0x0118:   // Min Sample Value
     447           0 :             nMinSampleValue = ReadIntData();
     448             :             SAL_INFO("filter.tiff","MinSampleValue: " << nMinSampleValue);
     449           0 :             break;
     450             : 
     451             :         case 0x0119:   // Max Sample Value
     452           0 :             nMaxSampleValue = ReadIntData();
     453             :             SAL_INFO("filter.tiff","MaxSampleValue: " << nMaxSampleValue);
     454           0 :             break;
     455             : 
     456             :         case 0x011a:   // X Resolution
     457          12 :             fXResolution = ReadDoubleData();
     458          12 :             break;
     459             : 
     460             :         case 0x011b:   // Y Resolution
     461          12 :             fYResolution = ReadDoubleData();
     462          12 :             break;
     463             : 
     464             :         case 0x011c:   // Planar Configuration
     465          15 :             nPlanarConfiguration = ReadIntData();
     466             :             SAL_INFO("filter.tiff","PlanarConfiguration: " << nPlanarConfiguration);
     467          15 :             break;
     468             : 
     469             :         case 0x0124:   // Group 3 Options
     470           0 :             nGroup3Options = ReadIntData();
     471             :             SAL_INFO("filter.tiff","Group3Options: " << nGroup3Options);
     472           0 :             break;
     473             : 
     474             :         case 0x0125:   // Group 4 Options
     475           0 :             nGroup4Options = ReadIntData();
     476             :             SAL_INFO("filter.tiff","Group4Options: " << nGroup4Options);
     477           0 :             break;
     478             : 
     479             :         case 0x0128:   // Resolution Unit
     480          12 :             nResolutionUnit = ReadIntData();
     481          12 :             break;
     482             : 
     483             :         case 0x013d:   // Predictor
     484           3 :             nPredictor = ReadIntData();
     485             :             SAL_INFO("filter.tiff","Predictor: " << nPredictor);
     486           3 :             break;
     487             : 
     488             :         case 0x0140: { // Color Map
     489             :             sal_uInt16 nVal;
     490             :             sal_uLong i;
     491           0 :             nNumColors= ( (sal_uLong)1 << nBitsPerSample );
     492           0 :             if ( nDataType == 3 && nNumColors <= 256)
     493             :             {
     494           0 :                 pColorMap = new sal_uLong[ 256 ];
     495           0 :                 for ( i = 0; i < nNumColors; i++ )
     496           0 :                     pColorMap[ i ] = 0;
     497           0 :                 for ( i = 0; i < nNumColors; i++ )
     498             :                 {
     499           0 :                     pTIFF->ReadUInt16( nVal );
     500           0 :                     pColorMap[ i ] |= ( ( (sal_uLong)nVal ) << 8 ) & 0x00ff0000;
     501             :                 }
     502           0 :                 for ( i = 0; i < nNumColors; i++ )
     503             :                 {
     504           0 :                     pTIFF->ReadUInt16( nVal );
     505           0 :                     pColorMap[ i ] |= ( (sal_uLong)nVal ) & 0x0000ff00;
     506             :                 }
     507           0 :                 for ( i = 0; i < nNumColors; i++ )
     508             :                 {
     509           0 :                     pTIFF->ReadUInt16( nVal );
     510           0 :                     pColorMap[ i ] |= ( ( (sal_uLong)nVal ) >> 8 ) & 0x000000ff;
     511             :                 }
     512             :             }
     513             :             else
     514           0 :                 bStatus = false;
     515             :             SAL_INFO("filter.tiff","ColorMap (number of colors): " << nNumColors);
     516           0 :             break;
     517             :         }
     518             : 
     519             :         case 0x0153: { // SampleFormat
     520           4 :             sal_uLong nSampleFormat = ReadIntData();
     521           4 :             if ( nSampleFormat == 3 ) // IEEE floating point samples are not supported yet
     522           0 :                 bStatus = false;
     523           4 :             break;
     524             :         }
     525             :     }
     526             : 
     527         225 :     if ( pTIFF->GetError() )
     528           2 :         bStatus = false;
     529             : }
     530             : 
     531             : 
     532             : 
     533          14 : bool TIFFReader::ReadMap()
     534             : {
     535          14 :     if ( nCompression == 1 || nCompression == 32771 )
     536             :     {
     537             :         sal_uLong ny, np, nStrip, nStripBytesPerRow;
     538             : 
     539           4 :         if ( nCompression == 1 )
     540           4 :             nStripBytesPerRow = nBytesPerRow;
     541             :         else
     542           0 :             nStripBytesPerRow = ( nBytesPerRow + 1 ) & 0xfffffffe;
     543        1460 :         for ( ny = 0; ny < nImageLength; ny++ )
     544             :         {
     545        2912 :             for ( np = 0; np < nPlanes; np++ )
     546             :             {
     547        1456 :                 nStrip = ny / GetRowsPerStrip() + np * nStripsPerPlane;
     548        1456 :                 if ( nStrip >= nNumStripOffsets )
     549           0 :                     return false;
     550        1456 :                 pTIFF->Seek( pStripOffsets[ nStrip ] + ( ny % GetRowsPerStrip() ) * nStripBytesPerRow );
     551        1456 :                 pTIFF->Read( pMap[ np ], nBytesPerRow );
     552        1456 :                 if ( pTIFF->GetError() )
     553           0 :                     return false;
     554             :             }
     555        1456 :             if ( !ConvertScanline( ny ) )
     556           0 :                 return false;
     557           4 :         }
     558             :     }
     559          10 :     else if ( nCompression == 2 || nCompression == 3 || nCompression == 4 )
     560             :     {
     561             :         sal_uLong ny, np, nStrip, nOptions;
     562           1 :         if ( nCompression == 2 )
     563             :         {
     564           0 :             nOptions = CCI_OPTION_BYTEALIGNROW;
     565             :         }
     566           1 :         else if ( nCompression == 3 )
     567             :         {
     568           1 :             nOptions = CCI_OPTION_EOL;
     569           1 :             if ( nGroup3Options & 0x00000001 )
     570           0 :                 nOptions |= CCI_OPTION_2D;
     571           1 :             if ( nGroup3Options & 0x00000004 )
     572           0 :                 nOptions |= CCI_OPTION_BYTEALIGNEOL;
     573           1 :             if ( nGroup3Options & 0xfffffffa )
     574           0 :                 return false;
     575             :         }
     576             :         else
     577             :         {   // nCompression==4
     578           0 :             nOptions = CCI_OPTION_2D;
     579           0 :             if ( nGroup4Options & 0xffffffff )
     580           0 :                 return false;
     581             :         }
     582           1 :         if ( nFillOrder == 2 )
     583             :         {
     584           1 :             nOptions |= CCI_OPTION_INVERSEBITORDER;
     585           1 :             bByteSwap = false;
     586             :         }
     587           1 :         nStrip = 0;
     588           1 :         if ( nStrip >= nNumStripOffsets )
     589           0 :             return false;
     590           1 :         pTIFF->Seek(pStripOffsets[nStrip]);
     591             : 
     592           1 :         CCIDecompressor aCCIDecom( nOptions, nImageWidth );
     593             : 
     594           1 :         aCCIDecom.StartDecompression( *pTIFF );
     595             : 
     596        3249 :         for ( ny = 0; ny < nImageLength; ny++ )
     597             :         {
     598        6496 :             for ( np = 0; np < nPlanes; np++ )
     599             :             {
     600        3248 :                 if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip )
     601             :                 {
     602           0 :                     nStrip=ny/GetRowsPerStrip()+np*nStripsPerPlane;
     603           0 :                     if ( nStrip >= nNumStripOffsets )
     604           0 :                         return false;
     605           0 :                     pTIFF->Seek( pStripOffsets[ nStrip ] );
     606           0 :                     aCCIDecom.StartDecompression( *pTIFF );
     607             :                 }
     608        3248 :                 if ( !aCCIDecom.DecompressScanline( pMap[ np ], nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes, np + 1 == nPlanes ) )
     609           0 :                     return false;
     610        3248 :                 if ( pTIFF->GetError() )
     611           0 :                     return false;
     612             :             }
     613        3248 :             if ( !ConvertScanline( ny ) )
     614           0 :                 return false;
     615           1 :         }
     616             :     }
     617           9 :     else if ( nCompression == 5 )
     618             :     {
     619           2 :         LZWDecompressor aLZWDecom;
     620             :         sal_uLong ny, np, nStrip;
     621           2 :         nStrip=0;
     622           2 :         if ( nStrip >= nNumStripOffsets )
     623           0 :             return false;
     624           2 :         pTIFF->Seek(pStripOffsets[nStrip]);
     625           2 :         aLZWDecom.StartDecompression(*pTIFF);
     626         514 :         for ( ny = 0; ny < nImageLength; ny++ )
     627             :         {
     628        1025 :             for ( np = 0; np < nPlanes; np++ )
     629             :             {
     630         513 :                 if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip )
     631             :                 {
     632          85 :                     nStrip = ny / GetRowsPerStrip() + np * nStripsPerPlane;
     633          85 :                     if ( nStrip >= nNumStripOffsets )
     634           0 :                         return false;
     635          85 :                     pTIFF->Seek(pStripOffsets[nStrip]);
     636          85 :                     aLZWDecom.StartDecompression(*pTIFF);
     637             :                 }
     638         513 :                 if ( ( aLZWDecom.Decompress( pMap[ np ], nBytesPerRow ) != nBytesPerRow ) || pTIFF->GetError() )
     639           1 :                     return false;
     640             :             }
     641         512 :             if ( !ConvertScanline( ny ) )
     642           0 :                 return false;
     643           1 :         }
     644             :     }
     645           7 :     else if ( nCompression == 32773 )
     646             :     {
     647             :         sal_uLong nStrip,nRecCount,nRowBytesLeft,ny,np,i;
     648             :         sal_uInt8 * pdst;
     649           1 :         nStrip = 0;
     650           1 :         if ( nStrip >= nNumStripOffsets )
     651           0 :             return false;
     652           1 :         pTIFF->Seek(pStripOffsets[nStrip]);
     653         393 :         for ( ny = 0; ny < nImageLength; ny++ )
     654             :         {
     655         784 :             for ( np = 0; np < nPlanes; np++ )
     656             :             {
     657         392 :                 if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip )
     658             :                 {
     659          78 :                     nStrip=ny/GetRowsPerStrip()+np*nStripsPerPlane;
     660          78 :                     if ( nStrip >= nNumStripOffsets )
     661           0 :                         return false;
     662          78 :                     pTIFF->Seek(pStripOffsets[nStrip]);
     663             :                 }
     664         392 :                 nRowBytesLeft = nBytesPerRow;
     665         392 :                 pdst=pMap[ np ];
     666        8831 :                 do
     667             :                 {
     668        8831 :                     sal_uInt8 nRecHeader(0);
     669        8831 :                     pTIFF->ReadUChar( nRecHeader );
     670        8831 :                     if ((nRecHeader&0x80)==0)
     671             :                     {
     672        5700 :                         nRecCount=0x00000001+((sal_uLong)nRecHeader);
     673        5700 :                         if ( nRecCount > nRowBytesLeft )
     674           0 :                             return false;
     675        5700 :                         pTIFF->Read(pdst,nRecCount);
     676        5700 :                         pdst+=nRecCount;
     677        5700 :                         nRowBytesLeft-=nRecCount;
     678             :                     }
     679        3131 :                     else if ( nRecHeader != 0x80 )
     680             :                     {
     681        3131 :                         nRecCount = 0x000000101 - ( (sal_uLong)nRecHeader );
     682        3131 :                         if ( nRecCount > nRowBytesLeft )
     683             :                         {
     684           0 :                             nRecCount = nRowBytesLeft;
     685             : 
     686             : //                          bStatus = sal_False;
     687             : //                          return;
     688             : 
     689             :                         }
     690        3131 :                         sal_uInt8 nRecData(0);
     691        3131 :                         pTIFF->ReadUChar( nRecData );
     692       12267 :                         for ( i = 0; i < nRecCount; i++ )
     693        9136 :                             *(pdst++) = nRecData;
     694        3131 :                         nRowBytesLeft -= nRecCount;
     695             :                     }
     696             :                 } while ( nRowBytesLeft != 0 );
     697         392 :                 if ( pTIFF->GetError() )
     698           0 :                     return false;
     699             :             }
     700         392 :             if ( !ConvertScanline( ny ) )
     701           0 :                 return false;
     702             :         }
     703             :     }
     704             :     else
     705           6 :         return false;
     706           7 :     return true;
     707             : }
     708             : 
     709           0 : sal_uLong TIFFReader::GetBits( const sal_uInt8 * pSrc, sal_uLong nBitsPos, sal_uLong nBitsCount )
     710             : {
     711             :     sal_uLong nRes;
     712           0 :     if ( bByteSwap )
     713             :     {
     714           0 :         pSrc += ( nBitsPos >> 3 );
     715           0 :         nBitsPos &= 7;
     716           0 :         sal_uInt8 nDat = *pSrc;
     717           0 :         nRes = (sal_uLong)( BYTESWAP( nDat ) & ( 0xff >> nBitsPos ) );
     718             : 
     719           0 :         if ( nBitsCount <= 8 - nBitsPos )
     720             :         {
     721           0 :             nRes >>= ( 8 - nBitsPos - nBitsCount );
     722             :         }
     723             :         else
     724             :         {
     725           0 :             pSrc++;
     726           0 :             nBitsCount -= 8 - nBitsPos;
     727           0 :             while ( nBitsCount >= 8 )
     728             :             {
     729           0 :                 nDat = *(pSrc++);
     730           0 :                 nRes = ( nRes << 8 ) | ((sal_uLong)BYTESWAP( nDat ) );
     731           0 :                 nBitsCount -= 8;
     732             :             }
     733           0 :             if ( nBitsCount > 0 )
     734             :             {
     735           0 :                 nDat = *pSrc;
     736           0 :                 nRes = ( nRes << nBitsCount ) | (((sal_uLong)BYTESWAP(nDat))>>(8-nBitsCount));
     737             :             }
     738             :         }
     739             :     }
     740             :     else
     741             :     {
     742           0 :         pSrc += ( nBitsPos >> 3 );
     743           0 :         nBitsPos &= 7;
     744           0 :         nRes = (sal_uLong)((*pSrc)&(0xff>>nBitsPos));
     745           0 :         if ( nBitsCount <= 8 - nBitsPos )
     746             :         {
     747           0 :             nRes >>= ( 8 - nBitsPos - nBitsCount );
     748             :         }
     749             :         else
     750             :         {
     751           0 :             pSrc++;
     752           0 :             nBitsCount -= 8 - nBitsPos;
     753           0 :             while ( nBitsCount >= 8 )
     754             :             {
     755           0 :                 nRes = ( nRes << 8 ) | ((sal_uLong)*(pSrc++));
     756           0 :                 nBitsCount -= 8;
     757             :             }
     758           0 :             if ( nBitsCount > 0 )
     759           0 :                 nRes = ( nRes << nBitsCount ) | (((sal_uLong)*pSrc)>>(8-nBitsCount));
     760             :         }
     761             :     }
     762           0 :     return nRes;
     763             : }
     764             : 
     765             : 
     766             : 
     767        5608 : bool TIFFReader::ConvertScanline( sal_uLong nY )
     768             : {
     769             :     sal_uInt32  nRed, nGreen, nBlue, ns, nx, nVal, nByteCount;
     770             :     sal_uInt8   nByteVal;
     771             : 
     772        5608 :     if ( nDstBitsPerPixel == 24 )
     773             :     {
     774        4720 :         if ( nBitsPerSample == 8 && nSamplesPerPixel >= 3 &&
     775        4720 :              nPlanes == 1 && nPhotometricInterpretation == 2 )
     776             :         {
     777        2360 :             sal_uInt8*  pt = pMap[ 0 ];
     778             : 
     779             :             // are the values being saved as difference?
     780        2360 :             if ( 2 == nPredictor )
     781             :             {
     782           0 :                 sal_uInt8  nLRed = 0;
     783           0 :                 sal_uInt8  nLGreen = 0;
     784           0 :                 sal_uInt8  nLBlue = 0;
     785           0 :                 sal_uInt8  nLAlpha = 0;
     786           0 :                 for ( nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel )
     787             :                 {
     788           0 :                     nLRed = nLRed + pt[ 0 ];
     789           0 :                     nLGreen = nLGreen + pt[ 1 ];
     790           0 :                     nLBlue = nLBlue + pt[ 2 ];
     791           0 :                     pAcc->SetPixel( nY, nx, Color( nLRed, nLGreen, nLBlue ) );
     792           0 :                     if (nSamplesPerPixel >= 4 && pMaskAcc)
     793             :                     {
     794           0 :                         nLAlpha = nLAlpha + pt[ 3 ];
     795           0 :                         pMaskAcc->SetPixel( nY, nx, BitmapColor(~nLAlpha) );
     796             :                     }
     797             :                 }
     798             :             }
     799             :             else
     800             :             {
     801     1438488 :                 for ( nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel )
     802             :                 {
     803     1436128 :                     pAcc->SetPixel( nY, nx, Color( pt[0], pt[1], pt[2] ) );
     804     1436128 :                     if (nSamplesPerPixel >= 4 && pMaskAcc)
     805             :                     {
     806         256 :                         sal_uInt8 nAlpha = pt[3];
     807         256 :                         pMaskAcc->SetPixel( nY, nx, BitmapColor(~nAlpha) );
     808             :                     }
     809             :                 }
     810        2360 :             }
     811             :         }
     812           0 :         else if ( nPhotometricInterpretation == 2 && nSamplesPerPixel >= 3 )
     813             :         {
     814           0 :             if ( nMaxSampleValue > nMinSampleValue )
     815             :             {
     816           0 :                 sal_uLong nMinMax = nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue );
     817           0 :                 for ( nx = 0; nx < nImageWidth; nx++ )
     818             :                 {
     819           0 :                     if ( nPlanes < 3 )
     820             :                     {
     821           0 :                         nRed = GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + 0 ) * nBitsPerSample, nBitsPerSample );
     822           0 :                         nGreen = GetBits( pMap[ 1 ], ( nx * nSamplesPerPixel + 1 ) * nBitsPerSample, nBitsPerSample );
     823           0 :                         nBlue = GetBits( pMap[ 2 ], ( nx * nSamplesPerPixel + 2 ) * nBitsPerSample, nBitsPerSample );
     824             :                     }
     825             :                     else
     826             :                     {
     827           0 :                         nRed = GetBits( pMap[ 0 ], nx * nBitsPerSample, nBitsPerSample );
     828           0 :                         nGreen = GetBits( pMap[ 1 ], nx * nBitsPerSample, nBitsPerSample );
     829           0 :                         nBlue = GetBits( pMap[ 2 ], nx * nBitsPerSample, nBitsPerSample );
     830             :                     }
     831           0 :                     pAcc->SetPixel( nY, nx, Color( (sal_uInt8)( nRed - nMinMax ), (sal_uInt8)( nGreen - nMinMax ), (sal_uInt8)(nBlue - nMinMax) ) );
     832             :                 }
     833           0 :             }
     834             :         }
     835           0 :         else if ( nPhotometricInterpretation == 5 && nSamplesPerPixel == 3 )
     836             :         {
     837           0 :             if ( nMaxSampleValue > nMinSampleValue )
     838             :             {
     839           0 :                 sal_uLong nMinMax =  nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue );
     840           0 :                 for ( nx = 0; nx < nImageWidth; nx++ )
     841             :                 {
     842           0 :                     if ( nPlanes < 3 )
     843             :                     {
     844           0 :                         nRed = GetBits( pMap[ 0 ],( nx * nSamplesPerPixel + 0 ) * nBitsPerSample, nBitsPerSample );
     845           0 :                         nGreen = GetBits( pMap[ 0 ],( nx * nSamplesPerPixel + 1 ) * nBitsPerSample, nBitsPerSample );
     846           0 :                         nBlue = GetBits( pMap[ 0 ],( nx * nSamplesPerPixel + 2 ) * nBitsPerSample, nBitsPerSample );
     847             :                     }
     848             :                     else
     849             :                     {
     850           0 :                         nRed = GetBits( pMap[ 0 ], nx * nBitsPerSample, nBitsPerSample );
     851           0 :                         nGreen = GetBits( pMap[ 1 ], nx * nBitsPerSample, nBitsPerSample );
     852           0 :                         nBlue = GetBits( pMap[ 2 ], nx * nBitsPerSample, nBitsPerSample );
     853             :                     }
     854           0 :                     nRed = 255 - (sal_uInt8)( nRed - nMinMax );
     855           0 :                     nGreen = 255 - (sal_uInt8)( nGreen - nMinMax );
     856           0 :                     nBlue = 255 - (sal_uInt8)( nBlue - nMinMax );
     857           0 :                     pAcc->SetPixel( nY, nx, Color( (sal_uInt8) nRed, (sal_uInt8) nGreen, (sal_uInt8) nBlue ) );
     858             :                 }
     859           0 :             }
     860             :         }
     861           0 :         else if( nPhotometricInterpretation == 5 && nSamplesPerPixel == 4 )
     862             :         {
     863           0 :             if ( nMaxSampleValue > nMinSampleValue )
     864             :             {
     865             :                 sal_uInt8   nSamp[ 4 ];
     866           0 :                 sal_uInt8   nSampLast[ 4 ] = { 0, 0, 0, 0 };
     867             : 
     868           0 :                 for( nx = 0; nx < nImageWidth; nx++ )
     869             :                 {
     870             :                     // are the values being saved as difference?
     871           0 :                     if( 2 == nPredictor )
     872             :                     {
     873           0 :                         for( ns = 0; ns < 4; ns++ )
     874             :                         {
     875           0 :                             if( nPlanes < 3 )
     876           0 :                                 nSampLast[ ns ] = nSampLast[ ns ] + (sal_uInt8) GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample );
     877             :                             else
     878           0 :                                 nSampLast[ ns ] = nSampLast[ ns ] + (sal_uInt8) GetBits( pMap[ ns ], nx * nBitsPerSample, nBitsPerSample );
     879           0 :                             nSamp[ ns ] = nSampLast[ ns ];
     880             :                         }
     881             :                     }
     882             :                     else
     883             :                     {
     884           0 :                         for( ns = 0; ns < 4; ns++ )
     885             :                         {
     886           0 :                             if( nPlanes < 3 )
     887           0 :                                 nSamp[ ns ] = (sal_uInt8) GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample );
     888             :                             else
     889           0 :                                 nSamp[ ns ]= (sal_uInt8) GetBits( pMap[ ns ], nx * nBitsPerSample, nBitsPerSample );
     890             :                         }
     891             :                     }
     892           0 :                     const long nBlack = nSamp[ 3 ];
     893           0 :                     nRed = (sal_uInt8) std::max( 0L, 255L - ( ( (long) nSamp[ 0 ] + nBlack - ( ( (long) nMinSampleValue ) << 1 ) ) *
     894           0 :                                 255L/(long)(nMaxSampleValue-nMinSampleValue) ) );
     895           0 :                     nGreen = (sal_uInt8) std::max( 0L, 255L - ( ( (long) nSamp[ 1 ] + nBlack - ( ( (long) nMinSampleValue ) << 1 ) ) *
     896           0 :                                 255L/(long)(nMaxSampleValue-nMinSampleValue) ) );
     897           0 :                     nBlue = (sal_uInt8) std::max( 0L, 255L - ( ( (long) nSamp[ 2 ] + nBlack - ( ( (long) nMinSampleValue ) << 1 ) ) *
     898           0 :                                 255L/(long)(nMaxSampleValue-nMinSampleValue) ) );
     899           0 :                     pAcc->SetPixel( nY, nx, Color ( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
     900             :                 }
     901             :             }
     902             :         }
     903             :     }
     904        3248 :     else if ( nSamplesPerPixel == 1 && ( nPhotometricInterpretation <= 1 || nPhotometricInterpretation == 3 ) )
     905             :     {
     906        3248 :         if ( nMaxSampleValue > nMinSampleValue )
     907             :         {
     908        3248 :             sal_uLong nMinMax = ( ( 1 << nDstBitsPerPixel ) - 1 ) / ( nMaxSampleValue - nMinSampleValue );
     909        3248 :             sal_uInt8* pt = pMap[ 0 ];
     910             :             sal_uInt8 nShift;
     911             : 
     912        3248 :             switch ( nDstBitsPerPixel )
     913             :             {
     914             :                 case 8 :
     915             :                 {
     916           0 :                     if ( bByteSwap )
     917             :                     {
     918           0 :                         if ( nPredictor == 2 )
     919             :                         {
     920           0 :                             sal_uInt8 nLast = 0;
     921           0 :                             for ( nx = 0; nx < nImageWidth; nx++ )
     922             :                             {
     923           0 :                                 nLast += nx == 0 ? BYTESWAP( (sal_uInt8)*pt++ ) : *pt++;
     924           0 :                                 pAcc->SetPixelIndex( nY, nx, nLast );
     925             :                             }
     926             :                         }
     927             :                         else
     928             :                         {
     929           0 :                             for ( nx = 0; nx < nImageWidth; nx++ )
     930             :                             {
     931           0 :                                 sal_uInt8 nLast = *pt++;
     932           0 :                                 pAcc->SetPixelIndex( nY, nx, static_cast<sal_uInt8>( (BYTESWAP((sal_uLong)nLast) - nMinSampleValue) * nMinMax ) );
     933             :                             }
     934             :                         }
     935             :                     }
     936             :                     else
     937             :                     {
     938           0 :                         if ( nPredictor == 2 )
     939             :                         {
     940           0 :                             sal_uInt8 nLast = 0;
     941           0 :                             for ( nx = 0; nx < nImageWidth; nx++ )
     942             :                             {
     943           0 :                                 nLast += *pt++;
     944           0 :                                 pAcc->SetPixelIndex( nY, nx, nLast );
     945             :                             }
     946             :                         }
     947             :                         else
     948             :                         {
     949           0 :                             for ( nx = 0; nx < nImageWidth; nx++ )
     950             :                             {
     951           0 :                                 pAcc->SetPixelIndex( nY, nx, static_cast<sal_uInt8>( ((sal_uLong)*pt++ - nMinSampleValue) * nMinMax ) );
     952             : 
     953             :                             }
     954             :                         }
     955             :                     }
     956             :                 }
     957           0 :                 break;
     958             : 
     959             :                 case 7 :
     960             :                 case 6 :
     961             :                 case 5 :
     962             :                 case 4 :
     963             :                 case 3 :
     964             :                 case 2 :
     965             :                 {
     966           0 :                     for ( nx = 0; nx < nImageWidth; nx++ )
     967             :                     {
     968           0 :                         nVal = ( GetBits( pt, nx * nBitsPerSample, nBitsPerSample ) - nMinSampleValue ) * nMinMax;
     969           0 :                         pAcc->SetPixelIndex( nY, nx, static_cast<sal_uInt8>(nVal));
     970             :                     }
     971             :                 }
     972           0 :                 break;
     973             : 
     974             :                 case 1 :
     975             :                 {
     976        3248 :                     if ( bByteSwap )
     977             :                     {
     978           0 :                         nx = 0;
     979           0 :                         nByteCount = ( nImageWidth >> 3 ) + 1;
     980           0 :                         while ( --nByteCount )
     981             :                         {
     982           0 :                             nByteVal = *pt++;
     983           0 :                             pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
     984           0 :                             nByteVal >>= 1;
     985           0 :                             pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
     986           0 :                             nByteVal >>= 1;
     987           0 :                             pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
     988           0 :                             nByteVal >>= 1;
     989           0 :                             pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
     990           0 :                             nByteVal >>= 1;
     991           0 :                             pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
     992           0 :                             nByteVal >>= 1;
     993           0 :                             pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
     994           0 :                             nByteVal >>= 1;
     995           0 :                             pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
     996           0 :                             nByteVal >>= 1;
     997           0 :                             pAcc->SetPixelIndex( nY, nx++, nByteVal );
     998             :                         }
     999           0 :                         if ( nImageWidth & 7 )
    1000             :                         {
    1001           0 :                             nByteVal = *pt++;
    1002           0 :                             while ( nx < nImageWidth )
    1003             :                             {
    1004           0 :                                 pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
    1005           0 :                                 nByteVal >>= 1;
    1006             :                             }
    1007             :                         }
    1008             :                     }
    1009             :                     else
    1010             :                     {
    1011        3248 :                         nx = 7;
    1012        3248 :                         nByteCount = ( nImageWidth >> 3 ) + 1;
    1013     1006880 :                         while ( --nByteCount )
    1014             :                         {
    1015     1000384 :                             nByteVal = *pt++;
    1016     1000384 :                             pAcc->SetPixelIndex( nY, nx, nByteVal & 1 );
    1017     1000384 :                             nByteVal >>= 1;
    1018     1000384 :                             pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
    1019     1000384 :                             nByteVal >>= 1;
    1020     1000384 :                             pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
    1021     1000384 :                             nByteVal >>= 1;
    1022     1000384 :                             pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
    1023     1000384 :                             nByteVal >>= 1;
    1024     1000384 :                             pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
    1025     1000384 :                             nByteVal >>= 1;
    1026     1000384 :                             pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
    1027     1000384 :                             nByteVal >>= 1;
    1028     1000384 :                             pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
    1029     1000384 :                             nByteVal >>= 1;
    1030     1000384 :                             pAcc->SetPixelIndex( nY, --nx, nByteVal );
    1031     1000384 :                             nx += 15;
    1032             :                         }
    1033        3248 :                         if ( nImageWidth & 7 )
    1034             :                         {
    1035           0 :                             nx -= 7;
    1036           0 :                             nByteVal = *pt++;
    1037           0 :                             nShift = 7;
    1038           0 :                             while ( nx < nImageWidth )
    1039             :                             {
    1040           0 :                                 pAcc->SetPixelIndex( nY, nx++, ( nByteVal >> nShift ) & 1);
    1041             :                             }
    1042             :                         }
    1043             :                     }
    1044             :                 }
    1045        3248 :                 break;
    1046             : 
    1047             :                 default :
    1048           0 :                     return false;
    1049             :             }
    1050        3248 :         }
    1051             :     }
    1052           0 :     else if ( ( nSamplesPerPixel == 2 ) && ( nBitsPerSample == 8 ) &&
    1053           0 :         ( nPlanarConfiguration == 1 ) && ( pColorMap == 0 ) )               // grayscale
    1054             :     {
    1055           0 :         if ( nMaxSampleValue > nMinSampleValue )
    1056             :         {
    1057           0 :             sal_uLong nMinMax = ( ( 1 << 8 /*nDstBitsPerPixel*/ ) - 1 ) / ( nMaxSampleValue - nMinSampleValue );
    1058           0 :             sal_uInt8*  pt = pMap[ 0 ];
    1059           0 :             for ( nx = 0; nx < nImageWidth; nx++, pt += 2 )
    1060             :             {
    1061           0 :                 pAcc->SetPixelIndex( nY, nx, static_cast<sal_uInt8>( ((sal_uLong)*pt - nMinSampleValue) * nMinMax) );
    1062             :             }
    1063           0 :         }
    1064             :     }
    1065             :     else
    1066           0 :         return false;
    1067        5608 :     return true;
    1068             : }
    1069             : 
    1070             : 
    1071             : 
    1072           7 : void TIFFReader::MakePalCol()
    1073             : {
    1074           7 :     if ( nDstBitsPerPixel <= 8 )
    1075             :     {
    1076             :         sal_uLong i, nVal, n0RGB;
    1077           1 :         if  ( pColorMap == NULL )
    1078           1 :             pColorMap = new sal_uLong[ 256 ];
    1079           1 :         if ( nPhotometricInterpretation <= 1 )
    1080             :         {
    1081           1 :             nNumColors = (sal_uLong)1 << nBitsPerSample;
    1082           1 :             if ( nNumColors > 256 )
    1083           0 :                 nNumColors = 256;
    1084           1 :             pAcc->SetPaletteEntryCount( (sal_uInt16)nNumColors );
    1085           3 :             for ( i = 0; i < nNumColors; i++ )
    1086             :             {
    1087           2 :                 nVal = ( i * 255 / ( nNumColors - 1 ) ) & 0xff;
    1088           2 :                 n0RGB = nVal | ( nVal << 8 ) | ( nVal << 16 );
    1089           2 :                 if ( nPhotometricInterpretation == 1 )
    1090           0 :                     pColorMap[ i ] = n0RGB;
    1091             :                 else
    1092           2 :                     pColorMap[ nNumColors - i - 1 ] = n0RGB;
    1093             :             }
    1094             :         }
    1095           3 :         for ( i = 0; i < nNumColors; i++ )
    1096             :         {
    1097           2 :             pAcc->SetPaletteColor( (sal_uInt16)i, BitmapColor( (sal_uInt8)( pColorMap[ i ] >> 16 ),
    1098           4 :                 (sal_uInt8)( pColorMap[ i ] >> 8 ), (sal_uInt8)pColorMap[ i ] ) );
    1099             :         }
    1100             :     }
    1101             : 
    1102           7 :     if ( fXResolution > 1.0 && fYResolution > 1.0 && ( nResolutionUnit == 2 || nResolutionUnit == 3 ) )
    1103             :     {
    1104             :         sal_uLong nRX,nRY;
    1105           6 :         if (nResolutionUnit==2)
    1106             :         {
    1107           6 :             nRX=(sal_uLong)(fXResolution+0.5);
    1108           6 :             nRY=(sal_uLong)(fYResolution+0.5);
    1109             :         }
    1110             :         else
    1111             :         {
    1112           0 :             nRX=(sal_uLong)(fXResolution*2.54+0.5);
    1113           0 :             nRY=(sal_uLong)(fYResolution*2.54+0.5);
    1114             :         }
    1115           6 :         MapMode aMapMode(MAP_INCH,Point(0,0),Fraction(1,nRX),Fraction(1,nRY));
    1116           6 :         aBitmap.SetPrefMapMode(aMapMode);
    1117           6 :         aBitmap.SetPrefSize(Size(nImageWidth,nImageLength));
    1118             :     }
    1119           7 : }
    1120             : 
    1121             : 
    1122             : 
    1123          17 : void TIFFReader::ReadHeader()
    1124             : {
    1125          17 :     sal_uInt8 nbyte1(0), nbyte2(0);
    1126          17 :     sal_uInt16 nushort(0);
    1127             : 
    1128          17 :     pTIFF->ReadUChar( nbyte1 );
    1129          17 :     if ( nbyte1 == 'I' )
    1130           8 :         pTIFF->SetEndian( SvStreamEndian::LITTLE );
    1131             :     else
    1132           9 :         pTIFF->SetEndian( SvStreamEndian::BIG );
    1133             : 
    1134          17 :     pTIFF->ReadUChar( nbyte2 ).ReadUInt16( nushort );
    1135          17 :     if ( nbyte1 != nbyte2 || ( nbyte1 != 'I' && nbyte1 != 'M' ) || nushort != 0x002a )
    1136           1 :         bStatus = false;
    1137          17 : }
    1138             : 
    1139          14 : bool TIFFReader::HasAlphaChannel() const
    1140             : {
    1141             :     /*There are undoubtedly more variants we could support, but keep it simple for now*/
    1142             :     return (
    1143          22 :              nDstBitsPerPixel == 24 &&
    1144          16 :              nBitsPerSample == 8 &&
    1145           9 :              nSamplesPerPixel >= 4 &&
    1146          16 :              nPlanes == 1 &&
    1147           1 :              nPhotometricInterpretation == 2
    1148          14 :            );
    1149             : }
    1150             : 
    1151             : 
    1152             : 
    1153          17 : bool TIFFReader::ReadTIFF(SvStream & rTIFF, Graphic & rGraphic )
    1154             : {
    1155          17 :     sal_uInt16  i, nNumTags(0), nTagType(0);
    1156             :     sal_uInt64  nMaxPos;
    1157             :     sal_uLong   nPos;
    1158          17 :     sal_uInt32 nFirstIfd(0), nDataLen;
    1159             : 
    1160          17 :     bStatus = true;
    1161          17 :     nLastPercent = 0;
    1162             : 
    1163          17 :     pTIFF = &rTIFF;
    1164          17 :     nMaxPos = nOrigPos = pTIFF->Tell();
    1165             :     // number format of pTIFF at the beginning
    1166          17 :     SvStreamEndian nOrigNumberFormat = pTIFF->GetEndian();
    1167             : 
    1168             :     // read header:
    1169          17 :     ReadHeader();
    1170             : 
    1171             :     // read first IFD:
    1172          17 :     pTIFF->ReadUInt32( nFirstIfd );
    1173             : 
    1174          17 :     if( !nFirstIfd || pTIFF->GetError() )
    1175           0 :         bStatus = false;
    1176             : 
    1177          17 :     if ( bStatus )
    1178             :     {
    1179          16 :         sal_uInt32 nOffset = nFirstIfd;
    1180             : 
    1181             :         // calculate length of TIFF file
    1182          16 :         do
    1183             :         {
    1184          18 :             pTIFF->Seek( nOrigPos + nOffset );
    1185             : 
    1186          18 :             if( pTIFF->GetError() )
    1187             :             {
    1188           2 :                 pTIFF->ResetError();
    1189           2 :                 break;
    1190             :             };
    1191          16 :             nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
    1192             : 
    1193          16 :             pTIFF->ReadUInt16( nNumTags );
    1194             : 
    1195             :             // loop through tags:
    1196         263 :             for( i = 0; i < nNumTags; i++ )
    1197             :             {
    1198         247 :                 pTIFF->ReadUInt16( nTagType ).ReadUInt16( nDataType ).ReadUInt32( nDataLen ).ReadUInt32( nOffset );
    1199             : 
    1200         247 :                 if( DataTypeSize() * nDataLen > 4 )
    1201          94 :                     nMaxPos = std::max( (sal_uInt64) nOrigPos + nOffset + DataTypeSize() * nDataLen, nMaxPos );
    1202             :             }
    1203          16 :             pTIFF->ReadUInt32( nOffset );
    1204          16 :             if ( pTIFF->IsEof() )
    1205           0 :                 nOffset = 0;
    1206             : 
    1207          16 :             nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
    1208          16 :             if ( !nOffset )
    1209          14 :                 nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
    1210             :         }
    1211             :         while( nOffset );
    1212             : 
    1213          48 :         for ( sal_uInt32 nNextIfd = nFirstIfd; nNextIfd && bStatus; )
    1214             :         {
    1215          16 :             pTIFF->Seek( nOrigPos + nNextIfd );
    1216             :             {
    1217          16 :                 bByteSwap = false;
    1218             : 
    1219          16 :                 nNewSubFile = 0;
    1220          16 :                 nSubFile = 0;
    1221          16 :                 nImageWidth = 0;
    1222          16 :                 nImageLength = 0;
    1223          16 :                 nBitsPerSample = 1;                         // default value according to the documentation
    1224          16 :                 nCompression = 1;
    1225          16 :                 nPhotometricInterpretation = 0;
    1226          16 :                 nThresholding = 1;                          // default value according to the documentation
    1227          16 :                 nCellWidth = 1;
    1228          16 :                 nCellLength = 1;
    1229          16 :                 nFillOrder = 1;                             // default value according to the documentation
    1230          16 :                 nNumStripOffsets = 0;
    1231          16 :                 nOrientation = 1;
    1232          16 :                 nSamplesPerPixel = 1;                       // default value according to the documentation
    1233          16 :                 nRowsPerStrip = 0xffffffff;                 // default value according to the documentation
    1234          16 :                 nNumStripByteCounts = 0;
    1235          16 :                 nMinSampleValue = 0;                        // default value according to the documentation
    1236          16 :                 nMaxSampleValue = 0;
    1237          16 :                 fXResolution = 0.0;
    1238          16 :                 fYResolution = 0.0;
    1239          16 :                 nPlanarConfiguration = 1;
    1240          16 :                 nGroup3Options = 0;                         // default value according to the documentation
    1241          16 :                 nGroup4Options = 0;                         // default value according to the documentation
    1242          16 :                 nResolutionUnit = 2;                        // default value according to the documentation
    1243          16 :                 nPredictor = 1;
    1244          16 :                 nNumColors = 0;
    1245             : 
    1246          16 :                 pAcc = NULL;
    1247          16 :                 pColorMap = NULL;
    1248          16 :                 pStripOffsets = NULL;
    1249          16 :                 pStripByteCounts = NULL;
    1250          16 :                 pMap[ 0 ] = pMap[ 1 ] = pMap[ 2 ] = pMap[ 3 ] = NULL;
    1251             : 
    1252          16 :                 pTIFF->ReadUInt16( nNumTags );
    1253          16 :                 nPos = pTIFF->Tell();
    1254             : 
    1255          16 :                 const size_t nMinRecordSize = 8;
    1256          16 :                 const size_t nMaxRecords = pTIFF->remainingSize() / nMinRecordSize;
    1257          16 :                 if (nNumTags > nMaxRecords)
    1258             :                 {
    1259             :                     SAL_WARN("filter.tiff", "Parsing error: " << nMaxRecords <<
    1260             :                              " max possible entries, but " << nNumTags << " claimed, truncating");
    1261           0 :                     nNumTags = nMaxRecords;
    1262             :                 }
    1263             : 
    1264             :                 // Schleife ueber Tags:
    1265         239 :                 for( i = 0; i < nNumTags; i++ )
    1266             :                 {
    1267         225 :                     pTIFF->ReadUInt16( nTagType ).ReadUInt16( nDataType ).ReadUInt32( nDataLen );
    1268             : 
    1269         225 :                     if( DataTypeSize() * nDataLen > 4 )
    1270             :                     {
    1271          75 :                         pTIFF->ReadUInt32( nOffset );
    1272          75 :                         pTIFF->Seek( nOrigPos + nOffset );
    1273             :                     }
    1274         225 :                     ReadTagData( nTagType, nDataLen );
    1275         225 :                     nPos += 12; pTIFF->Seek( nPos );
    1276             : 
    1277         225 :                     if ( pTIFF->GetError() )
    1278           2 :                         bStatus = false;
    1279             : 
    1280         225 :                     if ( !bStatus )
    1281           2 :                         break;
    1282             :                 }
    1283          16 :                 pTIFF->ReadUInt32( nNextIfd );
    1284          16 :                 if ( pTIFF->IsEof() )
    1285           0 :                     nNextIfd = 0;
    1286             :             }
    1287          16 :             if ( !nBitsPerSample || ( nBitsPerSample > 32 ) )
    1288           0 :                 bStatus = false;
    1289          16 :             if ( bStatus )
    1290             :             {
    1291          14 :                 if ( nMaxSampleValue == 0 )
    1292             :                 {
    1293          14 :                     if ( nBitsPerSample == 32 )         // sj: i93300, compiler bug, 1 << 32 gives 1 one 32bit windows platforms,
    1294           0 :                         nMaxSampleValue = 0xffffffff;   // (up from 80286 only the lower 5 bits are used when shifting a 32bit register)
    1295             :                     else
    1296          14 :                         nMaxSampleValue = ( 1 << nBitsPerSample ) - 1;
    1297             :                 }
    1298          14 :                 if ( nPhotometricInterpretation == 2 || nPhotometricInterpretation == 5 || nPhotometricInterpretation == 6 )
    1299           8 :                     nDstBitsPerPixel = 24;
    1300           6 :                 else if ( nBitsPerSample*nSamplesPerPixel <= 1 )
    1301           2 :                     nDstBitsPerPixel = 1;
    1302           4 :                 else if ( nBitsPerSample*nSamplesPerPixel <= 4 )
    1303           0 :                     nDstBitsPerPixel = 4;
    1304             :                 else
    1305           4 :                     nDstBitsPerPixel = 8;
    1306             : 
    1307          14 :                 Size aTargetSize( nImageWidth, nImageLength );
    1308          14 :                 aBitmap = Bitmap( aTargetSize, nDstBitsPerPixel );
    1309          14 :                 pAcc = aBitmap.AcquireWriteAccess();
    1310          14 :                 if ( pAcc )
    1311             :                 {
    1312          14 :                     if ( nPlanarConfiguration == 1 )
    1313          14 :                         nPlanes = 1;
    1314             :                     else
    1315           0 :                         nPlanes = nSamplesPerPixel;
    1316             : 
    1317          14 :                     if ( ( nFillOrder == 2 ) && ( nCompression != 5 ) )     // in the LZW mode bits are already being inverted
    1318           1 :                         bByteSwap = true;
    1319             : 
    1320          14 :                     nStripsPerPlane = ( nImageLength - 1 ) / GetRowsPerStrip() + 1;
    1321          14 :                     bStatus = nPlanes != 0;
    1322             : 
    1323          14 :                     if (bStatus)
    1324             :                     {
    1325          14 :                         nBytesPerRow = ( nImageWidth * nSamplesPerPixel / nPlanes * nBitsPerSample + 7 ) >> 3;
    1326             : 
    1327          70 :                         for ( sal_uLong j = 0; j < 4; j++ )
    1328             :                         {
    1329             :                             try
    1330             :                             {
    1331          56 :                                 pMap[ j ] = new sal_uInt8[ nBytesPerRow ];
    1332             :                             }
    1333           0 :                             catch (const std::bad_alloc &)
    1334             :                             {
    1335           0 :                                 pMap[ j ] = NULL;
    1336           0 :                                 bStatus = false;
    1337           0 :                                 break;
    1338             :                             }
    1339             :                         }
    1340             :                     }
    1341             : 
    1342          14 :                     if (bStatus && HasAlphaChannel())
    1343             :                     {
    1344           1 :                         pAlphaMask = new AlphaMask( aTargetSize );
    1345           1 :                         pMaskAcc = pAlphaMask->AcquireWriteAccess();
    1346             :                     }
    1347             : 
    1348          14 :                     if (bStatus && ReadMap())
    1349             :                     {
    1350           7 :                         nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
    1351           7 :                         MakePalCol();
    1352           7 :                         nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
    1353             :                     }
    1354             :                     else
    1355           7 :                         bStatus = false;
    1356             : 
    1357          14 :                     if( pAcc )
    1358             :                     {
    1359          14 :                         Bitmap::ReleaseAccess( pAcc );
    1360             : 
    1361          14 :                         if ( pMaskAcc )
    1362             :                         {
    1363           1 :                             if ( pAlphaMask )
    1364           1 :                                 pAlphaMask->ReleaseAccess( pMaskAcc );
    1365           1 :                             pMaskAcc = NULL;
    1366             :                         }
    1367             : 
    1368          14 :                         if ( bStatus )
    1369             :                         {
    1370           7 :                             BitmapEx aImage;
    1371             : 
    1372           7 :                             if (pAlphaMask)
    1373           1 :                                 aImage = BitmapEx( aBitmap, *pAlphaMask );
    1374             :                             else
    1375           6 :                                 aImage = aBitmap;
    1376             : 
    1377           7 :                             AnimationBitmap aAnimationBitmap( aImage, Point( 0, 0 ), aBitmap.GetSizePixel(),
    1378          14 :                                                               ANIMATION_TIMEOUT_ON_CLICK, DISPOSE_BACK );
    1379             : 
    1380          14 :                             aAnimation.Insert( aAnimationBitmap );
    1381             :                         }
    1382             :                     }
    1383             :                 }
    1384             :             }
    1385             : 
    1386             :             // Clean up:
    1387          80 :             for ( i = 0; i < 4; i++ )
    1388          64 :                 delete[] pMap[ i ];
    1389          16 :             delete[] pColorMap;
    1390          16 :             delete[] pStripOffsets;
    1391          16 :             delete[] pStripByteCounts;
    1392             :         }
    1393             :     }
    1394             : 
    1395             :     // seek to end of TIFF if succeeded
    1396          17 :     pTIFF->SetEndian( nOrigNumberFormat );
    1397          17 :     pTIFF->Seek( bStatus ? nMaxPos : nOrigPos );
    1398             : 
    1399          17 :     if ( aAnimation.Count() )
    1400             :     {
    1401           7 :         if ( aAnimation.Count() == 1 )
    1402           7 :             rGraphic = aAnimation.GetBitmapEx();
    1403             :         else
    1404           0 :             rGraphic = aAnimation;  //aBitmap;
    1405             : 
    1406           7 :         return true;
    1407             :     }
    1408             :     else
    1409          10 :         return false;
    1410             : }
    1411             : 
    1412             : 
    1413             : //================== GraphicImport - the exported function ================
    1414             : 
    1415             : // this needs to be kept in sync with
    1416             : // ImpFilterLibCacheEntry::GetImportFunction() from
    1417             : // vcl/source/filter/graphicfilter.cxx
    1418             : #if defined(DISABLE_DYNLOADING)
    1419             : #define GraphicImport itiGraphicImport
    1420             : #endif
    1421             : 
    1422             : extern "C" SAL_DLLPUBLIC_EXPORT bool SAL_CALL
    1423          17 : GraphicImport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* )
    1424             : {
    1425          17 :     TIFFReader aTIFFReader;
    1426             : 
    1427          17 :     return aTIFFReader.ReadTIFF( rStream, rGraphic );
    1428             : }
    1429             : 
    1430             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11