1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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:
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
48 sal_uLong nLastPercent
;
51 BitmapWriteAccess
* mpAcc
;
53 sal_uInt8 nOrientation
; // orientation of the picture withinthe PCD file:
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
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
);
81 PCDReader(SvStream
&rStream
)
87 sal_Bool
ReadPCD( Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
90 //=================== Methods of PCDReader ==============================
92 sal_Bool
PCDReader::ReadPCD( Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
)
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:
107 // which resolution do we want?:
108 eResolution
= PCDRES_BASE
;
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:
143 if ( ( nOrientation
& 0x01 ) == 0 )
146 nBMPHeight
= nHeight
;
153 aBmp
= Bitmap( Size( nBMPWidth
, nBMPHeight
), 24 );
154 if ( ( mpAcc
= aBmp
.AcquireWriteAccess() ) == sal_False
)
159 aBmp
.ReleaseAccess( mpAcc
), mpAcc
= NULL
;
165 // -------------------------------------------------------------------------------------------
167 void PCDReader::MayCallback(sal_uLong
/*nPercent*/)
171 // -------------------------------------------------------------------------------------------
173 void PCDReader::CheckPCDImagePacFile()
178 m_rPCD
.Read( Buf
, 7 );
180 if (OString(Buf
) != "PCD_IPI")
184 // -------------------------------------------------------------------------------------------
186 void PCDReader::ReadOrientation()
188 if ( bStatus
== sal_False
)
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
;
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
)
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
);
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 ];
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
;
281 for ( nx
= 0; nx
< nWidth
; nx
++ )
283 // get/calculate nL,nCb,nCr for the pixel nx,ny:
287 nL
= (long)pL0
[ nx
];
288 if (( nx
& 1 ) == 0 )
290 nCb
= (long)pCb
[ nXPair
];
291 nCr
= (long)pCr
[ nXPair
];
295 nCb
= ( ( (long)pCb
[ nXPair
] ) + ( (long)pCb
[ nXPair
+ 1 ] ) ) >> 1;
296 nCr
= ( ( (long)pCr
[ nXPair
] ) + ( (long)pCr
[ nXPair
+ 1 ] ) ) >> 1;
301 if ( ( nx
& 1 ) == 0 )
303 nCb
= ( ( (long)pCb
[ nXPair
] ) + ( (long)pCbN
[ nXPair
] ) ) >> 1;
304 nCr
= ( ( (long)pCr
[ nXPair
] ) + ( (long)pCrN
[ nXPair
] ) ) >> 1;
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:
318 nRed
= ( nL
+ nCr
* 119374L + 0x8000 ) >> 16;
323 nGreen
= ( nL
- nCb
* 28198L - nCr
* 60761L + 0x8000 ) >> 16;
328 nBlue
= ( nL
+ nCb
* 145352L + 0x8000 ) >> 16;
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
) );
340 mpAcc
->SetPixel( nWidth
- 1 - nx
, ny
, BitmapColor( (sal_uInt8
)nRed
, (sal_uInt8
)nGreen
, (sal_uInt8
)nBlue
) );
344 if ( nOrientation
== 2 )
345 mpAcc
->SetPixel( nHeight
- 1 - ny
, ( nWidth
- 1 - nx
), BitmapColor( (sal_uInt8
)nRed
, (sal_uInt8
)nGreen
, (sal_uInt8
)nBlue
) );
347 mpAcc
->SetPixel( nx
, ( nHeight
- 1 - ny
), BitmapColor( (sal_uInt8
)nRed
, (sal_uInt8
)nGreen
, (sal_uInt8
)nBlue
) );
352 if ( m_rPCD
.GetError() )
354 MayCallback( nMinPercent
+ ( nMaxPercent
- nMinPercent
) * nYPair
/ nH2
);
355 if ( bStatus
== sal_False
)
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
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: */