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