xref: /AOO41X/main/filter/source/graphicfilter/ipcd/ipcd.cxx (revision 0af288bd36294aa09e93d369656aab1681e705d2)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 
27 #include "rtl/alloc.h"
28 #include <vcl/graph.hxx>
29 #include <vcl/bmpacc.hxx>
30 #include <vcl/svapp.hxx>
31 #include <svtools/fltcall.hxx>
32 #include <svl/solar.hrc>
33 #include <svtools/FilterConfigItem.hxx>
34 
35 //============================ PCDReader ==================================
36 
37 // Diese Aufloesungen sind in einer PCD-Datei enthalten:
38 enum PCDResolution {
39     PCDRES_BASE16,  //  192 x  128
40     PCDRES_BASE4,   //  384 x  256
41     PCDRES_BASE,    //  768 x  512
42     // Die folgenden sind komprimiert und koennen
43     // von uns NICHT gelesen werden:
44     PCDRES_4BASE,   // 1536 x 1024
45     PCDRES_16BASE   // 3072 x 3072
46 };
47 
48 class PCDReader {
49 
50 private:
51 
52     sal_Bool bStatus;
53 
54     sal_uLong               nLastPercent;
55 
56     SvStream*           pPCD;
57     BitmapWriteAccess*  mpAcc;
58 
59     sal_uInt8               nOrientation;   // Ausrichtung des Bildes in der PCD-Datei:
60                                         // 0 - Turmspitze zeigt nach oben
61                                         // 1 - Turmspitze zeigt nach rechts
62                                         // 2 - Turmspitze zeigt nach unten
63                                         // 3 - Turmspitze zeigt nach links
64 
65     PCDResolution       eResolution;    // Welche Aufloesung wir haben wollen
66 
67     sal_uLong               nWidth;         // Breite des PCD-Bildes
68     sal_uLong               nHeight;        // Hoehe des PCD-Bildes
69     sal_uLong               nImagePos;      // Position des Bildes in der PCD-Datei
70 
71     // Temporare BLue-Green-Red-Bitmap
72     sal_uLong               nBMPWidth;
73     sal_uLong               nBMPHeight;
74 
75     void    MayCallback(sal_uLong nPercent);
76 
77     void    CheckPCDImagePacFile();
78         // Prueft, ob es eine Photo-CD-Datei mit 'Image Pac' ist.
79 
80     void    ReadOrientation();
81         // Liest die Ausrichtung und setzt nOrientation
82 
83     void    ReadImage(sal_uLong nMinPercent, sal_uLong nMaxPercent);
84 
85 public:
86 
PCDReader()87     PCDReader() {}
~PCDReader()88     ~PCDReader() {}
89 
90     sal_Bool ReadPCD( SvStream & rPCD, Graphic & rGraphic, FilterConfigItem* pConfigItem );
91 };
92 
93 //=================== Methoden von PCDReader ==============================
94 
ReadPCD(SvStream & rPCD,Graphic & rGraphic,FilterConfigItem * pConfigItem)95 sal_Bool PCDReader::ReadPCD( SvStream & rPCD, Graphic & rGraphic, FilterConfigItem* pConfigItem )
96 {
97     Bitmap       aBmp;
98 
99     bStatus      = sal_True;
100     nLastPercent = 0;
101     pPCD         = &rPCD;
102 
103     MayCallback( 0 );
104 
105     // Ist es eine PCD-Datei mit Bild ? ( setzt bStatus == sal_False, wenn nicht ):
106     CheckPCDImagePacFile();
107 
108     // Orientierung des Bildes einlesen:
109     ReadOrientation();
110 
111     // Welche Aufloesung wollen wir ?:
112     eResolution = PCDRES_BASE;
113     if ( pConfigItem )
114     {
115         sal_Int32 nResolution = pConfigItem->ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Resolution" ) ), 2 );
116         if ( nResolution == 1 )
117             eResolution = PCDRES_BASE4;
118         else if ( nResolution == 0 )
119             eResolution = PCDRES_BASE16;
120     }
121     // Groesse und Position (Position in PCD-Datei) des Bildes bestimmen:
122     switch (eResolution)
123     {
124         case PCDRES_BASE16 :
125             nWidth = 192;
126             nHeight = 128;
127             nImagePos = 8192;
128             break;
129 
130         case PCDRES_BASE4 :
131             nWidth = 384;
132             nHeight = 256;
133             nImagePos = 47104;
134             break;
135 
136         case PCDRES_BASE :
137             nWidth = 768;
138             nHeight = 512;
139             nImagePos = 196608;
140             break;
141 
142         default:
143             bStatus = sal_False;
144     }
145     if ( bStatus )
146     {
147         if ( ( nOrientation & 0x01 ) == 0 )
148         {
149             nBMPWidth = nWidth;
150             nBMPHeight = nHeight;
151         }
152         else
153         {
154             nBMPWidth = nHeight;
155             nBMPHeight = nWidth;
156         }
157         aBmp = Bitmap( Size( nBMPWidth, nBMPHeight ), 24 );
158         mpAcc = aBmp.AcquireWriteAccess();
159         if ( !mpAcc )
160             return sal_False;
161 
162         ReadImage( 5 ,65 );
163 
164         aBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
165         rGraphic = aBmp;
166     }
167     return bStatus;
168 }
169 
170 // -------------------------------------------------------------------------------------------
171 
MayCallback(sal_uLong)172 void PCDReader::MayCallback(sal_uLong /*nPercent*/)
173 {
174 /*
175     if ( nPercent >= nLastPercent + 3 )
176     {
177         nLastPercent=nPercent;
178         if ( pCallback != NULL && nPercent <= 100 && bStatus == sal_True )
179         {
180             if ( ( (*pCallback)( pCallerData, (sal_uInt16)nPercent ) ) == sal_True )
181                 bStatus = sal_False;
182         }
183     }
184 */
185 }
186 
187 // -------------------------------------------------------------------------------------------
188 
CheckPCDImagePacFile()189 void PCDReader::CheckPCDImagePacFile()
190 {
191     char Buf[ 8 ];
192 
193     pPCD->Seek( 2048 );
194     pPCD->Read( Buf, 7 );
195     Buf[ 7 ] = 0;
196     if ( ByteString( Buf ).CompareTo( "PCD_IPI" ) != COMPARE_EQUAL )
197         bStatus = sal_False;
198 }
199 
200 // -------------------------------------------------------------------------------------------
201 
ReadOrientation()202 void PCDReader::ReadOrientation()
203 {
204     if ( bStatus == sal_False )
205         return;
206     pPCD->Seek( 194635 );
207     *pPCD >> nOrientation;
208     nOrientation &= 0x03;
209 }
210 
211 // -------------------------------------------------------------------------------------------
212 
ReadImage(sal_uLong nMinPercent,sal_uLong nMaxPercent)213 void PCDReader::ReadImage(sal_uLong nMinPercent, sal_uLong nMaxPercent)
214 {
215     sal_uLong  nx,ny,nW2,nH2,nYPair,ndy,nXPair;
216     long   nL,nCb,nCr,nRed,nGreen,nBlue;
217     sal_uInt8 * pt;
218     sal_uInt8 * pL0; // Luminanz fuer jeden Pixel der 1. Zeile des aktuellen Zeilen-Paars
219     sal_uInt8 * pL1; // Luminanz fuer jeden Pixel der 2. Zeile des aktuellen Zeilen-Paars
220     sal_uInt8 * pCb; // Blau-Chrominanz fuer je 2x2 Pixel des aktuellen Zeilen-Paars
221     sal_uInt8 * pCr; // Rot-Chrominanz fuer je 2x2 Pixel des aktuellen Zeilen-Paars
222     sal_uInt8 * pL0N, * pL1N, * pCbN, * pCrN; // wie oben, nur fuer das naechste Zeilen-Paar
223 
224     if ( bStatus == sal_False )
225         return;
226 
227     nW2=nWidth>>1;
228     nH2=nHeight>>1;
229 
230     pL0 =(sal_uInt8*)rtl_allocateMemory( nWidth );
231     pL1 =(sal_uInt8*)rtl_allocateMemory( nWidth );
232     pCb =(sal_uInt8*)rtl_allocateMemory( nW2+1 );
233     pCr =(sal_uInt8*)rtl_allocateMemory( nW2+1 );
234     pL0N=(sal_uInt8*)rtl_allocateMemory( nWidth );
235     pL1N=(sal_uInt8*)rtl_allocateMemory( nWidth );
236     pCbN=(sal_uInt8*)rtl_allocateMemory( nW2+1 );
237     pCrN=(sal_uInt8*)rtl_allocateMemory( nW2+1 );
238 
239     if ( pL0 == NULL || pL1 == NULL || pCb == NULL || pCr == NULL ||
240         pL0N == NULL || pL1N == NULL || pCbN == NULL || pCrN == NULL)
241     {
242         rtl_freeMemory((void*)pL0 );
243         rtl_freeMemory((void*)pL1 );
244         rtl_freeMemory((void*)pCb );
245         rtl_freeMemory((void*)pCr );
246         rtl_freeMemory((void*)pL0N);
247         rtl_freeMemory((void*)pL1N);
248         rtl_freeMemory((void*)pCbN);
249         rtl_freeMemory((void*)pCrN);
250         bStatus = sal_False;
251         return;
252     }
253 
254     pPCD->Seek( nImagePos );
255 
256     // naechstes Zeilen-Paar := erstes Zeile-Paar:
257     pPCD->Read( pL0N, nWidth );
258     pPCD->Read( pL1N, nWidth );
259     pPCD->Read( pCbN, nW2 );
260     pPCD->Read( pCrN, nW2 );
261     pCbN[ nW2 ] = pCbN[ nW2 - 1 ];
262     pCrN[ nW2 ] = pCrN[ nW2 - 1 ];
263 
264     for ( nYPair = 0; nYPair < nH2; nYPair++ )
265     {
266         // aktuelles Zeilen-Paar := naechstes Zeilen-Paar
267         pt=pL0; pL0=pL0N; pL0N=pt;
268         pt=pL1; pL1=pL1N; pL1N=pt;
269         pt=pCb; pCb=pCbN; pCbN=pt;
270         pt=pCr; pCr=pCrN; pCrN=pt;
271 
272         // naechstes Zeilen-Paar holen:
273         if ( nYPair < nH2 - 1 )
274         {
275             pPCD->Read( pL0N, nWidth );
276             pPCD->Read( pL1N, nWidth );
277             pPCD->Read( pCbN, nW2 );
278             pPCD->Read( pCrN, nW2 );
279             pCbN[nW2]=pCbN[ nW2 - 1 ];
280             pCrN[nW2]=pCrN[ nW2 - 1 ];
281         }
282         else
283         {
284             for ( nXPair = 0; nXPair < nW2; nXPair++ )
285             {
286                 pCbN[ nXPair ] = pCb[ nXPair ];
287                 pCrN[ nXPair ] = pCr[ nXPair ];
288             }
289         }
290 
291         // Schleife uber die beiden Zeilen des Zeilen-Paars:
292         for ( ndy = 0; ndy < 2; ndy++ )
293         {
294             ny = ( nYPair << 1 ) + ndy;
295 
296             // Schleife ueber X:
297             for ( nx = 0; nx < nWidth; nx++ )
298             {
299                 // nL,nCb,nCr fuer den Pixel nx,ny holen/berechenen:
300                 nXPair = nx >> 1;
301                 if ( ndy == 0 )
302                 {
303                     nL = (long)pL0[ nx ];
304                     if (( nx & 1 ) == 0 )
305                     {
306                         nCb = (long)pCb[ nXPair ];
307                         nCr = (long)pCr[ nXPair ];
308                     }
309                     else
310                     {
311                         nCb = ( ( (long)pCb[ nXPair ] ) + ( (long)pCb[ nXPair + 1 ] ) ) >> 1;
312                         nCr = ( ( (long)pCr[ nXPair ] ) + ( (long)pCr[ nXPair + 1 ] ) ) >> 1;
313                     }
314                 }
315                 else {
316                     nL = pL1[ nx ];
317                     if ( ( nx & 1 ) == 0 )
318                     {
319                         nCb = ( ( (long)pCb[ nXPair ] ) + ( (long)pCbN[ nXPair ] ) ) >> 1;
320                         nCr = ( ( (long)pCr[ nXPair ] ) + ( (long)pCrN[ nXPair ] ) ) >> 1;
321                     }
322                     else
323                     {
324                         nCb = ( ( (long)pCb[ nXPair ] ) + ( (long)pCb[ nXPair + 1 ] ) +
325                                ( (long)pCbN[ nXPair ] ) + ( (long)pCbN[ nXPair + 1 ] ) ) >> 2;
326                         nCr = ( ( (long)pCr[ nXPair ] ) + ( (long)pCr[ nXPair + 1] ) +
327                                ( (long)pCrN[ nXPair ] ) + ( (long)pCrN[ nXPair + 1 ] ) ) >> 2;
328                     }
329                 }
330                 // Umwandlung von nL,nCb,nCr in nRed,nGreen,nBlue:
331                 nL *= 89024L;
332                 nCb -= 156;
333                 nCr -= 137;
334                 nRed = ( nL + nCr * 119374L + 0x8000 ) >> 16;
335                 if ( nRed < 0 )
336                     nRed = 0;
337                 if ( nRed > 255)
338                     nRed = 255;
339                 nGreen = ( nL - nCb * 28198L - nCr * 60761L + 0x8000 ) >> 16;
340                 if ( nGreen < 0 )
341                     nGreen = 0;
342                 if ( nGreen > 255 )
343                     nGreen = 255;
344                 nBlue = ( nL + nCb * 145352L + 0x8000 ) >> 16;
345                 if ( nBlue < 0 )
346                     nBlue = 0;
347                 if ( nBlue > 255 )
348                     nBlue = 255;
349 
350                 // Farbwert in pBMPMap eintragen:
351                 if ( nOrientation < 2 )
352                 {
353                     if ( nOrientation == 0 )
354                         mpAcc->SetPixel( ny, nx, BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
355                     else
356                         mpAcc->SetPixel( nWidth - 1 - nx, ny, BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
357                 }
358                 else
359                 {
360                     if ( nOrientation == 2 )
361                         mpAcc->SetPixel( nHeight - 1 - ny, ( nWidth - 1 - nx ), BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
362                     else
363                         mpAcc->SetPixel( nx, ( nHeight - 1 - ny ), BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
364                 }
365             }
366         }
367 
368         if ( pPCD->GetError() )
369             bStatus = sal_False;
370         MayCallback( nMinPercent + ( nMaxPercent - nMinPercent ) * nYPair / nH2 );
371         if ( bStatus == sal_False )
372             break;
373     }
374     rtl_freeMemory((void*)pL0 );
375     rtl_freeMemory((void*)pL1 );
376     rtl_freeMemory((void*)pCb );
377     rtl_freeMemory((void*)pCr );
378     rtl_freeMemory((void*)pL0N);
379     rtl_freeMemory((void*)pL1N);
380     rtl_freeMemory((void*)pCbN);
381     rtl_freeMemory((void*)pCrN);
382 }
383 
384 //================== GraphicImport - die exportierte Funktion ================
385 
GraphicImport(SvStream & rStream,Graphic & rGraphic,FilterConfigItem * pConfigItem,sal_Bool)386 extern "C" sal_Bool __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pConfigItem, sal_Bool )
387 {
388     PCDReader aPCDReader;
389     return aPCDReader.ReadPCD( rStream, rGraphic, pConfigItem );
390 }
391 
392