bump product version to 4.1.6.2
[LibreOffice.git] / filter / source / graphicfilter / ipcd / ipcd.cxx
blob57178d8f94b8d21ef579f32578e959d1f469f0e9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "rtl/alloc.h"
22 #include <vcl/graph.hxx>
23 #include <vcl/bmpacc.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/fltcall.hxx>
26 #include <svl/solar.hrc>
27 #include <vcl/FilterConfigItem.hxx>
29 //============================ PCDReader ==================================
31 // these resolutions are contained in a PCD file:
32 enum PCDResolution {
33 PCDRES_BASE16, // 192 x 128
34 PCDRES_BASE4, // 384 x 256
35 PCDRES_BASE, // 768 x 512
36 // the following ones are compressed
37 // and CANNOT be read by us
38 PCDRES_4BASE, // 1536 x 1024
39 PCDRES_16BASE // 3072 x 3072
42 class PCDReader {
44 private:
46 sal_Bool bStatus;
48 sal_uLong nLastPercent;
50 SvStream &m_rPCD;
51 BitmapWriteAccess* mpAcc;
53 sal_uInt8 nOrientation; // orientation of the picture withinthe PCD file:
54 // 0 - spire point up
55 // 1 - spire points to the right
56 // 2 - spire points down
57 // 3 - spire points to the left
59 PCDResolution eResolution; // which resolution we want
61 sal_uLong nWidth; // width of the PCD picture
62 sal_uLong nHeight; // height of the PCD picture
63 sal_uLong nImagePos; // position of the picture within the PCD file
65 // temporary lLue-Green-Red-Bitmap
66 sal_uLong nBMPWidth;
67 sal_uLong nBMPHeight;
69 void MayCallback(sal_uLong nPercent);
71 void CheckPCDImagePacFile();
72 // checks whether it's a Photo-CD file with 'Image Pac'
74 void ReadOrientation();
75 // reads the orientation and sets nOrientation
77 void ReadImage(sal_uLong nMinPercent, sal_uLong nMaxPercent);
79 public:
81 PCDReader(SvStream &rStream)
82 : m_rPCD(rStream)
85 ~PCDReader() {}
87 sal_Bool ReadPCD( Graphic & rGraphic, FilterConfigItem* pConfigItem );
90 //=================== Methods of PCDReader ==============================
92 sal_Bool PCDReader::ReadPCD( Graphic & rGraphic, FilterConfigItem* pConfigItem )
94 Bitmap aBmp;
96 bStatus = sal_True;
97 nLastPercent = 0;
99 MayCallback( 0 );
101 // is it a PCD file with a picture? ( sets bStatus == sal_False, if that's not the case):
102 CheckPCDImagePacFile();
104 // read orientation of the picture:
105 ReadOrientation();
107 // which resolution do we want?:
108 eResolution = PCDRES_BASE;
109 if ( pConfigItem )
111 sal_Int32 nResolution = pConfigItem->ReadInt32( "Resolution", 2 );
112 if ( nResolution == 1 )
113 eResolution = PCDRES_BASE4;
114 else if ( nResolution == 0 )
115 eResolution = PCDRES_BASE16;
117 // determine size and position (position within the PCD file) of the picture:
118 switch (eResolution)
120 case PCDRES_BASE16 :
121 nWidth = 192;
122 nHeight = 128;
123 nImagePos = 8192;
124 break;
126 case PCDRES_BASE4 :
127 nWidth = 384;
128 nHeight = 256;
129 nImagePos = 47104;
130 break;
132 case PCDRES_BASE :
133 nWidth = 768;
134 nHeight = 512;
135 nImagePos = 196608;
136 break;
138 default:
139 bStatus = sal_False;
141 if ( bStatus )
143 if ( ( nOrientation & 0x01 ) == 0 )
145 nBMPWidth = nWidth;
146 nBMPHeight = nHeight;
148 else
150 nBMPWidth = nHeight;
151 nBMPHeight = nWidth;
153 aBmp = Bitmap( Size( nBMPWidth, nBMPHeight ), 24 );
154 if ( ( mpAcc = aBmp.AcquireWriteAccess() ) == sal_False )
155 return sal_False;
157 ReadImage( 5 ,65 );
159 aBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
160 rGraphic = aBmp;
162 return bStatus;
165 // -------------------------------------------------------------------------------------------
167 void PCDReader::MayCallback(sal_uLong /*nPercent*/)
171 // -------------------------------------------------------------------------------------------
173 void PCDReader::CheckPCDImagePacFile()
175 char Buf[ 8 ];
177 m_rPCD.Seek( 2048 );
178 m_rPCD.Read( Buf, 7 );
179 Buf[ 7 ] = 0;
180 if (OString(Buf) != "PCD_IPI")
181 bStatus = sal_False;
184 // -------------------------------------------------------------------------------------------
186 void PCDReader::ReadOrientation()
188 if ( bStatus == sal_False )
189 return;
190 m_rPCD.Seek( 194635 );
191 m_rPCD >> nOrientation;
192 nOrientation &= 0x03;
195 // -------------------------------------------------------------------------------------------
197 void PCDReader::ReadImage(sal_uLong nMinPercent, sal_uLong nMaxPercent)
199 sal_uLong nx,ny,nW2,nH2,nYPair,ndy,nXPair;
200 long nL,nCb,nCr,nRed,nGreen,nBlue;
201 sal_uInt8 * pt;
202 sal_uInt8 * pL0; // luminance for each pixel of the 1st row of the current pair of rows
203 sal_uInt8 * pL1; // luminance for each pixel of the 2nd row of the current pair of rows
204 sal_uInt8 * pCb; // blue chrominance for each 2x2 pixel of the current pair of rows
205 sal_uInt8 * pCr; // red chrominance fuer je 2x2 pixel of the current pair of rows
206 sal_uInt8 * pL0N, * pL1N, * pCbN, * pCrN; // like above, but for the next pair of rows
208 if ( bStatus == sal_False )
209 return;
211 nW2=nWidth>>1;
212 nH2=nHeight>>1;
214 pL0 =(sal_uInt8*)rtl_allocateMemory( nWidth );
215 pL1 =(sal_uInt8*)rtl_allocateMemory( nWidth );
216 pCb =(sal_uInt8*)rtl_allocateMemory( nW2+1 );
217 pCr =(sal_uInt8*)rtl_allocateMemory( nW2+1 );
218 pL0N=(sal_uInt8*)rtl_allocateMemory( nWidth );
219 pL1N=(sal_uInt8*)rtl_allocateMemory( nWidth );
220 pCbN=(sal_uInt8*)rtl_allocateMemory( nW2+1 );
221 pCrN=(sal_uInt8*)rtl_allocateMemory( nW2+1 );
223 if ( pL0 == NULL || pL1 == NULL || pCb == NULL || pCr == NULL ||
224 pL0N == NULL || pL1N == NULL || pCbN == NULL || pCrN == NULL)
226 rtl_freeMemory((void*)pL0 );
227 rtl_freeMemory((void*)pL1 );
228 rtl_freeMemory((void*)pCb );
229 rtl_freeMemory((void*)pCr );
230 rtl_freeMemory((void*)pL0N);
231 rtl_freeMemory((void*)pL1N);
232 rtl_freeMemory((void*)pCbN);
233 rtl_freeMemory((void*)pCrN);
234 bStatus = sal_False;
235 return;
238 m_rPCD.Seek( nImagePos );
240 // next pair of rows := first pair of rows:
241 m_rPCD.Read( pL0N, nWidth );
242 m_rPCD.Read( pL1N, nWidth );
243 m_rPCD.Read( pCbN, nW2 );
244 m_rPCD.Read( pCrN, nW2 );
245 pCbN[ nW2 ] = pCbN[ nW2 - 1 ];
246 pCrN[ nW2 ] = pCrN[ nW2 - 1 ];
248 for ( nYPair = 0; nYPair < nH2; nYPair++ )
250 // current pair of rows := next pair of rows:
251 pt=pL0; pL0=pL0N; pL0N=pt;
252 pt=pL1; pL1=pL1N; pL1N=pt;
253 pt=pCb; pCb=pCbN; pCbN=pt;
254 pt=pCr; pCr=pCrN; pCrN=pt;
256 // get the next pair of rows:
257 if ( nYPair < nH2 - 1 )
259 m_rPCD.Read( pL0N, nWidth );
260 m_rPCD.Read( pL1N, nWidth );
261 m_rPCD.Read( pCbN, nW2 );
262 m_rPCD.Read( pCrN, nW2 );
263 pCbN[nW2]=pCbN[ nW2 - 1 ];
264 pCrN[nW2]=pCrN[ nW2 - 1 ];
266 else
268 for ( nXPair = 0; nXPair < nW2; nXPair++ )
270 pCbN[ nXPair ] = pCb[ nXPair ];
271 pCrN[ nXPair ] = pCr[ nXPair ];
275 // loop trough both rows of the pair of rows:
276 for ( ndy = 0; ndy < 2; ndy++ )
278 ny = ( nYPair << 1 ) + ndy;
280 // loop trough X:
281 for ( nx = 0; nx < nWidth; nx++ )
283 // get/calculate nL,nCb,nCr for the pixel nx,ny:
284 nXPair = nx >> 1;
285 if ( ndy == 0 )
287 nL = (long)pL0[ nx ];
288 if (( nx & 1 ) == 0 )
290 nCb = (long)pCb[ nXPair ];
291 nCr = (long)pCr[ nXPair ];
293 else
295 nCb = ( ( (long)pCb[ nXPair ] ) + ( (long)pCb[ nXPair + 1 ] ) ) >> 1;
296 nCr = ( ( (long)pCr[ nXPair ] ) + ( (long)pCr[ nXPair + 1 ] ) ) >> 1;
299 else {
300 nL = pL1[ nx ];
301 if ( ( nx & 1 ) == 0 )
303 nCb = ( ( (long)pCb[ nXPair ] ) + ( (long)pCbN[ nXPair ] ) ) >> 1;
304 nCr = ( ( (long)pCr[ nXPair ] ) + ( (long)pCrN[ nXPair ] ) ) >> 1;
306 else
308 nCb = ( ( (long)pCb[ nXPair ] ) + ( (long)pCb[ nXPair + 1 ] ) +
309 ( (long)pCbN[ nXPair ] ) + ( (long)pCbN[ nXPair + 1 ] ) ) >> 2;
310 nCr = ( ( (long)pCr[ nXPair ] ) + ( (long)pCr[ nXPair + 1] ) +
311 ( (long)pCrN[ nXPair ] ) + ( (long)pCrN[ nXPair + 1 ] ) ) >> 2;
314 // conversion of nL,nCb,nCr in nRed,nGreen,nBlue:
315 nL *= 89024L;
316 nCb -= 156;
317 nCr -= 137;
318 nRed = ( nL + nCr * 119374L + 0x8000 ) >> 16;
319 if ( nRed < 0 )
320 nRed = 0;
321 if ( nRed > 255)
322 nRed = 255;
323 nGreen = ( nL - nCb * 28198L - nCr * 60761L + 0x8000 ) >> 16;
324 if ( nGreen < 0 )
325 nGreen = 0;
326 if ( nGreen > 255 )
327 nGreen = 255;
328 nBlue = ( nL + nCb * 145352L + 0x8000 ) >> 16;
329 if ( nBlue < 0 )
330 nBlue = 0;
331 if ( nBlue > 255 )
332 nBlue = 255;
334 // register color value in pBMPMap:
335 if ( nOrientation < 2 )
337 if ( nOrientation == 0 )
338 mpAcc->SetPixel( ny, nx, BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
339 else
340 mpAcc->SetPixel( nWidth - 1 - nx, ny, BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
342 else
344 if ( nOrientation == 2 )
345 mpAcc->SetPixel( nHeight - 1 - ny, ( nWidth - 1 - nx ), BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
346 else
347 mpAcc->SetPixel( nx, ( nHeight - 1 - ny ), BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
352 if ( m_rPCD.GetError() )
353 bStatus = sal_False;
354 MayCallback( nMinPercent + ( nMaxPercent - nMinPercent ) * nYPair / nH2 );
355 if ( bStatus == sal_False )
356 break;
358 rtl_freeMemory((void*)pL0 );
359 rtl_freeMemory((void*)pL1 );
360 rtl_freeMemory((void*)pCb );
361 rtl_freeMemory((void*)pCr );
362 rtl_freeMemory((void*)pL0N);
363 rtl_freeMemory((void*)pL1N);
364 rtl_freeMemory((void*)pCbN);
365 rtl_freeMemory((void*)pCrN);
368 //================== GraphicImport - the exported Function ================
370 // this needs to be kept in sync with
371 // ImpFilterLibCacheEntry::GetImportFunction() from
372 // vcl/source/filter/graphicfilter.cxx
373 #if defined(DISABLE_DYNLOADING)
374 #define GraphicImport icdGraphicImport
375 #endif
377 extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL
378 GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pConfigItem, sal_Bool)
380 PCDReader aPCDReader(rStream);
381 return aPCDReader.ReadPCD(rGraphic, pConfigItem);
384 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */