| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_filter.hxx" |
| |
| #include <vcl/graph.hxx> |
| #include <vcl/bmpacc.hxx> |
| #include <svtools/fltcall.hxx> |
| |
| //============================ PSDReader ================================== |
| |
| #define PSD_BITMAP 0 |
| #define PSD_GRAYSCALE 1 |
| #define PSD_INDEXED 2 |
| #define PSD_RGB 3 |
| #define PSD_CMYK 4 |
| #define PSD_MULTICHANNEL 7 |
| #define PSD_DUOTONE 8 |
| #define PSD_LAB 9 |
| |
| typedef struct |
| { |
| sal_uInt32 nSignature; |
| sal_uInt16 nVersion; |
| sal_uInt32 nPad1; |
| sal_uInt16 nPad2; |
| sal_uInt16 nChannels; |
| sal_uInt32 nRows; |
| sal_uInt32 nColumns; |
| sal_uInt16 nDepth; |
| sal_uInt16 nMode; |
| |
| } PSDFileHeader; |
| |
| class PSDReader { |
| |
| private: |
| |
| SvStream* mpPSD; // Die einzulesende PSD-Datei |
| PSDFileHeader* mpFileHeader; |
| |
| sal_uInt32 mnXResFixed; |
| sal_uInt32 mnYResFixed; |
| |
| sal_Bool mbStatus; |
| sal_Bool mbTransparent; |
| |
| Bitmap maBmp; |
| Bitmap maMaskBmp; |
| BitmapReadAccess* mpReadAcc; |
| BitmapWriteAccess* mpWriteAcc; |
| BitmapWriteAccess* mpMaskWriteAcc; |
| sal_uInt16 mnDestBitDepth; |
| sal_Bool mbCompression; // RLE decoding |
| sal_uInt8* mpPalette; |
| |
| sal_Bool ImplReadBody(); |
| sal_Bool ImplReadHeader(); |
| |
| public: |
| PSDReader(); |
| ~PSDReader(); |
| sal_Bool ReadPSD( SvStream & rPSD, Graphic & rGraphic ); |
| }; |
| |
| //=================== Methoden von PSDReader ============================== |
| |
| PSDReader::PSDReader() : |
| mpFileHeader ( NULL ), |
| mnXResFixed ( 0 ), |
| mnYResFixed ( 0 ), |
| mbStatus ( sal_True ), |
| mbTransparent ( sal_False ), |
| mpReadAcc ( NULL ), |
| mpWriteAcc ( NULL ), |
| mpMaskWriteAcc ( NULL ), |
| mpPalette ( NULL ) |
| { |
| } |
| |
| PSDReader::~PSDReader() |
| { |
| delete[] mpPalette; |
| delete mpFileHeader; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| sal_Bool PSDReader::ReadPSD( SvStream & rPSD, Graphic & rGraphic ) |
| { |
| if ( rPSD.GetError() ) |
| return sal_False; |
| |
| mpPSD = &rPSD; |
| mpPSD->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN ); |
| |
| // Kopf einlesen: |
| |
| if ( ImplReadHeader() == sal_False ) |
| return sal_False; |
| |
| Size aBitmapSize( mpFileHeader->nColumns, mpFileHeader->nRows ); |
| maBmp = Bitmap( aBitmapSize, mnDestBitDepth ); |
| if ( ( mpWriteAcc = maBmp.AcquireWriteAccess() ) == NULL ) |
| mbStatus = sal_False; |
| if ( ( mpReadAcc = maBmp.AcquireReadAccess() ) == NULL ) |
| mbStatus = sal_False; |
| if ( mbTransparent && mbStatus ) |
| { |
| maMaskBmp = Bitmap( aBitmapSize, 1 ); |
| if ( ( mpMaskWriteAcc = maMaskBmp.AcquireWriteAccess() ) == NULL ) |
| mbStatus = sal_False; |
| } |
| if ( mpPalette && mbStatus ) |
| { |
| mpWriteAcc->SetPaletteEntryCount( 256 ); |
| for ( sal_uInt16 i = 0; i < 256; i++ ) |
| { |
| mpWriteAcc->SetPaletteColor( i, Color( mpPalette[ i ], mpPalette[ i + 256 ], mpPalette[ i + 512 ] ) ); |
| } |
| } |
| // Bitmap-Daten einlesen |
| if ( mbStatus && ImplReadBody() ) |
| { |
| if ( mbTransparent ) |
| rGraphic = Graphic( BitmapEx( maBmp, maMaskBmp ) ); |
| else |
| rGraphic = maBmp; |
| |
| if ( mnXResFixed && mnYResFixed ) |
| { |
| Point aEmptyPoint; |
| Fraction aFractX( 1, mnXResFixed >> 16 ); |
| Fraction aFractY( 1, mnYResFixed >> 16 ); |
| MapMode aMapMode( MAP_INCH, aEmptyPoint, aFractX, aFractY ); |
| Size aPrefSize = OutputDevice::LogicToLogic( aBitmapSize, aMapMode, MAP_100TH_MM ); |
| rGraphic.SetPrefSize( aPrefSize ); |
| rGraphic.SetPrefMapMode( MapMode( MAP_100TH_MM ) ); |
| } |
| } |
| else |
| mbStatus = sal_False; |
| if ( mpWriteAcc ) |
| maBmp.ReleaseAccess( mpWriteAcc ); |
| if ( mpReadAcc ) |
| maBmp.ReleaseAccess( mpReadAcc ); |
| if ( mpMaskWriteAcc ) |
| maMaskBmp.ReleaseAccess( mpMaskWriteAcc ); |
| return mbStatus; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| sal_Bool PSDReader::ImplReadHeader() |
| { |
| sal_uInt16 nCompression; |
| sal_uInt32 nColorLength, nResourceLength, nLayerMaskLength; |
| |
| mpFileHeader = new PSDFileHeader; |
| |
| if ( !mpFileHeader ) |
| return sal_False; |
| |
| *mpPSD >> mpFileHeader->nSignature >> mpFileHeader->nVersion >> mpFileHeader->nPad1 >> |
| mpFileHeader->nPad2 >> mpFileHeader->nChannels >> mpFileHeader->nRows >> |
| mpFileHeader->nColumns >> mpFileHeader->nDepth >> mpFileHeader->nMode; |
| |
| if ( ( mpFileHeader->nSignature != 0x38425053 ) || ( mpFileHeader->nVersion != 1 ) ) |
| return sal_False; |
| |
| if ( mpFileHeader->nRows == 0 || mpFileHeader->nColumns == 0 ) |
| return sal_False; |
| |
| if ( ( mpFileHeader->nRows > 30000 ) || ( mpFileHeader->nColumns > 30000 ) ) |
| return sal_False; |
| |
| sal_uInt16 nDepth = mpFileHeader->nDepth; |
| if (!( ( nDepth == 1 ) || ( nDepth == 8 ) || ( nDepth == 16 ) ) ) |
| return sal_False; |
| |
| mnDestBitDepth = ( nDepth == 16 ) ? 8 : nDepth; |
| |
| *mpPSD >> nColorLength; |
| if ( mpFileHeader->nMode == PSD_CMYK ) |
| { |
| switch ( mpFileHeader->nChannels ) |
| { |
| case 5 : |
| mbTransparent = sal_True; |
| case 4 : |
| mnDestBitDepth = 24; |
| break; |
| default : |
| return sal_False; |
| } |
| } |
| else switch ( mpFileHeader->nChannels ) |
| { |
| case 2 : |
| mbTransparent = sal_True; |
| case 1 : |
| break; |
| case 4 : |
| mbTransparent = sal_True; |
| case 3 : |
| mnDestBitDepth = 24; |
| break; |
| default: |
| return sal_False; |
| } |
| |
| switch ( mpFileHeader->nMode ) |
| { |
| case PSD_BITMAP : |
| { |
| if ( nColorLength || ( nDepth != 1 ) ) |
| return sal_False; |
| } |
| break; |
| |
| case PSD_INDEXED : |
| { |
| if ( nColorLength != 768 ) // we need the color map |
| return sal_False; |
| mpPalette = new sal_uInt8[ 768 ]; |
| if ( mpPalette == NULL ) |
| return sal_False; |
| mpPSD->Read( mpPalette, 768 ); |
| } |
| break; |
| |
| case PSD_DUOTONE : // we'll handle the doutone color like a normal grayscale picture |
| mpPSD->SeekRel( nColorLength ); |
| nColorLength = 0; |
| case PSD_GRAYSCALE : |
| { |
| if ( nColorLength ) |
| return sal_False; |
| mpPalette = new sal_uInt8[ 768 ]; |
| if ( mpPalette == NULL ) |
| return sal_False; |
| for ( sal_uInt16 i = 0; i < 256; i++ ) |
| { |
| mpPalette[ i ] = mpPalette[ i + 256 ] = mpPalette[ i + 512 ] = (sal_uInt8)i; |
| } |
| } |
| break; |
| |
| case PSD_CMYK : |
| case PSD_RGB : |
| case PSD_MULTICHANNEL : |
| case PSD_LAB : |
| { |
| if ( nColorLength ) // color table is not supported by the other graphic modes |
| return sal_False; |
| } |
| break; |
| |
| default: |
| return sal_False; |
| } |
| *mpPSD >> nResourceLength; |
| sal_uInt32 nLayerPos = mpPSD->Tell() + nResourceLength; |
| |
| // this is a loop over the resource entries to get the resolution info |
| while( mpPSD->Tell() < nLayerPos ) |
| { |
| sal_uInt8 n8; |
| sal_uInt32 nType, nPStringLen, nResEntryLen; |
| sal_uInt16 nUniqueID; |
| |
| *mpPSD >> nType >> nUniqueID >> n8; |
| nPStringLen = n8; |
| if ( nType != 0x3842494d ) |
| break; |
| if ( ! ( nPStringLen & 1 ) ) |
| nPStringLen++; |
| mpPSD->SeekRel( nPStringLen ); // skipping the pstring |
| *mpPSD >> nResEntryLen; |
| if ( nResEntryLen & 1 ) |
| nResEntryLen++; // the resource entries are padded |
| sal_uInt32 nCurrentPos = mpPSD->Tell(); |
| if ( ( nResEntryLen + nCurrentPos ) > nLayerPos ) // check if size |
| break; // is possible |
| switch( nUniqueID ) |
| { |
| case 0x3ed : // UID for the resolution info |
| { |
| sal_Int16 nUnit; |
| |
| *mpPSD >> mnXResFixed >> nUnit >> nUnit |
| >> mnYResFixed >> nUnit >> nUnit; |
| } |
| break; |
| } |
| mpPSD->Seek( nCurrentPos + nResEntryLen ); // set the stream to the next |
| } // resource entry |
| mpPSD->Seek( nLayerPos ); |
| *mpPSD >> nLayerMaskLength; |
| mpPSD->SeekRel( nLayerMaskLength ); |
| |
| *mpPSD >> nCompression; |
| if ( nCompression == 0 ) |
| { |
| mbCompression = sal_False; |
| } |
| else if ( nCompression == 1 ) |
| { |
| mpPSD->SeekRel( ( mpFileHeader->nRows * mpFileHeader->nChannels ) << 1 ); |
| mbCompression = sal_True; |
| } |
| else |
| return sal_False; |
| |
| return sal_True; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| sal_Bool PSDReader::ImplReadBody() |
| { |
| sal_uLong nX, nY; |
| char nRunCount = 0; |
| signed char nBitCount = -1; |
| sal_uInt8 nDat = 0, nDummy, nRed, nGreen, nBlue; |
| BitmapColor aBitmapColor; |
| nX = nY = 0; |
| |
| switch ( mnDestBitDepth ) |
| { |
| case 1 : |
| { |
| while ( nY < mpFileHeader->nRows ) |
| { |
| if ( nBitCount == -1 ) |
| { |
| if ( mbCompression ) // else nRunCount = 0 -> so we use only single raw packets |
| *mpPSD >> nRunCount; |
| } |
| if ( nRunCount & 0x80 ) // a run length packet |
| { |
| if ( nBitCount == -1 ) // bits left in nDat ? |
| { |
| *mpPSD >> nDat; |
| nDat ^= 0xff; |
| nBitCount = 7; |
| } |
| for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ ) |
| { |
| mpWriteAcc->SetPixelIndex( nY, nX, nDat >> nBitCount-- ); |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| nBitCount = -1; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| else // a raw packet |
| { |
| for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) |
| { |
| if ( nBitCount == -1 ) // bits left in nDat ? |
| { |
| *mpPSD >> nDat; |
| nDat ^= 0xff; |
| nBitCount = 7; |
| } |
| mpWriteAcc->SetPixelIndex( nY, nX, nDat >> nBitCount-- ); |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| nBitCount = -1; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| } |
| } |
| break; |
| |
| case 8 : |
| { |
| while ( nY < mpFileHeader->nRows ) |
| { |
| if ( mbCompression ) // else nRunCount = 0 -> so we use only single raw packets |
| *mpPSD >> nRunCount; |
| |
| if ( nRunCount & 0x80 ) // a run length packet |
| { |
| *mpPSD >> nDat; |
| if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped |
| *mpPSD >> nDummy; |
| for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ ) |
| { |
| mpWriteAcc->SetPixelIndex( nY, nX, nDat ); |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| else // a raw packet |
| { |
| for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) |
| { |
| *mpPSD >> nDat; |
| if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped |
| *mpPSD >> nDummy; |
| mpWriteAcc->SetPixelIndex( nY, nX, nDat ); |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| } |
| } |
| break; |
| |
| case 24 : |
| { |
| |
| // the psd format is in plain order (RRRR GGGG BBBB) so we have to set each pixel three times |
| // maybe the format is CCCC MMMM YYYY KKKK |
| |
| while ( nY < mpFileHeader->nRows ) |
| { |
| if ( mbCompression ) // else nRunCount = 0 -> so we use only single raw packets |
| *mpPSD >> nRunCount; |
| |
| if ( nRunCount & 0x80 ) // a run length packet |
| { |
| *mpPSD >> nRed; |
| if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped |
| *mpPSD >> nDummy; |
| for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ ) |
| { |
| mpWriteAcc->SetPixel( nY, nX, BitmapColor( nRed, (sal_uInt8)0, (sal_uInt8)0 ) ); |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| else // a raw packet |
| { |
| for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) |
| { |
| *mpPSD >> nRed; |
| if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped |
| *mpPSD >> nDummy; |
| mpWriteAcc->SetPixel( nY, nX, BitmapColor( nRed, (sal_uInt8)0, (sal_uInt8)0 ) ); |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| } |
| nY = 0; |
| while ( nY < mpFileHeader->nRows ) |
| { |
| if ( mbCompression ) |
| *mpPSD >> nRunCount; |
| if ( nRunCount & 0x80 ) // a run length packet |
| { |
| *mpPSD >> nGreen; |
| if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped |
| *mpPSD >> nDummy; |
| for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ ) |
| { |
| aBitmapColor = mpReadAcc->GetPixel( nY, nX ); |
| mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), nGreen, aBitmapColor.GetBlue() ) ); |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| else // a raw packet |
| { |
| for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) |
| { |
| *mpPSD >> nGreen; |
| if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped |
| *mpPSD >> nDummy; |
| aBitmapColor = mpReadAcc->GetPixel( nY, nX ); |
| mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), nGreen, aBitmapColor.GetBlue() ) ); |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| } |
| nY = 0; |
| while ( nY < mpFileHeader->nRows ) |
| { |
| if ( mbCompression ) |
| *mpPSD >> nRunCount; |
| if ( nRunCount & 0x80 ) // a run length packet |
| { |
| *mpPSD >> nBlue; |
| if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped |
| *mpPSD >> nDummy; |
| for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ ) |
| { |
| aBitmapColor = mpReadAcc->GetPixel( nY, nX ); |
| mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), aBitmapColor.GetGreen(), nBlue ) ); |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| else // a raw packet |
| { |
| for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) |
| { |
| *mpPSD >> nBlue; |
| if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped |
| *mpPSD >> nDummy; |
| aBitmapColor = mpReadAcc->GetPixel( nY, nX ); |
| mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), aBitmapColor.GetGreen(), nBlue ) ); |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| } |
| if ( mpFileHeader->nMode == PSD_CMYK ) |
| { |
| sal_uInt32 nBlack, nBlackMax = 0; |
| sal_uInt8* pBlack = new sal_uInt8[ mpFileHeader->nRows * mpFileHeader->nColumns ]; |
| nY = 0; |
| while ( nY < mpFileHeader->nRows ) |
| { |
| if ( mbCompression ) // else nRunCount = 0 -> so we use only single raw packets |
| *mpPSD >> nRunCount; |
| |
| if ( nRunCount & 0x80 ) // a run length packet |
| { |
| *mpPSD >> nDat; |
| |
| if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped |
| *mpPSD >> nDummy; |
| |
| for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ ) |
| { |
| nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetRed() + nDat; |
| if ( nBlack > nBlackMax ) |
| nBlackMax = nBlack; |
| nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetGreen() + nDat; |
| if ( nBlack > nBlackMax ) |
| nBlackMax = nBlack; |
| nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetBlue() + nDat; |
| if ( nBlack > nBlackMax ) |
| nBlackMax = nBlack; |
| pBlack[ nX + nY * mpFileHeader->nColumns ] = nDat ^ 0xff; |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| else // a raw packet |
| { |
| for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) |
| { |
| *mpPSD >> nDat; |
| |
| if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped |
| *mpPSD >> nDummy; |
| nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetRed() + nDat; |
| if ( nBlack > nBlackMax ) |
| nBlackMax = nBlack; |
| nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetGreen() + nDat; |
| if ( nBlack > nBlackMax ) |
| nBlackMax = nBlack; |
| nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetBlue() + nDat; |
| if ( nBlack > nBlackMax ) |
| nBlackMax = nBlack; |
| pBlack[ nX + nY * mpFileHeader->nColumns ] = nDat ^ 0xff; |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| } |
| |
| for ( nY = 0; nY < mpFileHeader->nRows; nY++ ) |
| { |
| for ( nX = 0; nX < mpFileHeader->nColumns; nX++ ) |
| { |
| sal_Int32 nDAT = pBlack[ nX + nY * mpFileHeader->nColumns ] * ( nBlackMax - 256 ) / 0x1ff; |
| |
| aBitmapColor = mpReadAcc->GetPixel( nY, nX ); |
| sal_uInt8 cR = (sal_uInt8) MinMax( aBitmapColor.GetRed() - nDAT, 0L, 255L ); |
| sal_uInt8 cG = (sal_uInt8) MinMax( aBitmapColor.GetGreen() - nDAT, 0L, 255L ); |
| sal_uInt8 cB = (sal_uInt8) MinMax( aBitmapColor.GetBlue() - nDAT, 0L, 255L ); |
| mpWriteAcc->SetPixel( nY, nX, BitmapColor( cR, cG, cB ) ); |
| } |
| } |
| delete[] pBlack; |
| } |
| } |
| break; |
| } |
| |
| if ( mbTransparent ) |
| { |
| // the psd is 24 or 8 bit grafix + alphachannel |
| |
| nY = nX = 0; |
| while ( nY < mpFileHeader->nRows ) |
| { |
| if ( mbCompression ) // else nRunCount = 0 -> so we use only single raw packets |
| *mpPSD >> nRunCount; |
| |
| if ( nRunCount & 0x80 ) // a run length packet |
| { |
| *mpPSD >> nDat; |
| if ( nDat ) |
| nDat = 0; |
| else |
| nDat = 1; |
| if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped |
| *mpPSD >> nDummy; |
| for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ ) |
| { |
| mpMaskWriteAcc->SetPixelIndex( nY, nX, nDat ); |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| else // a raw packet |
| { |
| for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) |
| { |
| *mpPSD >> nDat; |
| if ( nDat ) |
| nDat = 0; |
| else |
| nDat = 1; |
| if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped |
| *mpPSD >> nDummy; |
| mpMaskWriteAcc->SetPixelIndex( nY, nX, nDat ); |
| if ( ++nX == mpFileHeader->nColumns ) |
| { |
| nX = 0; |
| nY++; |
| if ( nY == mpFileHeader->nRows ) |
| break; |
| } |
| } |
| } |
| } |
| } |
| return sal_True; |
| } |
| |
| //================== GraphicImport - die exportierte Funktion ================ |
| |
| extern "C" sal_Bool __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, sal_Bool ) |
| { |
| PSDReader aPSDReader; |
| |
| return aPSDReader.ReadPSD( rStream, rGraphic ); |
| } |
| |