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