Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include <vcl/graph.hxx>
22 : #include <vcl/bmpacc.hxx>
23 :
24 : class FilterConfigItem;
25 :
26 : #define RAS_TYPE_OLD 0x00000000 // supported formats by this filter
27 : #define RAS_TYPE_STANDARD 0x00000001
28 : #define RAS_TYPE_BYTE_ENCODED 0x00000002
29 : #define RAS_TYPE_RGB_FORMAT 0x00000003
30 :
31 : #define RAS_COLOR_NO_MAP 0x00000000
32 : #define RAS_COLOR_RGB_MAP 0x00000001
33 : #define RAS_COLOR_RAW_MAP 0x00000002
34 :
35 : #define SUNRASTER_MAGICNUMBER 0x59a66a95
36 :
37 : //============================ RASReader ==================================
38 :
39 : class RASReader {
40 :
41 : private:
42 :
43 : SvStream& m_rRAS; // Die einzulesende RAS-Datei
44 :
45 : bool mbStatus;
46 : Bitmap maBmp;
47 : sal_uInt32 mnWidth, mnHeight; // Bildausmass in Pixeln
48 : sal_uInt16 mnDstBitsPerPix;
49 : sal_uInt16 mnDstColors;
50 : sal_uInt32 mnDepth, mnImageDatSize, mnType;
51 : sal_uInt32 mnColorMapType, mnColorMapSize;
52 : sal_uInt8 mnRepCount, mnRepVal; // RLE Decoding
53 : bool mbPalette;
54 :
55 : bool ImplReadBody(BitmapWriteAccess * pAcc);
56 : bool ImplReadHeader();
57 : sal_uInt8 ImplGetByte();
58 :
59 : public:
60 : RASReader(SvStream &rRAS);
61 : ~RASReader();
62 : bool ReadRAS(Graphic & rGraphic);
63 : };
64 :
65 : //=================== Methoden von RASReader ==============================
66 :
67 3 : RASReader::RASReader(SvStream &rRAS)
68 : : m_rRAS(rRAS)
69 : , mbStatus(true)
70 : , mnWidth(0)
71 : , mnHeight(0)
72 : , mnDstBitsPerPix(0)
73 : , mnDstColors(0)
74 : , mnDepth(0)
75 : , mnImageDatSize(0)
76 : , mnType(0)
77 : , mnColorMapType(0)
78 : , mnColorMapSize(0)
79 : , mnRepCount(0)
80 : , mnRepVal(0)
81 3 : , mbPalette(false)
82 : {
83 3 : }
84 :
85 3 : RASReader::~RASReader()
86 : {
87 3 : }
88 :
89 :
90 :
91 3 : bool RASReader::ReadRAS(Graphic & rGraphic)
92 : {
93 : sal_uInt32 nMagicNumber;
94 :
95 3 : if ( m_rRAS.GetError() )
96 0 : return false;
97 :
98 3 : m_rRAS.SetEndian( SvStreamEndian::BIG );
99 3 : m_rRAS.ReadUInt32( nMagicNumber );
100 3 : if ( nMagicNumber != SUNRASTER_MAGICNUMBER )
101 0 : return false;
102 :
103 : // Kopf einlesen:
104 :
105 3 : if ( !( mbStatus = ImplReadHeader() ) )
106 0 : return false;
107 :
108 3 : maBmp = Bitmap( Size( mnWidth, mnHeight ), mnDstBitsPerPix );
109 3 : Bitmap::ScopedWriteAccess pAcc(maBmp);
110 3 : if ( pAcc == 0 )
111 0 : return false;
112 :
113 3 : if ( mnDstBitsPerPix <= 8 ) // paletten bildchen
114 : {
115 1 : if ( mnColorMapType == RAS_COLOR_RAW_MAP ) // RAW Colormap wird geskipped
116 : {
117 0 : sal_uLong nCurPos = m_rRAS.Tell();
118 0 : m_rRAS.Seek( nCurPos + mnColorMapSize );
119 : }
120 1 : else if ( mnColorMapType == RAS_COLOR_RGB_MAP ) // RGB koennen wir auslesen
121 : {
122 1 : mnDstColors = (sal_uInt16)( mnColorMapSize / 3 );
123 :
124 1 : if ( ( 1 << mnDstBitsPerPix ) < mnDstColors )
125 1 : return false;
126 :
127 0 : if ( ( mnDstColors >= 2 ) && ( ( mnColorMapSize % 3 ) == 0 ) )
128 : {
129 0 : pAcc->SetPaletteEntryCount( mnDstColors );
130 : sal_uInt16 i;
131 : sal_uInt8 nRed[256], nGreen[256], nBlue[256];
132 0 : for ( i = 0; i < mnDstColors; i++ ) m_rRAS.ReadUChar( nRed[ i ] );
133 0 : for ( i = 0; i < mnDstColors; i++ ) m_rRAS.ReadUChar( nGreen[ i ] );
134 0 : for ( i = 0; i < mnDstColors; i++ ) m_rRAS.ReadUChar( nBlue[ i ] );
135 0 : for ( i = 0; i < mnDstColors; i++ )
136 : {
137 0 : pAcc->SetPaletteColor( i, BitmapColor( nRed[ i ], nGreen[ i ], nBlue[ i ] ) );
138 : }
139 0 : mbPalette = true;
140 : }
141 : else
142 0 : return false;
143 :
144 : }
145 0 : else if ( mnColorMapType != RAS_COLOR_NO_MAP ) // alles andere ist kein standard
146 0 : return false;
147 :
148 0 : if ( !mbPalette )
149 : {
150 0 : mnDstColors = 1 << mnDstBitsPerPix;
151 0 : pAcc->SetPaletteEntryCount( mnDstColors );
152 0 : for ( sal_uInt16 i = 0; i < mnDstColors; i++ )
153 : {
154 0 : sal_uLong nCount = 255 - ( 255 * i / ( mnDstColors - 1 ) );
155 0 : pAcc->SetPaletteColor( i, BitmapColor( (sal_uInt8)nCount, (sal_uInt8)nCount, (sal_uInt8)nCount ) );
156 : }
157 : }
158 : }
159 : else
160 : {
161 2 : if ( mnColorMapType != RAS_COLOR_NO_MAP ) // when graphic has more than 256 colors and a color map we skip
162 : { // the colormap
163 0 : sal_uLong nCurPos = m_rRAS.Tell();
164 0 : m_rRAS.Seek( nCurPos + mnColorMapSize );
165 : }
166 : }
167 :
168 : // Bitmap-Daten einlesen
169 2 : mbStatus = ImplReadBody(pAcc.get());
170 :
171 2 : if ( mbStatus )
172 2 : rGraphic = maBmp;
173 :
174 2 : return mbStatus;
175 : }
176 :
177 :
178 :
179 3 : bool RASReader::ImplReadHeader()
180 : {
181 3 : m_rRAS.ReadUInt32( mnWidth ).ReadUInt32( mnHeight ).ReadUInt32( mnDepth ).ReadUInt32( mnImageDatSize ). ReadUInt32( mnType ).ReadUInt32( mnColorMapType ).ReadUInt32( mnColorMapSize );
182 :
183 3 : if ( mnWidth == 0 || mnHeight == 0 )
184 0 : mbStatus = false;
185 :
186 3 : switch ( mnDepth )
187 : {
188 : case 24 :
189 : case 8 :
190 : case 1 :
191 3 : mnDstBitsPerPix = (sal_uInt16)mnDepth;
192 3 : break;
193 : case 32 :
194 0 : mnDstBitsPerPix = 24;
195 0 : break;
196 :
197 : default :
198 0 : mbStatus = false;
199 : }
200 :
201 3 : switch ( mnType )
202 : {
203 : case RAS_TYPE_OLD :
204 : case RAS_TYPE_STANDARD :
205 : case RAS_TYPE_RGB_FORMAT :
206 : case RAS_TYPE_BYTE_ENCODED : // this type will be supported later
207 3 : break;
208 :
209 : default:
210 0 : mbStatus = false;
211 : }
212 3 : return mbStatus;
213 : }
214 :
215 :
216 :
217 2 : bool RASReader::ImplReadBody(BitmapWriteAccess * pAcc)
218 : {
219 : sal_uLong x, y;
220 2 : sal_uInt8 nDat = 0;
221 : sal_uInt8 nRed, nGreen, nBlue;
222 2 : switch ( mnDstBitsPerPix )
223 : {
224 : case 1 :
225 0 : for ( y = 0; y < mnHeight; y++ )
226 : {
227 0 : for ( x = 0; x < mnWidth; x++ )
228 : {
229 0 : if (!(x & 7))
230 0 : nDat = ImplGetByte();
231 : pAcc->SetPixelIndex( y, x,
232 : sal::static_int_cast< sal_uInt8 >(
233 0 : nDat >> ( ( x & 7 ) ^ 7 )) );
234 : }
235 0 : if (!( ( x - 1 ) & 0x8 ) ) ImplGetByte(); // WORD ALIGNMENT ???
236 : }
237 0 : break;
238 :
239 : case 8 :
240 0 : for ( y = 0; y < mnHeight; y++ )
241 : {
242 0 : for ( x = 0; x < mnWidth; x++ )
243 : {
244 0 : nDat = ImplGetByte();
245 0 : pAcc->SetPixelIndex( y, x, nDat );
246 : }
247 0 : if ( x & 1 ) ImplGetByte(); // WORD ALIGNMENT ???
248 : }
249 0 : break;
250 :
251 : case 24 :
252 2 : switch ( mnDepth )
253 : {
254 :
255 : case 24 :
256 17539 : for ( y = 0; y < mnHeight; y++ )
257 : {
258 4794764 : for ( x = 0; x < mnWidth; x++ )
259 : {
260 4777227 : if ( mnType == RAS_TYPE_RGB_FORMAT )
261 : {
262 3356808 : nRed = ImplGetByte();
263 3356808 : nGreen = ImplGetByte();
264 3356808 : nBlue = ImplGetByte();
265 : }
266 : else
267 : {
268 1420419 : nBlue = ImplGetByte();
269 1420419 : nGreen = ImplGetByte();
270 1420419 : nRed = ImplGetByte();
271 : }
272 4777227 : pAcc->SetPixel ( y, x, BitmapColor( nRed, nGreen, nBlue ) );
273 : }
274 17537 : if ( x & 1 ) ImplGetByte(); // WORD ALIGNMENT ???
275 : }
276 2 : break;
277 :
278 : case 32 :
279 0 : for ( y = 0; y < mnHeight; y++ )
280 : {
281 0 : for ( x = 0; x < mnWidth; x++ )
282 : {
283 0 : nDat = ImplGetByte(); // pad byte > nil
284 0 : if ( mnType == RAS_TYPE_RGB_FORMAT )
285 : {
286 0 : nRed = ImplGetByte();
287 0 : nGreen = ImplGetByte();
288 0 : nBlue = ImplGetByte();
289 : }
290 : else
291 : {
292 0 : nBlue = ImplGetByte();
293 0 : nGreen = ImplGetByte();
294 0 : nRed = ImplGetByte();
295 : }
296 0 : pAcc->SetPixel ( y, x, BitmapColor( nRed, nGreen, nBlue ) );
297 : }
298 : }
299 0 : break;
300 : }
301 2 : break;
302 :
303 : default:
304 0 : mbStatus = false;
305 0 : break;
306 : }
307 2 : return mbStatus;
308 : }
309 :
310 :
311 :
312 14349218 : sal_uInt8 RASReader::ImplGetByte()
313 : {
314 : sal_uInt8 nRetVal;
315 14349218 : if ( mnType != RAS_TYPE_BYTE_ENCODED )
316 : {
317 14349218 : m_rRAS.ReadUChar( nRetVal );
318 14349218 : return nRetVal;
319 : }
320 : else
321 : {
322 0 : if ( mnRepCount )
323 : {
324 0 : mnRepCount--;
325 0 : return mnRepVal;
326 : }
327 : else
328 : {
329 0 : m_rRAS.ReadUChar( nRetVal );
330 0 : if ( nRetVal != 0x80 )
331 0 : return nRetVal;
332 0 : m_rRAS.ReadUChar( nRetVal );
333 0 : if ( nRetVal == 0 )
334 0 : return 0x80;
335 0 : mnRepCount = nRetVal ;
336 0 : m_rRAS.ReadUChar( mnRepVal );
337 0 : return mnRepVal;
338 : }
339 : }
340 : }
341 :
342 : //================== GraphicImport - die exportierte Funktion ================
343 :
344 : // this needs to be kept in sync with
345 : // ImpFilterLibCacheEntry::GetImportFunction() from
346 : // vcl/source/filter/graphicfilter.cxx
347 : #if defined(DISABLE_DYNLOADING)
348 : #define GraphicImport iraGraphicImport
349 : #endif
350 :
351 : extern "C" SAL_DLLPUBLIC_EXPORT bool SAL_CALL
352 3 : GraphicImport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* )
353 : {
354 3 : RASReader aRASReader(rStream);
355 :
356 3 : return aRASReader.ReadRAS(rGraphic );
357 : }
358 :
359 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|