| /************************************************************** |
| * |
| * 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 "rtl/alloc.h" |
| #include <vcl/graph.hxx> |
| #include <vcl/bmpacc.hxx> |
| #include <vcl/svapp.hxx> |
| #include <svtools/fltcall.hxx> |
| #include <svl/solar.hrc> |
| #include <svtools/FilterConfigItem.hxx> |
| |
| //============================ PCDReader ================================== |
| |
| // Diese Aufloesungen sind in einer PCD-Datei enthalten: |
| enum PCDResolution { |
| PCDRES_BASE16, // 192 x 128 |
| PCDRES_BASE4, // 384 x 256 |
| PCDRES_BASE, // 768 x 512 |
| // Die folgenden sind komprimiert und koennen |
| // von uns NICHT gelesen werden: |
| PCDRES_4BASE, // 1536 x 1024 |
| PCDRES_16BASE // 3072 x 3072 |
| }; |
| |
| class PCDReader { |
| |
| private: |
| |
| sal_Bool bStatus; |
| |
| sal_uLong nLastPercent; |
| |
| SvStream* pPCD; |
| BitmapWriteAccess* mpAcc; |
| |
| sal_uInt8 nOrientation; // Ausrichtung des Bildes in der PCD-Datei: |
| // 0 - Turmspitze zeigt nach oben |
| // 1 - Turmspitze zeigt nach rechts |
| // 2 - Turmspitze zeigt nach unten |
| // 3 - Turmspitze zeigt nach links |
| |
| PCDResolution eResolution; // Welche Aufloesung wir haben wollen |
| |
| sal_uLong nWidth; // Breite des PCD-Bildes |
| sal_uLong nHeight; // Hoehe des PCD-Bildes |
| sal_uLong nImagePos; // Position des Bildes in der PCD-Datei |
| |
| // Temporare BLue-Green-Red-Bitmap |
| sal_uLong nBMPWidth; |
| sal_uLong nBMPHeight; |
| |
| void MayCallback(sal_uLong nPercent); |
| |
| void CheckPCDImagePacFile(); |
| // Prueft, ob es eine Photo-CD-Datei mit 'Image Pac' ist. |
| |
| void ReadOrientation(); |
| // Liest die Ausrichtung und setzt nOrientation |
| |
| void ReadImage(sal_uLong nMinPercent, sal_uLong nMaxPercent); |
| |
| public: |
| |
| PCDReader() {} |
| ~PCDReader() {} |
| |
| sal_Bool ReadPCD( SvStream & rPCD, Graphic & rGraphic, FilterConfigItem* pConfigItem ); |
| }; |
| |
| //=================== Methoden von PCDReader ============================== |
| |
| sal_Bool PCDReader::ReadPCD( SvStream & rPCD, Graphic & rGraphic, FilterConfigItem* pConfigItem ) |
| { |
| Bitmap aBmp; |
| |
| bStatus = sal_True; |
| nLastPercent = 0; |
| pPCD = &rPCD; |
| |
| MayCallback( 0 ); |
| |
| // Ist es eine PCD-Datei mit Bild ? ( setzt bStatus == sal_False, wenn nicht ): |
| CheckPCDImagePacFile(); |
| |
| // Orientierung des Bildes einlesen: |
| ReadOrientation(); |
| |
| // Welche Aufloesung wollen wir ?: |
| eResolution = PCDRES_BASE; |
| if ( pConfigItem ) |
| { |
| sal_Int32 nResolution = pConfigItem->ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Resolution" ) ), 2 ); |
| if ( nResolution == 1 ) |
| eResolution = PCDRES_BASE4; |
| else if ( nResolution == 0 ) |
| eResolution = PCDRES_BASE16; |
| } |
| // Groesse und Position (Position in PCD-Datei) des Bildes bestimmen: |
| switch (eResolution) |
| { |
| case PCDRES_BASE16 : |
| nWidth = 192; |
| nHeight = 128; |
| nImagePos = 8192; |
| break; |
| |
| case PCDRES_BASE4 : |
| nWidth = 384; |
| nHeight = 256; |
| nImagePos = 47104; |
| break; |
| |
| case PCDRES_BASE : |
| nWidth = 768; |
| nHeight = 512; |
| nImagePos = 196608; |
| break; |
| |
| default: |
| bStatus = sal_False; |
| } |
| if ( bStatus ) |
| { |
| if ( ( nOrientation & 0x01 ) == 0 ) |
| { |
| nBMPWidth = nWidth; |
| nBMPHeight = nHeight; |
| } |
| else |
| { |
| nBMPWidth = nHeight; |
| nBMPHeight = nWidth; |
| } |
| aBmp = Bitmap( Size( nBMPWidth, nBMPHeight ), 24 ); |
| mpAcc = aBmp.AcquireWriteAccess(); |
| if ( !mpAcc ) |
| return sal_False; |
| |
| ReadImage( 5 ,65 ); |
| |
| aBmp.ReleaseAccess( mpAcc ), mpAcc = NULL; |
| rGraphic = aBmp; |
| } |
| return bStatus; |
| } |
| |
| // ------------------------------------------------------------------------------------------- |
| |
| void PCDReader::MayCallback(sal_uLong /*nPercent*/) |
| { |
| /* |
| if ( nPercent >= nLastPercent + 3 ) |
| { |
| nLastPercent=nPercent; |
| if ( pCallback != NULL && nPercent <= 100 && bStatus == sal_True ) |
| { |
| if ( ( (*pCallback)( pCallerData, (sal_uInt16)nPercent ) ) == sal_True ) |
| bStatus = sal_False; |
| } |
| } |
| */ |
| } |
| |
| // ------------------------------------------------------------------------------------------- |
| |
| void PCDReader::CheckPCDImagePacFile() |
| { |
| char Buf[ 8 ]; |
| |
| pPCD->Seek( 2048 ); |
| pPCD->Read( Buf, 7 ); |
| Buf[ 7 ] = 0; |
| if ( ByteString( Buf ).CompareTo( "PCD_IPI" ) != COMPARE_EQUAL ) |
| bStatus = sal_False; |
| } |
| |
| // ------------------------------------------------------------------------------------------- |
| |
| void PCDReader::ReadOrientation() |
| { |
| if ( bStatus == sal_False ) |
| return; |
| pPCD->Seek( 194635 ); |
| *pPCD >> nOrientation; |
| nOrientation &= 0x03; |
| } |
| |
| // ------------------------------------------------------------------------------------------- |
| |
| void PCDReader::ReadImage(sal_uLong nMinPercent, sal_uLong nMaxPercent) |
| { |
| sal_uLong nx,ny,nW2,nH2,nYPair,ndy,nXPair; |
| long nL,nCb,nCr,nRed,nGreen,nBlue; |
| sal_uInt8 * pt; |
| sal_uInt8 * pL0; // Luminanz fuer jeden Pixel der 1. Zeile des aktuellen Zeilen-Paars |
| sal_uInt8 * pL1; // Luminanz fuer jeden Pixel der 2. Zeile des aktuellen Zeilen-Paars |
| sal_uInt8 * pCb; // Blau-Chrominanz fuer je 2x2 Pixel des aktuellen Zeilen-Paars |
| sal_uInt8 * pCr; // Rot-Chrominanz fuer je 2x2 Pixel des aktuellen Zeilen-Paars |
| sal_uInt8 * pL0N, * pL1N, * pCbN, * pCrN; // wie oben, nur fuer das naechste Zeilen-Paar |
| |
| if ( bStatus == sal_False ) |
| return; |
| |
| nW2=nWidth>>1; |
| nH2=nHeight>>1; |
| |
| pL0 =(sal_uInt8*)rtl_allocateMemory( nWidth ); |
| pL1 =(sal_uInt8*)rtl_allocateMemory( nWidth ); |
| pCb =(sal_uInt8*)rtl_allocateMemory( nW2+1 ); |
| pCr =(sal_uInt8*)rtl_allocateMemory( nW2+1 ); |
| pL0N=(sal_uInt8*)rtl_allocateMemory( nWidth ); |
| pL1N=(sal_uInt8*)rtl_allocateMemory( nWidth ); |
| pCbN=(sal_uInt8*)rtl_allocateMemory( nW2+1 ); |
| pCrN=(sal_uInt8*)rtl_allocateMemory( nW2+1 ); |
| |
| if ( pL0 == NULL || pL1 == NULL || pCb == NULL || pCr == NULL || |
| pL0N == NULL || pL1N == NULL || pCbN == NULL || pCrN == NULL) |
| { |
| rtl_freeMemory((void*)pL0 ); |
| rtl_freeMemory((void*)pL1 ); |
| rtl_freeMemory((void*)pCb ); |
| rtl_freeMemory((void*)pCr ); |
| rtl_freeMemory((void*)pL0N); |
| rtl_freeMemory((void*)pL1N); |
| rtl_freeMemory((void*)pCbN); |
| rtl_freeMemory((void*)pCrN); |
| bStatus = sal_False; |
| return; |
| } |
| |
| pPCD->Seek( nImagePos ); |
| |
| // naechstes Zeilen-Paar := erstes Zeile-Paar: |
| pPCD->Read( pL0N, nWidth ); |
| pPCD->Read( pL1N, nWidth ); |
| pPCD->Read( pCbN, nW2 ); |
| pPCD->Read( pCrN, nW2 ); |
| pCbN[ nW2 ] = pCbN[ nW2 - 1 ]; |
| pCrN[ nW2 ] = pCrN[ nW2 - 1 ]; |
| |
| for ( nYPair = 0; nYPair < nH2; nYPair++ ) |
| { |
| // aktuelles Zeilen-Paar := naechstes Zeilen-Paar |
| pt=pL0; pL0=pL0N; pL0N=pt; |
| pt=pL1; pL1=pL1N; pL1N=pt; |
| pt=pCb; pCb=pCbN; pCbN=pt; |
| pt=pCr; pCr=pCrN; pCrN=pt; |
| |
| // naechstes Zeilen-Paar holen: |
| if ( nYPair < nH2 - 1 ) |
| { |
| pPCD->Read( pL0N, nWidth ); |
| pPCD->Read( pL1N, nWidth ); |
| pPCD->Read( pCbN, nW2 ); |
| pPCD->Read( pCrN, nW2 ); |
| pCbN[nW2]=pCbN[ nW2 - 1 ]; |
| pCrN[nW2]=pCrN[ nW2 - 1 ]; |
| } |
| else |
| { |
| for ( nXPair = 0; nXPair < nW2; nXPair++ ) |
| { |
| pCbN[ nXPair ] = pCb[ nXPair ]; |
| pCrN[ nXPair ] = pCr[ nXPair ]; |
| } |
| } |
| |
| // Schleife uber die beiden Zeilen des Zeilen-Paars: |
| for ( ndy = 0; ndy < 2; ndy++ ) |
| { |
| ny = ( nYPair << 1 ) + ndy; |
| |
| // Schleife ueber X: |
| for ( nx = 0; nx < nWidth; nx++ ) |
| { |
| // nL,nCb,nCr fuer den Pixel nx,ny holen/berechenen: |
| nXPair = nx >> 1; |
| if ( ndy == 0 ) |
| { |
| nL = (long)pL0[ nx ]; |
| if (( nx & 1 ) == 0 ) |
| { |
| nCb = (long)pCb[ nXPair ]; |
| nCr = (long)pCr[ nXPair ]; |
| } |
| else |
| { |
| nCb = ( ( (long)pCb[ nXPair ] ) + ( (long)pCb[ nXPair + 1 ] ) ) >> 1; |
| nCr = ( ( (long)pCr[ nXPair ] ) + ( (long)pCr[ nXPair + 1 ] ) ) >> 1; |
| } |
| } |
| else { |
| nL = pL1[ nx ]; |
| if ( ( nx & 1 ) == 0 ) |
| { |
| nCb = ( ( (long)pCb[ nXPair ] ) + ( (long)pCbN[ nXPair ] ) ) >> 1; |
| nCr = ( ( (long)pCr[ nXPair ] ) + ( (long)pCrN[ nXPair ] ) ) >> 1; |
| } |
| else |
| { |
| nCb = ( ( (long)pCb[ nXPair ] ) + ( (long)pCb[ nXPair + 1 ] ) + |
| ( (long)pCbN[ nXPair ] ) + ( (long)pCbN[ nXPair + 1 ] ) ) >> 2; |
| nCr = ( ( (long)pCr[ nXPair ] ) + ( (long)pCr[ nXPair + 1] ) + |
| ( (long)pCrN[ nXPair ] ) + ( (long)pCrN[ nXPair + 1 ] ) ) >> 2; |
| } |
| } |
| // Umwandlung von nL,nCb,nCr in nRed,nGreen,nBlue: |
| nL *= 89024L; |
| nCb -= 156; |
| nCr -= 137; |
| nRed = ( nL + nCr * 119374L + 0x8000 ) >> 16; |
| if ( nRed < 0 ) |
| nRed = 0; |
| if ( nRed > 255) |
| nRed = 255; |
| nGreen = ( nL - nCb * 28198L - nCr * 60761L + 0x8000 ) >> 16; |
| if ( nGreen < 0 ) |
| nGreen = 0; |
| if ( nGreen > 255 ) |
| nGreen = 255; |
| nBlue = ( nL + nCb * 145352L + 0x8000 ) >> 16; |
| if ( nBlue < 0 ) |
| nBlue = 0; |
| if ( nBlue > 255 ) |
| nBlue = 255; |
| |
| // Farbwert in pBMPMap eintragen: |
| if ( nOrientation < 2 ) |
| { |
| if ( nOrientation == 0 ) |
| mpAcc->SetPixel( ny, nx, BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) ); |
| else |
| mpAcc->SetPixel( nWidth - 1 - nx, ny, BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) ); |
| } |
| else |
| { |
| if ( nOrientation == 2 ) |
| mpAcc->SetPixel( nHeight - 1 - ny, ( nWidth - 1 - nx ), BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) ); |
| else |
| mpAcc->SetPixel( nx, ( nHeight - 1 - ny ), BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) ); |
| } |
| } |
| } |
| |
| if ( pPCD->GetError() ) |
| bStatus = sal_False; |
| MayCallback( nMinPercent + ( nMaxPercent - nMinPercent ) * nYPair / nH2 ); |
| if ( bStatus == sal_False ) |
| break; |
| } |
| rtl_freeMemory((void*)pL0 ); |
| rtl_freeMemory((void*)pL1 ); |
| rtl_freeMemory((void*)pCb ); |
| rtl_freeMemory((void*)pCr ); |
| rtl_freeMemory((void*)pL0N); |
| rtl_freeMemory((void*)pL1N); |
| rtl_freeMemory((void*)pCbN); |
| rtl_freeMemory((void*)pCrN); |
| } |
| |
| //================== GraphicImport - die exportierte Funktion ================ |
| |
| extern "C" sal_Bool __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pConfigItem, sal_Bool ) |
| { |
| PCDReader aPCDReader; |
| return aPCDReader.ReadPCD( rStream, rGraphic, pConfigItem ); |
| } |
| |