xref: /AOO42X/main/filter/source/graphicfilter/iras/iras.cxx (revision b1c5455db1639c48e26c568e4fa7ee78ca5d60ee)
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