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

Generated by: LCOV version 1.10