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/BitmapTools.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/fltcall.hxx>
26 #include <svl/solar.hrc>
27 #include <vcl/FilterConfigItem.hxx>
28 #include <tools/stream.hxx>
30 //============================ PCDReader ==================================
32 // these resolutions are contained in a PCD file:
34 PCDRES_BASE16
, // 192 x 128
35 PCDRES_BASE4
, // 384 x 256
36 PCDRES_BASE
, // 768 x 512
37 // the following ones are compressed
38 // and CANNOT be read by us
39 PCDRES_4BASE
, // 1536 x 1024
40 PCDRES_16BASE
// 3072 x 3072
50 std::unique_ptr
<vcl::bitmap::RawBitmap
> mpBitmap
;
52 sal_uInt8 nOrientation
; // orientation of the picture within the PCD file:
54 // 1 - spire points to the right
55 // 2 - spire points down
56 // 3 - spire points to the left
58 PCDResolution eResolution
; // which resolution we want
60 sal_uLong nWidth
; // width of the PCD picture
61 sal_uLong nHeight
; // height of the PCD picture
62 sal_uLong nImagePos
; // position of the picture within the PCD file
64 // temporary lLue-Green-Red-Bitmap
68 void CheckPCDImagePacFile();
69 // checks whether it's a Photo-CD file with 'Image Pac'
71 void ReadOrientation();
72 // reads the orientation and sets nOrientation
78 explicit PCDReader(SvStream
&rStream
)
82 , eResolution(PCDRES_BASE16
)
91 bool ReadPCD( Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
);
94 //=================== Methods of PCDReader ==============================
96 bool PCDReader::ReadPCD( Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
)
100 // is it a PCD file with a picture? ( sets bStatus == sal_False, if that's not the case):
101 CheckPCDImagePacFile();
103 // read orientation of the picture:
106 // which resolution do we want?:
107 eResolution
= PCDRES_BASE
;
110 sal_Int32 nResolution
= pConfigItem
->ReadInt32( "Resolution", 2 );
111 if ( nResolution
== 1 )
112 eResolution
= PCDRES_BASE4
;
113 else if ( nResolution
== 0 )
114 eResolution
= PCDRES_BASE16
;
116 // determine size and position (position within the PCD file) of the picture:
142 if ( ( nOrientation
& 0x01 ) == 0 )
145 nBMPHeight
= nHeight
;
152 mpBitmap
.reset(new vcl::bitmap::RawBitmap( Size( nBMPWidth
, nBMPHeight
), 24 ));
156 rGraphic
= vcl::bitmap::CreateFromData(std::move(*mpBitmap
));
162 void PCDReader::CheckPCDImagePacFile()
167 m_rPCD
.ReadBytes(Buf
, 7);
169 if (OString(Buf
) != "PCD_IPI")
174 void PCDReader::ReadOrientation()
178 m_rPCD
.Seek( 194635 );
179 m_rPCD
.ReadUChar( nOrientation
);
180 nOrientation
&= 0x03;
184 void PCDReader::ReadImage()
186 sal_uLong nx
,ny
,nW2
,nH2
,nYPair
,ndy
,nXPair
;
187 long nL
,nCb
,nCr
,nRed
,nGreen
,nBlue
;
189 sal_uInt8
* pL0
; // luminance for each pixel of the 1st row of the current pair of rows
190 sal_uInt8
* pL1
; // luminance for each pixel of the 2nd row of the current pair of rows
191 sal_uInt8
* pCb
; // blue chrominance for each 2x2 pixel of the current pair of rows
192 sal_uInt8
* pCr
; // red chrominance for each 2x2 pixel of the current pair of rows
193 sal_uInt8
* pL0N
, * pL1N
, * pCbN
, * pCrN
; // like above, but for the next pair of rows
201 pL0
=static_cast<sal_uInt8
*>(std::malloc( nWidth
));
202 pL1
=static_cast<sal_uInt8
*>(std::malloc( nWidth
));
203 pCb
=static_cast<sal_uInt8
*>(std::malloc( nW2
+1 ));
204 pCr
=static_cast<sal_uInt8
*>(std::malloc( nW2
+1 ));
205 pL0N
=static_cast<sal_uInt8
*>(std::malloc( nWidth
));
206 pL1N
=static_cast<sal_uInt8
*>(std::malloc( nWidth
));
207 pCbN
=static_cast<sal_uInt8
*>(std::malloc( nW2
+1 ));
208 pCrN
=static_cast<sal_uInt8
*>(std::malloc( nW2
+1 ));
210 if ( pL0
== nullptr || pL1
== nullptr || pCb
== nullptr || pCr
== nullptr ||
211 pL0N
== nullptr || pL1N
== nullptr || pCbN
== nullptr || pCrN
== nullptr)
213 std::free(static_cast<void*>(pL0
) );
214 std::free(static_cast<void*>(pL1
) );
215 std::free(static_cast<void*>(pCb
) );
216 std::free(static_cast<void*>(pCr
) );
217 std::free(static_cast<void*>(pL0N
));
218 std::free(static_cast<void*>(pL1N
));
219 std::free(static_cast<void*>(pCbN
));
220 std::free(static_cast<void*>(pCrN
));
225 m_rPCD
.Seek( nImagePos
);
227 // next pair of rows := first pair of rows:
228 m_rPCD
.ReadBytes( pL0N
, nWidth
);
229 m_rPCD
.ReadBytes( pL1N
, nWidth
);
230 m_rPCD
.ReadBytes( pCbN
, nW2
);
231 m_rPCD
.ReadBytes( pCrN
, nW2
);
232 pCbN
[ nW2
] = pCbN
[ nW2
- 1 ];
233 pCrN
[ nW2
] = pCrN
[ nW2
- 1 ];
235 for ( nYPair
= 0; nYPair
< nH2
; nYPair
++ )
237 // current pair of rows := next pair of rows:
238 pt
=pL0
; pL0
=pL0N
; pL0N
=pt
;
239 pt
=pL1
; pL1
=pL1N
; pL1N
=pt
;
240 pt
=pCb
; pCb
=pCbN
; pCbN
=pt
;
241 pt
=pCr
; pCr
=pCrN
; pCrN
=pt
;
243 // get the next pair of rows:
244 if ( nYPair
< nH2
- 1 )
246 m_rPCD
.ReadBytes( pL0N
, nWidth
);
247 m_rPCD
.ReadBytes( pL1N
, nWidth
);
248 m_rPCD
.ReadBytes( pCbN
, nW2
);
249 m_rPCD
.ReadBytes( pCrN
, nW2
);
250 pCbN
[nW2
]=pCbN
[ nW2
- 1 ];
251 pCrN
[nW2
]=pCrN
[ nW2
- 1 ];
255 for ( nXPair
= 0; nXPair
< nW2
; nXPair
++ )
257 pCbN
[ nXPair
] = pCb
[ nXPair
];
258 pCrN
[ nXPair
] = pCr
[ nXPair
];
262 // loop through both rows of the pair of rows:
263 for ( ndy
= 0; ndy
< 2; ndy
++ )
265 ny
= ( nYPair
<< 1 ) + ndy
;
268 for ( nx
= 0; nx
< nWidth
; nx
++ )
270 // get/calculate nL,nCb,nCr for the pixel nx,ny:
274 nL
= static_cast<long>(pL0
[ nx
]);
275 if (( nx
& 1 ) == 0 )
277 nCb
= static_cast<long>(pCb
[ nXPair
]);
278 nCr
= static_cast<long>(pCr
[ nXPair
]);
282 nCb
= ( static_cast<long>(pCb
[ nXPair
]) + static_cast<long>(pCb
[ nXPair
+ 1 ]) ) >> 1;
283 nCr
= ( static_cast<long>(pCr
[ nXPair
]) + static_cast<long>(pCr
[ nXPair
+ 1 ]) ) >> 1;
288 if ( ( nx
& 1 ) == 0 )
290 nCb
= ( static_cast<long>(pCb
[ nXPair
]) + static_cast<long>(pCbN
[ nXPair
]) ) >> 1;
291 nCr
= ( static_cast<long>(pCr
[ nXPair
]) + static_cast<long>(pCrN
[ nXPair
]) ) >> 1;
295 nCb
= ( static_cast<long>(pCb
[ nXPair
]) + static_cast<long>(pCb
[ nXPair
+ 1 ]) +
296 static_cast<long>(pCbN
[ nXPair
]) + static_cast<long>(pCbN
[ nXPair
+ 1 ]) ) >> 2;
297 nCr
= ( static_cast<long>(pCr
[ nXPair
]) + static_cast<long>(pCr
[ nXPair
+ 1]) +
298 static_cast<long>(pCrN
[ nXPair
]) + static_cast<long>(pCrN
[ nXPair
+ 1 ]) ) >> 2;
301 // conversion of nL,nCb,nCr in nRed,nGreen,nBlue:
305 nRed
= ( nL
+ nCr
* 119374 + 0x8000 ) >> 16;
310 nGreen
= ( nL
- nCb
* 28198 - nCr
* 60761 + 0x8000 ) >> 16;
315 nBlue
= ( nL
+ nCb
* 145352 + 0x8000 ) >> 16;
321 // register color value in pBMPMap:
322 if ( nOrientation
< 2 )
324 if ( nOrientation
== 0 )
325 mpBitmap
->SetPixel( ny
, nx
, Color( static_cast<sal_uInt8
>(nRed
), static_cast<sal_uInt8
>(nGreen
), static_cast<sal_uInt8
>(nBlue
) ) );
327 mpBitmap
->SetPixel( nWidth
- 1 - nx
, ny
, Color( static_cast<sal_uInt8
>(nRed
), static_cast<sal_uInt8
>(nGreen
), static_cast<sal_uInt8
>(nBlue
) ) );
331 if ( nOrientation
== 2 )
332 mpBitmap
->SetPixel( nHeight
- 1 - ny
, ( nWidth
- 1 - nx
), Color( static_cast<sal_uInt8
>(nRed
), static_cast<sal_uInt8
>(nGreen
), static_cast<sal_uInt8
>(nBlue
) ) );
334 mpBitmap
->SetPixel( nx
, ( nHeight
- 1 - ny
), Color( static_cast<sal_uInt8
>(nRed
), static_cast<sal_uInt8
>(nGreen
), static_cast<sal_uInt8
>(nBlue
) ) );
339 if ( m_rPCD
.GetError() )
344 std::free(static_cast<void*>(pL0
) );
345 std::free(static_cast<void*>(pL1
) );
346 std::free(static_cast<void*>(pCb
) );
347 std::free(static_cast<void*>(pCr
) );
348 std::free(static_cast<void*>(pL0N
));
349 std::free(static_cast<void*>(pL1N
));
350 std::free(static_cast<void*>(pCbN
));
351 std::free(static_cast<void*>(pCrN
));
354 //================== GraphicImport - the exported Function ================
356 extern "C" SAL_DLLPUBLIC_EXPORT
bool
357 icdGraphicImport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pConfigItem
)
359 PCDReader
aPCDReader(rStream
);
360 return aPCDReader
.ReadPCD(rGraphic
, pConfigItem
);
363 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */