1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26
27 #include <vcl/graph.hxx>
28 #include <vcl/bmpacc.hxx>
29 #include <svtools/fltcall.hxx>
30
31 #define RAS_TYPE_OLD 0x00000000 // supported formats by this filter
32 #define RAS_TYPE_STANDARD 0x00000001
33 #define RAS_TYPE_BYTE_ENCODED 0x00000002
34 #define RAS_TYPE_RGB_FORMAT 0x00000003
35
36 #define RAS_COLOR_NO_MAP 0x00000000
37 #define RAS_COLOR_RGB_MAP 0x00000001
38 #define RAS_COLOR_RAW_MAP 0x00000002
39
40 #define SUNRASTER_MAGICNUMBER 0x59a66a95
41
42 //============================ RASReader ==================================
43
44 class RASReader {
45
46 private:
47
48 SvStream* mpRAS; // Die einzulesende RAS-Datei
49
50 sal_Bool mbStatus;
51 Bitmap maBmp;
52 BitmapWriteAccess* mpAcc;
53 sal_uInt32 mnWidth, mnHeight; // Bildausmass in Pixeln
54 sal_uInt16 mnDstBitsPerPix;
55 sal_uInt16 mnDstColors;
56 sal_uInt32 mnDepth, mnImageDatSize, mnType;
57 sal_uInt32 mnColorMapType, mnColorMapSize;
58 sal_uInt8 mnRepCount, mnRepVal; // RLE Decoding
59 sal_Bool mbPalette;
60
61 sal_Bool ImplReadBody();
62 sal_Bool ImplReadHeader();
63 sal_uInt8 ImplGetByte();
64
65 public:
66 RASReader();
67 ~RASReader();
68 sal_Bool ReadRAS( SvStream & rRAS, Graphic & rGraphic );
69 };
70
71 //=================== Methoden von RASReader ==============================
72
RASReader()73 RASReader::RASReader() :
74 mbStatus ( sal_True ),
75 mpAcc ( NULL ),
76 mnRepCount ( 0 ),
77 mbPalette ( sal_False )
78 {
79 }
80
~RASReader()81 RASReader::~RASReader()
82 {
83 }
84
85 //----------------------------------------------------------------------------
86
ReadRAS(SvStream & rRAS,Graphic & rGraphic)87 sal_Bool RASReader::ReadRAS( SvStream & rRAS, Graphic & rGraphic )
88 {
89 sal_uInt32 nMagicNumber;
90
91 if ( rRAS.GetError() )
92 return sal_False;
93
94 mpRAS = &rRAS;
95 mpRAS->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
96 *mpRAS >> nMagicNumber;
97 if ( nMagicNumber != SUNRASTER_MAGICNUMBER )
98 return sal_False;
99
100 // Kopf einlesen:
101
102 if ( ( mbStatus = ImplReadHeader() ) == sal_False )
103 return sal_False;
104
105 maBmp = Bitmap( Size( mnWidth, mnHeight ), mnDstBitsPerPix );
106 mpAcc = maBmp.AcquireWriteAccess();
107 if ( !mpAcc )
108 return sal_False;
109
110 if ( mnDstBitsPerPix <= 8 ) // paletten bildchen
111 {
112 if ( mnColorMapType == RAS_COLOR_RAW_MAP ) // RAW Colormap wird geskipped
113 {
114 sal_uLong nCurPos = mpRAS->Tell();
115 mpRAS->Seek( nCurPos + mnColorMapSize );
116 }
117 else if ( mnColorMapType == RAS_COLOR_RGB_MAP ) // RGB koennen wir auslesen
118 {
119 mnDstColors = (sal_uInt16)( mnColorMapSize / 3 );
120
121 if ( ( 1 << mnDstBitsPerPix ) < mnDstColors )
122 return sal_False;
123
124 if ( ( mnDstColors >= 2 ) && ( ( mnColorMapSize % 3 ) == 0 ) )
125 {
126 mpAcc->SetPaletteEntryCount( mnDstColors );
127 sal_uInt16 i;
128 sal_uInt8 nRed[256], nGreen[256], nBlue[256];
129 for ( i = 0; i < mnDstColors; i++ ) *mpRAS >> nRed[ i ];
130 for ( i = 0; i < mnDstColors; i++ ) *mpRAS >> nGreen[ i ];
131 for ( i = 0; i < mnDstColors; i++ ) *mpRAS >> nBlue[ i ];
132 for ( i = 0; i < mnDstColors; i++ )
133 {
134 mpAcc->SetPaletteColor( i, BitmapColor( nRed[ i ], nGreen[ i ], nBlue[ i ] ) );
135 }
136 mbPalette = sal_True;
137 }
138 else
139 return sal_False;
140
141 }
142 else if ( mnColorMapType != RAS_COLOR_NO_MAP ) // alles andere ist kein standard
143 return sal_False;
144
145 if ( !mbPalette )
146 {
147 mnDstColors = 1 << mnDstBitsPerPix;
148 mpAcc->SetPaletteEntryCount( mnDstColors );
149 for ( sal_uInt16 i = 0; i < mnDstColors; i++ )
150 {
151 sal_uLong nCount = 255 - ( 255 * i / ( mnDstColors - 1 ) );
152 mpAcc->SetPaletteColor( i, BitmapColor( (sal_uInt8)nCount, (sal_uInt8)nCount, (sal_uInt8)nCount ) );
153 }
154 }
155 }
156 else
157 {
158 if ( mnColorMapType != RAS_COLOR_NO_MAP ) // when graphic has more then 256 colors and a color map we skip
159 { // the colormap
160 sal_uLong nCurPos = mpRAS->Tell();
161 mpRAS->Seek( nCurPos + mnColorMapSize );
162 }
163 }
164
165 // Bitmap-Daten einlesen
166 mbStatus = ImplReadBody();
167
168 if ( mpAcc )
169 {
170 maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
171 }
172 if ( mbStatus )
173 rGraphic = maBmp;
174
175 return mbStatus;
176 }
177
178 //----------------------------------------------------------------------------
179
ImplReadHeader()180 sal_Bool RASReader::ImplReadHeader()
181 {
182 *mpRAS >> mnWidth >> mnHeight >> mnDepth >> mnImageDatSize >>
183 mnType >> mnColorMapType >> mnColorMapSize;
184
185 if ( mnWidth == 0 || mnHeight == 0 )
186 mbStatus = sal_False;
187
188 switch ( mnDepth )
189 {
190 case 24 :
191 case 8 :
192 case 1 :
193 mnDstBitsPerPix = (sal_uInt16)mnDepth;
194 break;
195 case 32 :
196 mnDstBitsPerPix = 24;
197 break;
198
199 default :
200 mbStatus = sal_False;
201 }
202
203 switch ( mnType )
204 {
205 case RAS_TYPE_OLD :
206 case RAS_TYPE_STANDARD :
207 case RAS_TYPE_RGB_FORMAT :
208 case RAS_TYPE_BYTE_ENCODED : // this type will be supported later
209 break;
210
211 default:
212 mbStatus = sal_False;
213 }
214 return mbStatus;
215 }
216
217 //----------------------------------------------------------------------------
218
ImplReadBody()219 sal_Bool RASReader::ImplReadBody()
220 {
221 sal_uLong x, y;
222 sal_uInt8 nDat = 0;
223 sal_uInt8 nRed, nGreen, nBlue;
224 switch ( mnDstBitsPerPix )
225 {
226 case 1 :
227 for ( y = 0; y < mnHeight; y++ )
228 {
229 for ( x = 0; x < mnWidth; x++ )
230 {
231 if (!(x & 7))
232 nDat = ImplGetByte();
233 mpAcc->SetPixelIndex( y, x,
234 sal::static_int_cast< sal_uInt8 >(
235 nDat >> ( ( x & 7 ) ^ 7 )) );
236 }
237 if (!( ( x - 1 ) & 0x8 ) ) ImplGetByte(); // WORD ALIGNMENT ???
238 }
239 break;
240
241 case 8 :
242 for ( y = 0; y < mnHeight; y++ )
243 {
244 for ( x = 0; x < mnWidth; x++ )
245 {
246 nDat = ImplGetByte();
247 mpAcc->SetPixelIndex( y, x, nDat );
248 }
249 if ( x & 1 ) ImplGetByte(); // WORD ALIGNMENT ???
250 }
251 break;
252
253 case 24 :
254 switch ( mnDepth )
255 {
256
257 case 24 :
258 for ( y = 0; y < mnHeight; y++ )
259 {
260 for ( x = 0; x < mnWidth; x++ )
261 {
262 if ( mnType == RAS_TYPE_RGB_FORMAT )
263 {
264 nRed = ImplGetByte();
265 nGreen = ImplGetByte();
266 nBlue = ImplGetByte();
267 }
268 else
269 {
270 nBlue = ImplGetByte();
271 nGreen = ImplGetByte();
272 nRed = ImplGetByte();
273 }
274 mpAcc->SetPixel ( y, x, BitmapColor( nRed, nGreen, nBlue ) );
275 }
276 if ( x & 1 ) ImplGetByte(); // WORD ALIGNMENT ???
277 }
278 break;
279
280 case 32 :
281 for ( y = 0; y < mnHeight; y++ )
282 {
283 for ( x = 0; x < mnWidth; x++ )
284 {
285 nDat = ImplGetByte(); // pad byte > nil
286 if ( mnType == RAS_TYPE_RGB_FORMAT )
287 {
288 nRed = ImplGetByte();
289 nGreen = ImplGetByte();
290 nBlue = ImplGetByte();
291 }
292 else
293 {
294 nBlue = ImplGetByte();
295 nGreen = ImplGetByte();
296 nRed = ImplGetByte();
297 }
298 mpAcc->SetPixel ( y, x, BitmapColor( nRed, nGreen, nBlue ) );
299 }
300 }
301 break;
302 }
303 break;
304
305 default:
306 mbStatus = sal_False;
307 break;
308 }
309 return mbStatus;
310 }
311
312 //----------------------------------------------------------------------------
313
ImplGetByte()314 sal_uInt8 RASReader::ImplGetByte()
315 {
316 sal_uInt8 nRetVal;
317 if ( mnType != RAS_TYPE_BYTE_ENCODED )
318 {
319 *mpRAS >> nRetVal;
320 return nRetVal;
321 }
322 else
323 {
324 if ( mnRepCount )
325 {
326 mnRepCount--;
327 return mnRepVal;
328 }
329 else
330 {
331 *mpRAS >> nRetVal;
332 if ( nRetVal != 0x80 )
333 return nRetVal;
334 *mpRAS >> nRetVal;
335 if ( nRetVal == 0 )
336 return 0x80;
337 mnRepCount = nRetVal ;
338 *mpRAS >> mnRepVal;
339 return mnRepVal;
340 }
341 }
342 }
343
344 //================== GraphicImport - die exportierte Funktion ================
345
GraphicImport(SvStream & rStream,Graphic & rGraphic,FilterConfigItem *,sal_Bool)346 extern "C" sal_Bool __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, sal_Bool )
347 {
348 RASReader aRASReader;
349
350 return aRASReader.ReadRAS( rStream, rGraphic );
351 }
352
353