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 <vcl/graph.hxx>
22 #include <vcl/bmpacc.hxx>
24 class FilterConfigItem
;
26 //============================ PCXReader ==================================
32 SvStream
& m_rPCX
; // Die einzulesende PCX-Datei
35 BitmapWriteAccess
* pAcc
;
36 sal_uInt8 nVersion
; // PCX-Version
37 sal_uInt8 nEncoding
; // Art der Komprimierung
38 sal_uLong nBitsPerPlanePix
; // Bits Pro Ebene pro Pixel
39 sal_uLong nPlanes
; // Anzahl Ebenen
40 sal_uLong nBytesPerPlaneLin
; // Bytes in einer Ebenen pro Zeile
41 sal_uInt16 nPaletteInfo
;
43 sal_uLong nWidth
, nHeight
; // Bildausmass in Pixeln
44 sal_uInt16 nResX
, nResY
; // Aufloesung in Pixel pro Inch oder 0,0
45 sal_uInt16 nDestBitsPerPixel
; // Bits pro Pixel der Zielbitmap 1,4,8 oder 24
46 sal_uInt8
* pPalette
; //
47 sal_Bool nStatus
; // status nun nicht mehr am stream abfragen ( SJ )
50 sal_Bool
Callback( sal_uInt16 nPercent
);
52 void ImplReadPalette( sal_uLong nCol
);
53 void ImplReadHeader();
56 PCXReader(SvStream
&rStream
);
58 sal_Bool
ReadPCX(Graphic
& rGraphic
);
59 // Liesst aus dem Stream eine PCX-Datei und fuellt das GDIMetaFile
62 //=================== Methoden von PCXReader ==============================
64 PCXReader::PCXReader(SvStream
&rStream
)
68 pPalette
= new sal_uInt8
[ 768 ];
71 PCXReader::~PCXReader()
76 sal_Bool
PCXReader::Callback( sal_uInt16
/*nPercent*/ )
81 sal_Bool
PCXReader::ReadPCX(Graphic
& rGraphic
)
83 if ( m_rPCX
.GetError() )
86 sal_uLong
* pDummy
= new sal_uLong
; delete pDummy
; // damit unter OS/2
87 // das richtige (Tools-)new
88 // verwendet wird, da es sonst
89 // in dieser DLL nur Vector-news
92 m_rPCX
.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN
);
100 // BMP-Header und ggf. (eventuell zunaechst ungueltige) Farbpalette schreiben:
103 aBmp
= Bitmap( Size( nWidth
, nHeight
), nDestBitsPerPixel
);
104 if ( ( pAcc
= aBmp
.AcquireWriteAccess() ) == sal_False
)
107 if ( nDestBitsPerPixel
<= 8 )
109 sal_uInt16 nColors
= 1 << nDestBitsPerPixel
;
110 sal_uInt8
* pPal
= pPalette
;
111 pAcc
->SetPaletteEntryCount( nColors
);
112 for ( sal_uInt16 i
= 0; i
< nColors
; i
++, pPal
+= 3 )
114 pAcc
->SetPaletteColor( i
, BitmapColor ( pPal
[ 0 ], pPal
[ 1 ], pPal
[ 2 ] ) );
117 // Bitmap-Daten einlesen
120 // Wenn erweiterte Farbpalette am Ende von PCX, dann diese einlesen, und nochmals
121 // in Palette schreiben:
122 if ( nDestBitsPerPixel
== 8 && nStatus
)
124 sal_uInt8
* pPal
= pPalette
;
126 ImplReadPalette(256);
127 pAcc
->SetPaletteEntryCount( 256 );
128 for ( sal_uInt16 i
= 0; i
< 256; i
++, pPal
+= 3 )
130 pAcc
->SetPaletteColor( i
, BitmapColor ( pPal
[ 0 ], pPal
[ 1 ], pPal
[ 2 ] ) );
134 // Aufloesung einstellen:
135 if (nResX!=0 && nResY!=0) {
136 MapMode aMapMode(MAP_INCH,Point(0,0),Fraction(1,nResX),Fraction(1,nResY));
137 rBitmap.SetPrefMapMode(aMapMode);
138 rBitmap.SetPrefSize(Size(nWidth,nHeight));
140 */ if ( nStatus
&& pAcc
)
142 aBmp
.ReleaseAccess( pAcc
), pAcc
= NULL
;
150 void PCXReader::ImplReadHeader()
154 sal_uInt16 nMinX
,nMinY
,nMaxX
,nMaxY
;
156 m_rPCX
>> nbyte
>> nVersion
>> nEncoding
;
157 if ( nbyte
!=0x0a || (nVersion
!= 0 && nVersion
!= 2 && nVersion
!= 3 && nVersion
!= 5) || nEncoding
> 1 )
163 m_rPCX
>> nbyte
; nBitsPerPlanePix
= (sal_uLong
)nbyte
;
164 m_rPCX
>> nMinX
>> nMinY
>> nMaxX
>> nMaxY
;
166 if ((nMinX
> nMaxX
) || (nMinY
> nMaxY
))
172 nWidth
= nMaxX
-nMinX
+1;
173 nHeight
= nMaxY
-nMinY
+1;
177 if ( nResX
>= nWidth
|| nResY
>= nHeight
|| ( nResX
!= nResY
) )
180 ImplReadPalette( 16 );
183 m_rPCX
>> nbyte
; nPlanes
= (sal_uLong
)nbyte
;
184 m_rPCX
>> nushort
; nBytesPerPlaneLin
= (sal_uLong
)nushort
;
185 m_rPCX
>> nPaletteInfo
;
187 m_rPCX
.SeekRel( 58 );
189 nDestBitsPerPixel
= (sal_uInt16
)( nBitsPerPlanePix
* nPlanes
);
190 if (nDestBitsPerPixel
== 2 || nDestBitsPerPixel
== 3) nDestBitsPerPixel
= 4;
192 if ( ( nDestBitsPerPixel
!= 1 && nDestBitsPerPixel
!= 4 && nDestBitsPerPixel
!= 8 && nDestBitsPerPixel
!= 24 )
193 || nPlanes
> 4 || nBytesPerPlaneLin
< ( ( nWidth
* nBitsPerPlanePix
+7 ) >> 3 ) )
199 // Wenn das Bild nur 2 Farben hat, ist die Palette zumeist ungueltig, und es handelt sich
200 // immer (?) um ein schwarz-weiss-Bild:
201 if ( nPlanes
== 1 && nBitsPerPlanePix
== 1 )
203 pPalette
[ 0 ] = pPalette
[ 1 ] = pPalette
[ 2 ] = 0x00;
204 pPalette
[ 3 ] = pPalette
[ 4 ] = pPalette
[ 5 ] = 0xff;
208 void PCXReader::ImplReadBody()
210 sal_uInt8
*pPlane
[ 4 ], * pDest
, * pSource1
, * pSource2
, * pSource3
, *pSource4
;
211 sal_uLong i
, nx
, ny
, np
, nCount
, nPercent
;
212 sal_uLong nLastPercent
= 0;
213 sal_uInt8 nDat
= 0, nCol
= 0;
215 for( np
= 0; np
< nPlanes
; np
++ )
216 pPlane
[ np
] = new sal_uInt8
[ nBytesPerPlaneLin
];
219 for ( ny
= 0; ny
< nHeight
; ny
++ )
221 if (m_rPCX
.GetError() || m_rPCX
.IsEof())
226 nPercent
= ny
* 60 / nHeight
+ 10;
227 if ( ny
== 0 || nLastPercent
+ 4 <= nPercent
)
229 nLastPercent
= nPercent
;
230 if ( Callback( (sal_uInt16
)nPercent
) == sal_True
)
233 for ( np
= 0; np
< nPlanes
; np
++)
236 m_rPCX
.Read( (void *)pPlane
[ np
], nBytesPerPlaneLin
);
239 pDest
= pPlane
[ np
];
240 nx
= nBytesPerPlaneLin
;
241 while ( nCount
> 0 && nx
> 0)
250 if ( ( nDat
& 0xc0 ) == 0xc0 )
252 nCount
=( (sal_uLong
)nDat
) & 0x003f;
283 pSource1
= pPlane
[ 0 ];
284 pSource2
= pPlane
[ 1 ];
285 pSource3
= pPlane
[ 2 ];
286 pSource4
= pPlane
[ 3 ];
287 switch ( nBitsPerPlanePix
+ ( nPlanes
<< 8 ) )
291 for ( i
= 0; i
< nWidth
; i
++ )
293 sal_uLong nShift
= ( i
& 7 ) ^ 7;
295 pAcc
->SetPixel( ny
, i
, ( *pSource1
++ & 1 ) );
299 sal::static_int_cast
< sal_uInt8
>(
300 ( *pSource1
>> nShift
) & 1) );
305 for ( i
= 0; i
< nWidth
; i
++ )
310 nCol
= *pSource1
>> 6;
313 nCol
= ( *pSource1
>> 4 ) & 0x03 ;
316 nCol
= ( *pSource1
>> 2 ) & 0x03;
319 nCol
= ( *pSource1
++ ) & 0x03;
322 pAcc
->SetPixel( ny
, i
, nCol
);
327 for ( i
= 0; i
< nWidth
; i
++ )
329 pAcc
->SetPixel( ny
, i
, *pSource1
++ );
334 for ( i
= 0; i
< nWidth
; i
++ )
336 sal_uLong nShift
= ( i
& 7 ) ^ 7;
339 nCol
= ( *pSource1
++ & 1) + ( ( *pSource2
++ << 1 ) & 2 ) + ( ( *pSource3
++ << 2 ) & 4 );
340 pAcc
->SetPixel( ny
, i
, nCol
);
344 nCol
= sal::static_int_cast
< sal_uInt8
>(
345 ( ( *pSource1
>> nShift
) & 1) + ( ( ( *pSource2
>> nShift
) << 1 ) & 2 ) +
346 ( ( ( *pSource3
>> nShift
) << 2 ) & 4 ));
347 pAcc
->SetPixel( ny
, i
, nCol
);
353 for ( i
= 0; i
< nWidth
; i
++ )
355 sal_uLong nShift
= ( i
& 7 ) ^ 7;
358 nCol
= ( *pSource1
++ & 1) + ( ( *pSource2
++ << 1 ) & 2 ) + ( ( *pSource3
++ << 2 ) & 4 ) +
359 ( ( *pSource4
++ << 3 ) & 8 );
360 pAcc
->SetPixel( ny
, i
, nCol
);
364 nCol
= sal::static_int_cast
< sal_uInt8
>(
365 ( ( *pSource1
>> nShift
) & 1) + ( ( ( *pSource2
>> nShift
) << 1 ) & 2 ) +
366 ( ( ( *pSource3
>> nShift
) << 2 ) & 4 ) + ( ( ( *pSource4
>> nShift
) << 3 ) & 8 ));
367 pAcc
->SetPixel( ny
, i
, nCol
);
373 for ( i
= 0; i
< nWidth
; i
++ )
375 pAcc
->SetPixel( ny
, i
, Color( *pSource1
++, *pSource2
++, *pSource3
++ ) );
384 for ( np
= 0; np
< nPlanes
; np
++ )
385 delete[] pPlane
[ np
];
388 void PCXReader::ImplReadPalette( sal_uLong nCol
)
391 sal_uInt8
* pPtr
= pPalette
;
392 for ( sal_uLong i
= 0; i
< nCol
; i
++ )
394 m_rPCX
>> r
>> g
>> b
;
401 //================== GraphicImport - die exportierte Funktion ================
403 #ifdef DISABLE_DYNLOADING
404 #define GraphicImport ipxGraphicImport
407 extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool __LOADONCALLAPI
408 GraphicImport(SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
*, sal_Bool
)
410 PCXReader
aPCXReader(rStream
);
411 sal_Bool nRetValue
= aPCXReader
.ReadPCX(rGraphic
);
412 if ( nRetValue
== sal_False
)
413 rStream
.SetError( SVSTREAM_FILEFORMAT_ERROR
);
417 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */