Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "rtl/alloc.h"
31 : : #include <vcl/graph.hxx>
32 : : #include <vcl/bmpacc.hxx>
33 : : #include <vcl/svapp.hxx>
34 : : #include <svtools/fltcall.hxx>
35 : : #include <svl/solar.hrc>
36 : : #include <svtools/FilterConfigItem.hxx>
37 : :
38 : : //============================ PCDReader ==================================
39 : :
40 : : // these resolutions are contained in a PCD file:
41 : : enum PCDResolution {
42 : : PCDRES_BASE16, // 192 x 128
43 : : PCDRES_BASE4, // 384 x 256
44 : : PCDRES_BASE, // 768 x 512
45 : : // the following ones are compressed
46 : : // and CANNOT be read by us
47 : : PCDRES_4BASE, // 1536 x 1024
48 : : PCDRES_16BASE // 3072 x 3072
49 : : };
50 : :
51 : : class PCDReader {
52 : :
53 : : private:
54 : :
55 : : sal_Bool bStatus;
56 : :
57 : : sal_uLong nLastPercent;
58 : :
59 : : SvStream &m_rPCD;
60 : : BitmapWriteAccess* mpAcc;
61 : :
62 : : sal_uInt8 nOrientation; // orientation of the picture withinthe PCD file:
63 : : // 0 - spire point up
64 : : // 1 - spire points to the right
65 : : // 2 - spire points down
66 : : // 3 - spire points to the left
67 : :
68 : : PCDResolution eResolution; // which resolution we want
69 : :
70 : : sal_uLong nWidth; // width of the PCD picture
71 : : sal_uLong nHeight; // heigth of the PCD picture
72 : : sal_uLong nImagePos; // position of the picture within the PCD file
73 : :
74 : : // temporary lLue-Green-Red-Bitmap
75 : : sal_uLong nBMPWidth;
76 : : sal_uLong nBMPHeight;
77 : :
78 : : void MayCallback(sal_uLong nPercent);
79 : :
80 : : void CheckPCDImagePacFile();
81 : : // checks whether it's a Photo-CD file with 'Image Pac'
82 : :
83 : : void ReadOrientation();
84 : : // reads the orientation and sets nOrientation
85 : :
86 : : void ReadImage(sal_uLong nMinPercent, sal_uLong nMaxPercent);
87 : :
88 : : public:
89 : :
90 : 0 : PCDReader(SvStream &rStream)
91 : 0 : : m_rPCD(rStream)
92 : : {
93 : 0 : }
94 : 0 : ~PCDReader() {}
95 : :
96 : : sal_Bool ReadPCD( Graphic & rGraphic, FilterConfigItem* pConfigItem );
97 : : };
98 : :
99 : : //=================== Methods of PCDReader ==============================
100 : :
101 : 0 : sal_Bool PCDReader::ReadPCD( Graphic & rGraphic, FilterConfigItem* pConfigItem )
102 : : {
103 : 0 : Bitmap aBmp;
104 : :
105 : 0 : bStatus = sal_True;
106 : 0 : nLastPercent = 0;
107 : :
108 : 0 : MayCallback( 0 );
109 : :
110 : : // is it a PCD file with a picture? ( sets bStatus == sal_False, if that's not the case):
111 : 0 : CheckPCDImagePacFile();
112 : :
113 : : // read orientation of the picture:
114 : 0 : ReadOrientation();
115 : :
116 : : // which resolution do we want?:
117 : 0 : eResolution = PCDRES_BASE;
118 : 0 : if ( pConfigItem )
119 : : {
120 : 0 : sal_Int32 nResolution = pConfigItem->ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Resolution" ) ), 2 );
121 : 0 : if ( nResolution == 1 )
122 : 0 : eResolution = PCDRES_BASE4;
123 : 0 : else if ( nResolution == 0 )
124 : 0 : eResolution = PCDRES_BASE16;
125 : : }
126 : : // determine size and position (position within the PCD file) of the picture:
127 : 0 : switch (eResolution)
128 : : {
129 : : case PCDRES_BASE16 :
130 : 0 : nWidth = 192;
131 : 0 : nHeight = 128;
132 : 0 : nImagePos = 8192;
133 : 0 : break;
134 : :
135 : : case PCDRES_BASE4 :
136 : 0 : nWidth = 384;
137 : 0 : nHeight = 256;
138 : 0 : nImagePos = 47104;
139 : 0 : break;
140 : :
141 : : case PCDRES_BASE :
142 : 0 : nWidth = 768;
143 : 0 : nHeight = 512;
144 : 0 : nImagePos = 196608;
145 : 0 : break;
146 : :
147 : : default:
148 : 0 : bStatus = sal_False;
149 : : }
150 : 0 : if ( bStatus )
151 : : {
152 : 0 : if ( ( nOrientation & 0x01 ) == 0 )
153 : : {
154 : 0 : nBMPWidth = nWidth;
155 : 0 : nBMPHeight = nHeight;
156 : : }
157 : : else
158 : : {
159 : 0 : nBMPWidth = nHeight;
160 : 0 : nBMPHeight = nWidth;
161 : : }
162 : 0 : aBmp = Bitmap( Size( nBMPWidth, nBMPHeight ), 24 );
163 : 0 : if ( ( mpAcc = aBmp.AcquireWriteAccess() ) == sal_False )
164 : 0 : return sal_False;
165 : :
166 : 0 : ReadImage( 5 ,65 );
167 : :
168 : 0 : aBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
169 : 0 : rGraphic = aBmp;
170 : : }
171 : 0 : return bStatus;
172 : : }
173 : :
174 : : // -------------------------------------------------------------------------------------------
175 : :
176 : 0 : void PCDReader::MayCallback(sal_uLong /*nPercent*/)
177 : : {
178 : 0 : }
179 : :
180 : : // -------------------------------------------------------------------------------------------
181 : :
182 : 0 : void PCDReader::CheckPCDImagePacFile()
183 : : {
184 : : char Buf[ 8 ];
185 : :
186 : 0 : m_rPCD.Seek( 2048 );
187 : 0 : m_rPCD.Read( Buf, 7 );
188 : 0 : Buf[ 7 ] = 0;
189 : 0 : if (!rtl::OString(Buf).equalsL(RTL_CONSTASCII_STRINGPARAM("PCD_IPI")))
190 : 0 : bStatus = sal_False;
191 : 0 : }
192 : :
193 : : // -------------------------------------------------------------------------------------------
194 : :
195 : 0 : void PCDReader::ReadOrientation()
196 : : {
197 : 0 : if ( bStatus == sal_False )
198 : 0 : return;
199 : 0 : m_rPCD.Seek( 194635 );
200 : 0 : m_rPCD >> nOrientation;
201 : 0 : nOrientation &= 0x03;
202 : : }
203 : :
204 : : // -------------------------------------------------------------------------------------------
205 : :
206 : 0 : void PCDReader::ReadImage(sal_uLong nMinPercent, sal_uLong nMaxPercent)
207 : : {
208 : : sal_uLong nx,ny,nW2,nH2,nYPair,ndy,nXPair;
209 : : long nL,nCb,nCr,nRed,nGreen,nBlue;
210 : : sal_uInt8 * pt;
211 : : sal_uInt8 * pL0; // luminance for each pixel of the 1st row of the current pair of rows
212 : : sal_uInt8 * pL1; // luminance for each pixel of the 2nd row of the current pair of rows
213 : : sal_uInt8 * pCb; // blue chrominance for each 2x2 pixel of the current pair of rows
214 : : sal_uInt8 * pCr; // red chrominance fuer je 2x2 pixel of the current pair of rows
215 : : sal_uInt8 * pL0N, * pL1N, * pCbN, * pCrN; // like above, but for the next pair of rows
216 : :
217 : 0 : if ( bStatus == sal_False )
218 : 0 : return;
219 : :
220 : 0 : nW2=nWidth>>1;
221 : 0 : nH2=nHeight>>1;
222 : :
223 : 0 : pL0 =(sal_uInt8*)rtl_allocateMemory( nWidth );
224 : 0 : pL1 =(sal_uInt8*)rtl_allocateMemory( nWidth );
225 : 0 : pCb =(sal_uInt8*)rtl_allocateMemory( nW2+1 );
226 : 0 : pCr =(sal_uInt8*)rtl_allocateMemory( nW2+1 );
227 : 0 : pL0N=(sal_uInt8*)rtl_allocateMemory( nWidth );
228 : 0 : pL1N=(sal_uInt8*)rtl_allocateMemory( nWidth );
229 : 0 : pCbN=(sal_uInt8*)rtl_allocateMemory( nW2+1 );
230 : 0 : pCrN=(sal_uInt8*)rtl_allocateMemory( nW2+1 );
231 : :
232 : 0 : if ( pL0 == NULL || pL1 == NULL || pCb == NULL || pCr == NULL ||
233 : : pL0N == NULL || pL1N == NULL || pCbN == NULL || pCrN == NULL)
234 : : {
235 : 0 : rtl_freeMemory((void*)pL0 );
236 : 0 : rtl_freeMemory((void*)pL1 );
237 : 0 : rtl_freeMemory((void*)pCb );
238 : 0 : rtl_freeMemory((void*)pCr );
239 : 0 : rtl_freeMemory((void*)pL0N);
240 : 0 : rtl_freeMemory((void*)pL1N);
241 : 0 : rtl_freeMemory((void*)pCbN);
242 : 0 : rtl_freeMemory((void*)pCrN);
243 : 0 : bStatus = sal_False;
244 : 0 : return;
245 : : }
246 : :
247 : 0 : m_rPCD.Seek( nImagePos );
248 : :
249 : : // next pair of rows := first pair of rows:
250 : 0 : m_rPCD.Read( pL0N, nWidth );
251 : 0 : m_rPCD.Read( pL1N, nWidth );
252 : 0 : m_rPCD.Read( pCbN, nW2 );
253 : 0 : m_rPCD.Read( pCrN, nW2 );
254 : 0 : pCbN[ nW2 ] = pCbN[ nW2 - 1 ];
255 : 0 : pCrN[ nW2 ] = pCrN[ nW2 - 1 ];
256 : :
257 : 0 : for ( nYPair = 0; nYPair < nH2; nYPair++ )
258 : : {
259 : : // current pair of rows := next pair of rows:
260 : 0 : pt=pL0; pL0=pL0N; pL0N=pt;
261 : 0 : pt=pL1; pL1=pL1N; pL1N=pt;
262 : 0 : pt=pCb; pCb=pCbN; pCbN=pt;
263 : 0 : pt=pCr; pCr=pCrN; pCrN=pt;
264 : :
265 : : // get the next pair of rows:
266 : 0 : if ( nYPair < nH2 - 1 )
267 : : {
268 : 0 : m_rPCD.Read( pL0N, nWidth );
269 : 0 : m_rPCD.Read( pL1N, nWidth );
270 : 0 : m_rPCD.Read( pCbN, nW2 );
271 : 0 : m_rPCD.Read( pCrN, nW2 );
272 : 0 : pCbN[nW2]=pCbN[ nW2 - 1 ];
273 : 0 : pCrN[nW2]=pCrN[ nW2 - 1 ];
274 : : }
275 : : else
276 : : {
277 : 0 : for ( nXPair = 0; nXPair < nW2; nXPair++ )
278 : : {
279 : 0 : pCbN[ nXPair ] = pCb[ nXPair ];
280 : 0 : pCrN[ nXPair ] = pCr[ nXPair ];
281 : : }
282 : : }
283 : :
284 : : // loop trough both rows of the pair of rows:
285 : 0 : for ( ndy = 0; ndy < 2; ndy++ )
286 : : {
287 : 0 : ny = ( nYPair << 1 ) + ndy;
288 : :
289 : : // loop trough X:
290 : 0 : for ( nx = 0; nx < nWidth; nx++ )
291 : : {
292 : : // get/calculate nL,nCb,nCr for the pixel nx,ny:
293 : 0 : nXPair = nx >> 1;
294 : 0 : if ( ndy == 0 )
295 : : {
296 : 0 : nL = (long)pL0[ nx ];
297 : 0 : if (( nx & 1 ) == 0 )
298 : : {
299 : 0 : nCb = (long)pCb[ nXPair ];
300 : 0 : nCr = (long)pCr[ nXPair ];
301 : : }
302 : : else
303 : : {
304 : 0 : nCb = ( ( (long)pCb[ nXPair ] ) + ( (long)pCb[ nXPair + 1 ] ) ) >> 1;
305 : 0 : nCr = ( ( (long)pCr[ nXPair ] ) + ( (long)pCr[ nXPair + 1 ] ) ) >> 1;
306 : : }
307 : : }
308 : : else {
309 : 0 : nL = pL1[ nx ];
310 : 0 : if ( ( nx & 1 ) == 0 )
311 : : {
312 : 0 : nCb = ( ( (long)pCb[ nXPair ] ) + ( (long)pCbN[ nXPair ] ) ) >> 1;
313 : 0 : nCr = ( ( (long)pCr[ nXPair ] ) + ( (long)pCrN[ nXPair ] ) ) >> 1;
314 : : }
315 : : else
316 : : {
317 : 0 : nCb = ( ( (long)pCb[ nXPair ] ) + ( (long)pCb[ nXPair + 1 ] ) +
318 : 0 : ( (long)pCbN[ nXPair ] ) + ( (long)pCbN[ nXPair + 1 ] ) ) >> 2;
319 : 0 : nCr = ( ( (long)pCr[ nXPair ] ) + ( (long)pCr[ nXPair + 1] ) +
320 : 0 : ( (long)pCrN[ nXPair ] ) + ( (long)pCrN[ nXPair + 1 ] ) ) >> 2;
321 : : }
322 : : }
323 : : // Umwandlung von nL,nCb,nCr in nRed,nGreen,nBlue:
324 : 0 : nL *= 89024L;
325 : 0 : nCb -= 156;
326 : 0 : nCr -= 137;
327 : 0 : nRed = ( nL + nCr * 119374L + 0x8000 ) >> 16;
328 : 0 : if ( nRed < 0 )
329 : 0 : nRed = 0;
330 : 0 : if ( nRed > 255)
331 : 0 : nRed = 255;
332 : 0 : nGreen = ( nL - nCb * 28198L - nCr * 60761L + 0x8000 ) >> 16;
333 : 0 : if ( nGreen < 0 )
334 : 0 : nGreen = 0;
335 : 0 : if ( nGreen > 255 )
336 : 0 : nGreen = 255;
337 : 0 : nBlue = ( nL + nCb * 145352L + 0x8000 ) >> 16;
338 : 0 : if ( nBlue < 0 )
339 : 0 : nBlue = 0;
340 : 0 : if ( nBlue > 255 )
341 : 0 : nBlue = 255;
342 : :
343 : : // register color value in pBMPMap:
344 : 0 : if ( nOrientation < 2 )
345 : : {
346 : 0 : if ( nOrientation == 0 )
347 : 0 : mpAcc->SetPixel( ny, nx, BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
348 : : else
349 : 0 : mpAcc->SetPixel( nWidth - 1 - nx, ny, BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
350 : : }
351 : : else
352 : : {
353 : 0 : if ( nOrientation == 2 )
354 : 0 : mpAcc->SetPixel( nHeight - 1 - ny, ( nWidth - 1 - nx ), BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
355 : : else
356 : 0 : mpAcc->SetPixel( nx, ( nHeight - 1 - ny ), BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
357 : : }
358 : : }
359 : : }
360 : :
361 : 0 : if ( m_rPCD.GetError() )
362 : 0 : bStatus = sal_False;
363 : 0 : MayCallback( nMinPercent + ( nMaxPercent - nMinPercent ) * nYPair / nH2 );
364 : 0 : if ( bStatus == sal_False )
365 : 0 : break;
366 : : }
367 : 0 : rtl_freeMemory((void*)pL0 );
368 : 0 : rtl_freeMemory((void*)pL1 );
369 : 0 : rtl_freeMemory((void*)pCb );
370 : 0 : rtl_freeMemory((void*)pCr );
371 : 0 : rtl_freeMemory((void*)pL0N);
372 : 0 : rtl_freeMemory((void*)pL1N);
373 : 0 : rtl_freeMemory((void*)pCbN);
374 : 0 : rtl_freeMemory((void*)pCrN);
375 : : }
376 : :
377 : : //================== GraphicImport - the exported Function ================
378 : :
379 : : extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool __LOADONCALLAPI
380 : 0 : GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pConfigItem, sal_Bool)
381 : : {
382 : 0 : PCDReader aPCDReader(rStream);
383 : 0 : return aPCDReader.ReadPCD(rGraphic, pConfigItem);
384 : : }
385 : :
386 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|