LCOV - code coverage report
Current view: top level - filter/source/graphicfilter/ipsd - ipsd.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 165 359 46.0 %
Date: 2015-06-13 12:38:46 Functions: 6 6 100.0 %
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             : 
      21             : #include <vcl/graph.hxx>
      22             : #include <vcl/bmpacc.hxx>
      23             : #include <vcl/outdev.hxx>
      24             : #include <tools/fract.hxx>
      25             : #include <boost/scoped_array.hpp>
      26             : 
      27             : class FilterConfigItem;
      28             : 
      29             : //============================ PSDReader ==================================
      30             : 
      31             : #define PSD_BITMAP          0
      32             : #define PSD_GRAYSCALE       1
      33             : #define PSD_INDEXED         2
      34             : #define PSD_RGB             3
      35             : #define PSD_CMYK            4
      36             : #define PSD_MULTICHANNEL    7
      37             : #define PSD_DUOTONE         8
      38             : #define PSD_LAB             9
      39             : 
      40             : typedef struct
      41             : {
      42             :     sal_uInt32  nSignature;
      43             :     sal_uInt16  nVersion;
      44             :     sal_uInt32  nPad1;
      45             :     sal_uInt16  nPad2;
      46             :     sal_uInt16  nChannels;
      47             :     sal_uInt32  nRows;
      48             :     sal_uInt32  nColumns;
      49             :     sal_uInt16  nDepth;
      50             :     sal_uInt16  nMode;
      51             : 
      52             : } PSDFileHeader;
      53             : 
      54             : class PSDReader {
      55             : 
      56             : private:
      57             : 
      58             :     SvStream& m_rPSD;           // Die einzulesende PSD-Datei
      59             :     PSDFileHeader*      mpFileHeader;
      60             : 
      61             :     sal_uInt32          mnXResFixed;
      62             :     sal_uInt32          mnYResFixed;
      63             : 
      64             :     bool            mbStatus;
      65             :     bool            mbTransparent;
      66             : 
      67             :     Bitmap              maBmp;
      68             :     Bitmap              maMaskBmp;
      69             :     BitmapReadAccess*   mpReadAcc;
      70             :     BitmapWriteAccess*  mpWriteAcc;
      71             :     BitmapWriteAccess*  mpMaskWriteAcc;
      72             :     sal_uInt16              mnDestBitDepth;
      73             :     bool                mbCompression;  // RLE decoding
      74             :     sal_uInt8*              mpPalette;
      75             : 
      76             :     bool                ImplReadBody();
      77             :     bool                ImplReadHeader();
      78             : 
      79             : public:
      80             :     PSDReader(SvStream &rStream);
      81             :     ~PSDReader();
      82             :     bool ReadPSD(Graphic & rGraphic);
      83             : };
      84             : 
      85             : //=================== Methods of PSDReader ==============================
      86             : 
      87           3 : PSDReader::PSDReader(SvStream &rStream)
      88             :     : m_rPSD(rStream)
      89             :     , mpFileHeader(NULL)
      90             :     , mnXResFixed(0)
      91             :     , mnYResFixed(0)
      92             :     , mbStatus(true)
      93             :     , mbTransparent(false)
      94             :     , mpReadAcc(NULL)
      95             :     , mpWriteAcc(NULL)
      96             :     , mpMaskWriteAcc(NULL)
      97             :     , mnDestBitDepth(0)
      98             :     , mbCompression(false)
      99           3 :     , mpPalette(NULL)
     100             : {
     101           3 : }
     102             : 
     103           6 : PSDReader::~PSDReader()
     104             : {
     105           3 :     delete[] mpPalette;
     106           3 :     delete mpFileHeader;
     107           3 : }
     108             : 
     109           3 : bool PSDReader::ReadPSD(Graphic & rGraphic )
     110             : {
     111           3 :     if (m_rPSD.GetError())
     112           0 :         return false;
     113             : 
     114           3 :     m_rPSD.SetEndian( SvStreamEndian::BIG );
     115             : 
     116             :     // read header:
     117             : 
     118           3 :     if ( !ImplReadHeader() )
     119           1 :         return false;
     120             : 
     121           2 :     Size aBitmapSize( mpFileHeader->nColumns, mpFileHeader->nRows );
     122           2 :     maBmp = Bitmap( aBitmapSize, mnDestBitDepth );
     123           2 :     if ( ( mpWriteAcc = maBmp.AcquireWriteAccess() ) == NULL )
     124           0 :         mbStatus = false;
     125           2 :     if ( ( mpReadAcc = maBmp.AcquireReadAccess() ) == NULL )
     126           0 :         mbStatus = false;
     127           2 :     if ( mbTransparent && mbStatus )
     128             :     {
     129           0 :         maMaskBmp = Bitmap( aBitmapSize, 1 );
     130           0 :         if ( ( mpMaskWriteAcc = maMaskBmp.AcquireWriteAccess() ) == NULL )
     131           0 :             mbStatus = false;
     132             :     }
     133           2 :     if ( mpPalette && mbStatus )
     134             :     {
     135           0 :         mpWriteAcc->SetPaletteEntryCount( 256 );
     136           0 :         for ( sal_uInt16 i = 0; i < 256; i++ )
     137             :         {
     138           0 :             mpWriteAcc->SetPaletteColor( i, Color( mpPalette[ i ], mpPalette[ i + 256 ], mpPalette[ i + 512 ] ) );
     139             :         }
     140             :     }
     141             :     // read bitmap data
     142           2 :     if ( mbStatus && ImplReadBody() )
     143             :     {
     144           2 :         if ( mbTransparent )
     145           0 :             rGraphic = Graphic( BitmapEx( maBmp, maMaskBmp ) );
     146             :         else
     147           2 :             rGraphic = maBmp;
     148             : 
     149           2 :         if ( mnXResFixed && mnYResFixed )
     150             :         {
     151           2 :             Point       aEmptyPoint;
     152           2 :             Fraction    aFractX( 1, mnXResFixed >> 16 );
     153           4 :             Fraction    aFractY( 1, mnYResFixed >> 16 );
     154           4 :             MapMode     aMapMode( MAP_INCH, aEmptyPoint, aFractX, aFractY );
     155           2 :             Size        aPrefSize = OutputDevice::LogicToLogic( aBitmapSize, aMapMode, MAP_100TH_MM );
     156           2 :             rGraphic.SetPrefSize( aPrefSize );
     157           4 :             rGraphic.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
     158             :         }
     159             :     }
     160             :     else
     161           0 :         mbStatus = false;
     162           2 :     if ( mpWriteAcc )
     163           2 :         Bitmap::ReleaseAccess( mpWriteAcc );
     164           2 :     if ( mpReadAcc )
     165           2 :         Bitmap::ReleaseAccess( mpReadAcc );
     166           2 :     if ( mpMaskWriteAcc )
     167           0 :         Bitmap::ReleaseAccess( mpMaskWriteAcc );
     168           2 :     return mbStatus;
     169             : }
     170             : 
     171             : 
     172             : 
     173           3 : bool PSDReader::ImplReadHeader()
     174             : {
     175             :     sal_uInt16  nCompression;
     176             :     sal_uInt32  nColorLength, nResourceLength, nLayerMaskLength;
     177             : 
     178           3 :     mpFileHeader = new PSDFileHeader;
     179             : 
     180           3 :     m_rPSD.ReadUInt32( mpFileHeader->nSignature ).ReadUInt16( mpFileHeader->nVersion ).ReadUInt32( mpFileHeader->nPad1 ).        ReadUInt16( mpFileHeader->nPad2 ).ReadUInt16( mpFileHeader->nChannels ).ReadUInt32( mpFileHeader->nRows ).            ReadUInt32( mpFileHeader->nColumns ).ReadUInt16( mpFileHeader->nDepth ).ReadUInt16( mpFileHeader->nMode );
     181             : 
     182           3 :     if ( ( mpFileHeader->nSignature != 0x38425053 ) || ( mpFileHeader->nVersion != 1 ) )
     183           0 :         return false;
     184             : 
     185           3 :     if ( mpFileHeader->nRows == 0 || mpFileHeader->nColumns == 0 )
     186           0 :         return false;
     187             : 
     188           3 :     if ( ( mpFileHeader->nRows > 30000 ) || ( mpFileHeader->nColumns > 30000 ) )
     189           0 :         return false;
     190             : 
     191           3 :     sal_uInt16 nDepth = mpFileHeader->nDepth;
     192           3 :     if (!( ( nDepth == 1 ) || ( nDepth == 8 ) || ( nDepth == 16 ) ) )
     193           0 :         return false;
     194             : 
     195           3 :     mnDestBitDepth = ( nDepth == 16 ) ? 8 : nDepth;
     196             : 
     197           3 :     m_rPSD.ReadUInt32( nColorLength );
     198           3 :     if ( mpFileHeader->nMode == PSD_CMYK )
     199             :     {
     200           0 :         switch ( mpFileHeader->nChannels )
     201             :         {
     202             :             case 5 :
     203           0 :                 mbTransparent = true;
     204             :             case 4 :
     205           0 :                 mnDestBitDepth = 24;
     206           0 :             break;
     207             :             default :
     208           0 :                 return false;
     209             :         }
     210             :     }
     211           3 :     else switch ( mpFileHeader->nChannels )
     212             :     {
     213             :         case 2 :
     214           0 :             mbTransparent = true;
     215             :         case 1 :
     216           0 :             break;
     217             :         case 4 :
     218           1 :             mbTransparent = true;
     219             :         case 3 :
     220           3 :             mnDestBitDepth = 24;
     221           3 :             break;
     222             :         default:
     223           0 :             return false;
     224             :     }
     225             : 
     226           3 :     switch ( mpFileHeader->nMode )
     227             :     {
     228             :         case PSD_BITMAP :
     229             :         {
     230           0 :             if ( nColorLength || ( nDepth != 1 ) )
     231           0 :                 return false;
     232             :         }
     233           0 :         break;
     234             : 
     235             :         case PSD_INDEXED :
     236             :         {
     237           0 :             if ( nColorLength != 768 )      // we need the color map
     238           0 :                 return false;
     239           0 :             mpPalette = new sal_uInt8[ 768 ];
     240           0 :             m_rPSD.Read( mpPalette, 768 );
     241             :         }
     242           0 :         break;
     243             : 
     244             :         case PSD_DUOTONE :                  // we'll handle the duotone color like a normal grayscale picture
     245           0 :             m_rPSD.SeekRel( nColorLength );
     246           0 :             nColorLength = 0;
     247             :             /* Fall through */
     248             :         case PSD_GRAYSCALE :
     249             :         {
     250           0 :             if ( nColorLength )
     251           0 :                 return false;
     252           0 :             mpPalette = new sal_uInt8[ 768 ];
     253           0 :             for ( sal_uInt16 i = 0; i < 256; i++ )
     254             :             {
     255           0 :                 mpPalette[ i ] = mpPalette[ i + 256 ] = mpPalette[ i + 512 ] = (sal_uInt8)i;
     256             :             }
     257             :         }
     258           0 :         break;
     259             : 
     260             :         case PSD_CMYK :
     261             :         case PSD_RGB :
     262             :         case PSD_MULTICHANNEL :
     263             :         case PSD_LAB :
     264             :         {
     265           3 :             if ( nColorLength )     // color table is not supported by the other graphic modes
     266           0 :                 return false;
     267             :         }
     268           3 :         break;
     269             : 
     270             :         default:
     271           0 :             return false;
     272             :     }
     273           3 :     m_rPSD.ReadUInt32( nResourceLength );
     274           3 :     sal_uInt32 nLayerPos = m_rPSD.Tell() + nResourceLength;
     275             : 
     276             :     // this is a loop over the resource entries to get the resolution info
     277          48 :     while( m_rPSD.Tell() < nLayerPos )
     278             :     {
     279             :         sal_uInt8 n8;
     280             :         sal_uInt32 nType, nPStringLen, nResEntryLen;
     281             :         sal_uInt16 nUniqueID;
     282             : 
     283          43 :         m_rPSD.ReadUInt32( nType ).ReadUInt16( nUniqueID ).ReadUChar( n8 );
     284          43 :         nPStringLen = n8;
     285          43 :         if ( nType != 0x3842494d )
     286           2 :             break;
     287          42 :         if ( ! ( nPStringLen & 1 ) )
     288          42 :             nPStringLen++;
     289          42 :         m_rPSD.SeekRel( nPStringLen );  // skipping the pstring
     290          42 :         m_rPSD.ReadUInt32( nResEntryLen );
     291          42 :         if ( nResEntryLen & 1 )
     292           8 :             nResEntryLen++;             // the resource entries are padded
     293          42 :         sal_uInt32 nCurrentPos = m_rPSD.Tell();
     294          42 :         if ( ( nResEntryLen + nCurrentPos ) > nLayerPos )   // check if size
     295           0 :             break;                                          // is possible
     296          42 :         switch( nUniqueID )
     297             :         {
     298             :             case 0x3ed :    // UID for the resolution info
     299             :             {
     300             :                 sal_Int16   nUnit;
     301             : 
     302           2 :                 m_rPSD.ReadUInt32( mnXResFixed ).ReadInt16( nUnit ).ReadInt16( nUnit )
     303           4 :                       .ReadUInt32( mnYResFixed ).ReadInt16( nUnit ).ReadInt16( nUnit );
     304             :             }
     305           2 :             break;
     306             :         }
     307          42 :         m_rPSD.Seek( nCurrentPos + nResEntryLen );          // set the stream to the next
     308             :     }                                                       // resource entry
     309           3 :     m_rPSD.Seek( nLayerPos );
     310           3 :     m_rPSD.ReadUInt32( nLayerMaskLength );
     311           3 :     m_rPSD.SeekRel( nLayerMaskLength );
     312             : 
     313           3 :     m_rPSD.ReadUInt16( nCompression );
     314           3 :     if ( nCompression == 0 )
     315             :     {
     316           0 :         mbCompression = false;
     317             :     }
     318           3 :     else if ( nCompression == 1 )
     319             :     {
     320           2 :         m_rPSD.SeekRel( ( mpFileHeader->nRows * mpFileHeader->nChannels ) << 1 );
     321           2 :         mbCompression = true;
     322             :     }
     323             :     else
     324           1 :         return false;
     325             : 
     326           2 :     return true;
     327             : }
     328             : 
     329             : 
     330             : 
     331           2 : bool PSDReader::ImplReadBody()
     332             : {
     333             :     sal_uLong       nX, nY;
     334           2 :     char        nRunCount = 0;
     335           2 :     sal_uInt8       nDat = 0, nDummy, nRed, nGreen, nBlue;
     336           2 :     BitmapColor aBitmapColor;
     337           2 :     nX = nY = 0;
     338             : 
     339           2 :     switch ( mnDestBitDepth )
     340             :     {
     341             :         case 1 :
     342             :         {
     343           0 :             signed char nBitCount = -1;
     344           0 :             while ( nY < mpFileHeader->nRows )
     345             :             {
     346           0 :                 if ( nBitCount == -1 )
     347             :                 {
     348           0 :                     if ( mbCompression )    // else nRunCount = 0 -> so we use only single raw packets
     349           0 :                         m_rPSD.ReadChar( nRunCount );
     350             :                 }
     351           0 :                 if ( nRunCount & 0x80 )     // a run length packet
     352             :                 {
     353           0 :                     for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
     354             :                     {
     355           0 :                         if ( nBitCount == -1 )  // bits left in nDat?
     356             :                         {
     357           0 :                             m_rPSD.ReadUChar( nDat );
     358           0 :                             nDat ^= 0xff;
     359           0 :                             nBitCount = 7;
     360             :                         }
     361           0 :                         mpWriteAcc->SetPixelIndex( nY, nX, nDat >> nBitCount-- );
     362           0 :                         if ( ++nX == mpFileHeader->nColumns )
     363             :                         {
     364           0 :                             nX = 0;
     365           0 :                             nY++;
     366           0 :                             nBitCount = -1;
     367           0 :                             if ( nY == mpFileHeader->nRows )
     368           0 :                                 break;
     369             :                         }
     370             :                     }
     371             :                 }
     372             :                 else                        // a raw packet
     373             :                 {
     374           0 :                     for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
     375             :                     {
     376           0 :                         if ( nBitCount == -1 )  // bits left in nDat ?
     377             :                         {
     378           0 :                             m_rPSD.ReadUChar( nDat );
     379           0 :                             nDat ^= 0xff;
     380           0 :                             nBitCount = 7;
     381             :                         }
     382           0 :                         mpWriteAcc->SetPixelIndex( nY, nX, nDat >> nBitCount-- );
     383           0 :                         if ( ++nX == mpFileHeader->nColumns )
     384             :                         {
     385           0 :                             nX = 0;
     386           0 :                             nY++;
     387           0 :                             nBitCount = -1;
     388           0 :                             if ( nY == mpFileHeader->nRows )
     389           0 :                                 break;
     390             :                         }
     391             :                     }
     392             :                 }
     393             :             }
     394             :         }
     395           0 :         break;
     396             : 
     397             :         case 8 :
     398             :         {
     399           0 :             while ( nY < mpFileHeader->nRows )
     400             :             {
     401           0 :                 if ( mbCompression )        // else nRunCount = 0 -> so we use only single raw packets
     402           0 :                     m_rPSD.ReadChar( nRunCount );
     403             : 
     404           0 :                 if ( nRunCount & 0x80 )     // a run length packet
     405             :                 {
     406           0 :                     m_rPSD.ReadUChar( nDat );
     407           0 :                     if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to be skipped
     408           0 :                         m_rPSD.ReadUChar( nDummy );
     409           0 :                     for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
     410             :                     {
     411           0 :                         mpWriteAcc->SetPixelIndex( nY, nX, nDat );
     412           0 :                         if ( ++nX == mpFileHeader->nColumns )
     413             :                         {
     414           0 :                             nX = 0;
     415           0 :                             nY++;
     416           0 :                             if ( nY == mpFileHeader->nRows )
     417           0 :                                 break;
     418             :                         }
     419             :                     }
     420             :                 }
     421             :                 else                        // a raw packet
     422             :                 {
     423           0 :                     for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
     424             :                     {
     425           0 :                         m_rPSD.ReadUChar( nDat );
     426           0 :                         if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to be skipped
     427           0 :                             m_rPSD.ReadUChar( nDummy );
     428           0 :                         mpWriteAcc->SetPixelIndex( nY, nX, nDat );
     429           0 :                         if ( ++nX == mpFileHeader->nColumns )
     430             :                         {
     431           0 :                             nX = 0;
     432           0 :                             nY++;
     433           0 :                             if ( nY == mpFileHeader->nRows )
     434           0 :                                 break;
     435             :                         }
     436             :                     }
     437             :                 }
     438             :             }
     439             :         }
     440           0 :         break;
     441             : 
     442             :         case 24 :
     443             :         {
     444             : 
     445             :             // the psd format is in plain order (RRRR GGGG BBBB) so we have to set each pixel three times
     446             :             // maybe the format is CCCC MMMM YYYY KKKK
     447             : 
     448       30301 :             while ( nY < mpFileHeader->nRows )
     449             :             {
     450       30297 :                 if ( mbCompression )        // else nRunCount = 0 -> so we use only single raw packets
     451       30297 :                     m_rPSD.ReadChar( nRunCount );
     452             : 
     453       30297 :                 if ( nRunCount & 0x80 )     // a run length packet
     454             :                 {
     455       19723 :                     m_rPSD.ReadUChar( nRed );
     456       19723 :                     if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to be skipped
     457           0 :                         m_rPSD.ReadUChar( nDummy );
     458      731655 :                     for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
     459             :                     {
     460      711934 :                         mpWriteAcc->SetPixel( nY, nX, BitmapColor( nRed, (sal_uInt8)0, (sal_uInt8)0 ) );
     461      711934 :                         if ( ++nX == mpFileHeader->nColumns )
     462             :                         {
     463         753 :                             nX = 0;
     464         753 :                             nY++;
     465         753 :                             if ( nY == mpFileHeader->nRows )
     466           2 :                                 break;
     467             :                         }
     468             :                     }
     469             :                 }
     470             :                 else                        // a raw packet
     471             :                 {
     472       69848 :                     for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
     473             :                     {
     474       59274 :                         m_rPSD.ReadUChar( nRed );
     475       59274 :                         if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to be skipped
     476           0 :                             m_rPSD.ReadUChar( nDummy );
     477       59274 :                         mpWriteAcc->SetPixel( nY, nX, BitmapColor( nRed, (sal_uInt8)0, (sal_uInt8)0 ) );
     478       59274 :                         if ( ++nX == mpFileHeader->nColumns )
     479             :                         {
     480         264 :                             nX = 0;
     481         264 :                             nY++;
     482         264 :                             if ( nY == mpFileHeader->nRows )
     483           0 :                                 break;
     484             :                         }
     485             :                     }
     486             :                 }
     487             :             }
     488           2 :             nY = 0;
     489       30602 :             while ( nY < mpFileHeader->nRows )
     490             :             {
     491       30598 :                 if ( mbCompression )
     492       30598 :                     m_rPSD.ReadChar( nRunCount );
     493       30598 :                 if ( nRunCount & 0x80 )     // a run length packet
     494             :                 {
     495       19879 :                     m_rPSD.ReadUChar( nGreen );
     496       19879 :                     if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to be skipped
     497           0 :                         m_rPSD.ReadUChar( nDummy );
     498      730788 :                     for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
     499             :                     {
     500      710911 :                         aBitmapColor = mpReadAcc->GetPixel( nY, nX );
     501      710911 :                         mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), nGreen, aBitmapColor.GetBlue() ) );
     502      710911 :                         if ( ++nX == mpFileHeader->nColumns )
     503             :                         {
     504         730 :                             nX = 0;
     505         730 :                             nY++;
     506         730 :                             if ( nY == mpFileHeader->nRows )
     507           2 :                                 break;
     508             :                         }
     509             :                     }
     510             :                 }
     511             :                 else                        // a raw packet
     512             :                 {
     513       71016 :                     for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
     514             :                     {
     515       60297 :                         m_rPSD.ReadUChar( nGreen );
     516       60297 :                         if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to be skipped
     517           0 :                             m_rPSD.ReadUChar( nDummy );
     518       60297 :                         aBitmapColor = mpReadAcc->GetPixel( nY, nX );
     519       60297 :                         mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), nGreen, aBitmapColor.GetBlue() ) );
     520       60297 :                         if ( ++nX == mpFileHeader->nColumns )
     521             :                         {
     522         287 :                             nX = 0;
     523         287 :                             nY++;
     524         287 :                             if ( nY == mpFileHeader->nRows )
     525           0 :                                 break;
     526             :                         }
     527             :                     }
     528             :                 }
     529             :             }
     530           2 :             nY = 0;
     531       30706 :             while ( nY < mpFileHeader->nRows )
     532             :             {
     533       30702 :                 if ( mbCompression )
     534       30702 :                     m_rPSD.ReadChar( nRunCount );
     535       30702 :                 if ( nRunCount & 0x80 )     // a run length packet
     536             :                 {
     537       19973 :                     m_rPSD.ReadUChar( nBlue );
     538       19973 :                     if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to be skipped
     539           0 :                         m_rPSD.ReadUChar( nDummy );
     540      731348 :                     for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
     541             :                     {
     542      711377 :                         aBitmapColor = mpReadAcc->GetPixel( nY, nX );
     543      711377 :                         mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), aBitmapColor.GetGreen(), nBlue ) );
     544      711377 :                         if ( ++nX == mpFileHeader->nColumns )
     545             :                         {
     546         744 :                             nX = 0;
     547         744 :                             nY++;
     548         744 :                             if ( nY == mpFileHeader->nRows )
     549           2 :                                 break;
     550             :                         }
     551             :                     }
     552             :                 }
     553             :                 else                        // a raw packet
     554             :                 {
     555       70560 :                     for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
     556             :                     {
     557       59831 :                         m_rPSD.ReadUChar( nBlue );
     558       59831 :                         if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to be skipped
     559           0 :                             m_rPSD.ReadUChar( nDummy );
     560       59831 :                         aBitmapColor = mpReadAcc->GetPixel( nY, nX );
     561       59831 :                         mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), aBitmapColor.GetGreen(), nBlue ) );
     562       59831 :                         if ( ++nX == mpFileHeader->nColumns )
     563             :                         {
     564         273 :                             nX = 0;
     565         273 :                             nY++;
     566         273 :                             if ( nY == mpFileHeader->nRows )
     567           0 :                                 break;
     568             :                         }
     569             :                     }
     570             :                 }
     571             :             }
     572           2 :             if ( mpFileHeader->nMode == PSD_CMYK )
     573             :             {
     574           0 :                 sal_uInt32  nBlack, nBlackMax = 0;
     575           0 :                 boost::scoped_array<sal_uInt8> pBlack(new sal_uInt8[ mpFileHeader->nRows * mpFileHeader->nColumns ]);
     576           0 :                 nY = 0;
     577           0 :                 while ( nY < mpFileHeader->nRows )
     578             :                 {
     579           0 :                     if ( mbCompression )        // else nRunCount = 0 -> so we use only single raw packets
     580           0 :                         m_rPSD.ReadChar( nRunCount );
     581             : 
     582           0 :                     if ( nRunCount & 0x80 )     // a run length packet
     583             :                     {
     584           0 :                         m_rPSD.ReadUChar( nDat );
     585             : 
     586           0 :                         if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to be skipped
     587           0 :                             m_rPSD.ReadUChar( nDummy );
     588             : 
     589           0 :                         for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
     590             :                         {
     591           0 :                             nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetRed() + nDat;
     592           0 :                             if ( nBlack > nBlackMax )
     593           0 :                                 nBlackMax = nBlack;
     594           0 :                             nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetGreen() + nDat;
     595           0 :                             if ( nBlack > nBlackMax )
     596           0 :                                 nBlackMax = nBlack;
     597           0 :                             nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetBlue() + nDat;
     598           0 :                             if ( nBlack > nBlackMax )
     599           0 :                                 nBlackMax = nBlack;
     600           0 :                             pBlack[ nX + nY * mpFileHeader->nColumns ] = nDat ^ 0xff;
     601           0 :                             if ( ++nX == mpFileHeader->nColumns )
     602             :                             {
     603           0 :                                 nX = 0;
     604           0 :                                 nY++;
     605           0 :                             if ( nY == mpFileHeader->nRows )
     606           0 :                                 break;
     607             :                             }
     608             :                         }
     609             :                     }
     610             :                     else                        // a raw packet
     611             :                     {
     612           0 :                         for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
     613             :                         {
     614           0 :                             m_rPSD.ReadUChar( nDat );
     615             : 
     616           0 :                             if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to be skipped
     617           0 :                                 m_rPSD.ReadUChar( nDummy );
     618           0 :                             nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetRed() + nDat;
     619           0 :                             if ( nBlack > nBlackMax )
     620           0 :                                 nBlackMax = nBlack;
     621           0 :                             nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetGreen() + nDat;
     622           0 :                             if ( nBlack > nBlackMax )
     623           0 :                                 nBlackMax = nBlack;
     624           0 :                             nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetBlue() + nDat;
     625           0 :                             if ( nBlack > nBlackMax )
     626           0 :                                 nBlackMax = nBlack;
     627           0 :                             pBlack[ nX + nY * mpFileHeader->nColumns ] = nDat ^ 0xff;
     628           0 :                             if ( ++nX == mpFileHeader->nColumns )
     629             :                             {
     630           0 :                                 nX = 0;
     631           0 :                                 nY++;
     632           0 :                                 if ( nY == mpFileHeader->nRows )
     633           0 :                                     break;
     634             :                             }
     635             :                         }
     636             :                     }
     637             :                 }
     638             : 
     639           0 :                 for ( nY = 0; nY < mpFileHeader->nRows; nY++ )
     640             :                 {
     641           0 :                     for ( nX = 0; nX < mpFileHeader->nColumns; nX++ )
     642             :                     {
     643           0 :                         sal_Int32 nDAT = pBlack[ nX + nY * mpFileHeader->nColumns ] * ( nBlackMax - 256 ) / 0x1ff;
     644             : 
     645           0 :                         aBitmapColor = mpReadAcc->GetPixel( nY, nX );
     646           0 :                         sal_uInt8 cR = (sal_uInt8) MinMax( aBitmapColor.GetRed() - nDAT, 0L, 255L );
     647           0 :                         sal_uInt8 cG = (sal_uInt8) MinMax( aBitmapColor.GetGreen() - nDAT, 0L, 255L );
     648           0 :                         sal_uInt8 cB = (sal_uInt8) MinMax( aBitmapColor.GetBlue() - nDAT, 0L, 255L );
     649           0 :                         mpWriteAcc->SetPixel( nY, nX, BitmapColor( cR, cG, cB ) );
     650             :                     }
     651           0 :                 }
     652             :             }
     653             :         }
     654           2 :         break;
     655             :     }
     656             : 
     657           2 :     if ( mbTransparent )
     658             :     {
     659             :         // the psd is 24 or 8 bit grafix + alphachannel
     660             : 
     661           0 :         nY = nX = 0;
     662           0 :         while ( nY < mpFileHeader->nRows )
     663             :         {
     664           0 :             if ( mbCompression )        // else nRunCount = 0 -> so we use only single raw packets
     665           0 :                 m_rPSD.ReadChar( nRunCount );
     666             : 
     667           0 :             if ( nRunCount & 0x80 )     // a run length packet
     668             :             {
     669           0 :                 m_rPSD.ReadUChar( nDat );
     670           0 :                 if ( nDat )
     671           0 :                     nDat = 0;
     672             :                 else
     673           0 :                     nDat = 1;
     674           0 :                 if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to be skipped
     675           0 :                     m_rPSD.ReadUChar( nDummy );
     676           0 :                 for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
     677             :                 {
     678           0 :                     mpMaskWriteAcc->SetPixelIndex( nY, nX, nDat );
     679           0 :                     if ( ++nX == mpFileHeader->nColumns )
     680             :                     {
     681           0 :                         nX = 0;
     682           0 :                         nY++;
     683           0 :                         if ( nY == mpFileHeader->nRows )
     684           0 :                             break;
     685             :                     }
     686             :                 }
     687             :             }
     688             :             else                        // a raw packet
     689             :             {
     690           0 :                 for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
     691             :                 {
     692           0 :                     m_rPSD.ReadUChar( nDat );
     693           0 :                     if ( nDat )
     694           0 :                         nDat = 0;
     695             :                     else
     696           0 :                         nDat = 1;
     697           0 :                     if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to be skipped
     698           0 :                         m_rPSD.ReadUChar( nDummy );
     699           0 :                     mpMaskWriteAcc->SetPixelIndex( nY, nX, nDat );
     700           0 :                     if ( ++nX == mpFileHeader->nColumns )
     701             :                     {
     702           0 :                         nX = 0;
     703           0 :                         nY++;
     704           0 :                         if ( nY == mpFileHeader->nRows )
     705           0 :                             break;
     706             :                     }
     707             :                 }
     708             :             }
     709             :         }
     710             :     }
     711           2 :     return true;
     712             : }
     713             : 
     714             : //================== GraphicImport - the exported function ================
     715             : 
     716             : // this needs to be kept in sync with
     717             : // ImpFilterLibCacheEntry::GetImportFunction() from
     718             : // vcl/source/filter/graphicfilter.cxx
     719             : #if defined(DISABLE_DYNLOADING)
     720             : #define GraphicImport ipdGraphicImport
     721             : #endif
     722             : 
     723             : extern "C" SAL_DLLPUBLIC_EXPORT bool SAL_CALL
     724           3 : GraphicImport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* )
     725             : {
     726           3 :     PSDReader aPSDReader(rStream);
     727             : 
     728           3 :     return aPSDReader.ReadPSD(rGraphic);
     729             : }
     730             : 
     731             : 
     732             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11