xref: /AOO41X/main/filter/source/graphicfilter/eras/eras.cxx (revision 87bc88d3ed834c36654f277ed18005c290f77bdd)
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 #include <svtools/FilterConfigItem.hxx>
31 
32 //============================ RASWriter ==================================
33 
34 class RASWriter {
35 
36 private:
37 
38     SvStream*           mpOStm;
39     sal_uInt16              mpOStmOldModus;
40 
41     sal_Bool                mbStatus;
42     BitmapReadAccess*   mpAcc;
43 
44     sal_uLong               mnWidth, mnHeight;
45     sal_uInt16              mnColors, mnDepth;
46 
47     sal_uLong               mnRepCount;
48     sal_uInt8               mnRepVal;
49 
50     com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
51 
52     void                ImplCallback( sal_uLong nCurrentYPos );
53     sal_Bool                ImplWriteHeader();
54     void                ImplWritePalette();
55     void                ImplWriteBody();
56     void                ImplPutByte( sal_uInt8 );   // RLE decoding
57 
58 public:
59                         RASWriter();
60                         ~RASWriter();
61 
62     sal_Bool                WriteRAS( const Graphic& rGraphic, SvStream& rRAS, FilterConfigItem* pFilterConfigItem );
63 };
64 
65 //=================== Methoden von RASWriter ==============================
66 
RASWriter()67 RASWriter::RASWriter() :
68     mbStatus    ( sal_True ),
69     mpAcc       ( NULL ),
70     mnRepCount  ( 0xffffffff )
71 {
72 }
73 
74 // ------------------------------------------------------------------------
75 
~RASWriter()76 RASWriter::~RASWriter()
77 {
78 }
79 
80 // ------------------------------------------------------------------------
81 
ImplCallback(sal_uLong nYPos)82 void RASWriter::ImplCallback( sal_uLong nYPos )
83 {
84     if ( xStatusIndicator.is() )
85         xStatusIndicator->setValue( (sal_uInt16)( ( 100 * nYPos ) / mnHeight ) );
86 }
87 
88 //  ------------------------------------------------------------------------
89 
WriteRAS(const Graphic & rGraphic,SvStream & rRAS,FilterConfigItem * pFilterConfigItem)90 sal_Bool RASWriter::WriteRAS( const Graphic& rGraphic, SvStream& rRAS, FilterConfigItem* pFilterConfigItem)
91 {
92     Bitmap  aBmp;
93 
94     mpOStm = &rRAS;
95 
96     if ( pFilterConfigItem )
97     {
98         xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
99         if ( xStatusIndicator.is() )
100         {
101             rtl::OUString aMsg;
102             xStatusIndicator->start( aMsg, 100 );
103         }
104     }
105 
106     BitmapEx    aBmpEx( rGraphic.GetBitmapEx() );
107     aBmp = aBmpEx.GetBitmap();
108 
109     if ( aBmp.GetBitCount() == 4 )
110         aBmp.Convert( BMP_CONVERSION_8BIT_COLORS );
111 
112     mnDepth = aBmp.GetBitCount();
113 
114     // export code below only handles three discrete cases
115     mnDepth = mnDepth <= 1 ? 1 : mnDepth <= 8 ? 8 : 24;
116 
117     mpAcc = aBmp.AcquireReadAccess();
118     if ( mpAcc )
119     {
120         mpOStmOldModus = mpOStm->GetNumberFormatInt();
121         mpOStm->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
122 
123         if ( ImplWriteHeader() )
124         {
125             if ( mnDepth <= 8 )
126                 ImplWritePalette();
127             ImplWriteBody();
128         }
129         aBmp.ReleaseAccess( mpAcc );
130     }
131     else
132         mbStatus = sal_False;
133 
134     mpOStm->SetNumberFormatInt( mpOStmOldModus );
135 
136     if ( xStatusIndicator.is() )
137         xStatusIndicator->end();
138 
139     return mbStatus;
140 }
141 
142 // ------------------------------------------------------------------------
143 
ImplWriteHeader()144 sal_Bool RASWriter::ImplWriteHeader()
145 {
146     mnWidth = mpAcc->Width();
147     mnHeight = mpAcc->Height();
148     if ( mnDepth <= 8 )
149     {
150         mnColors = mpAcc->GetPaletteEntryCount();
151         if (mnColors == 0)
152             mbStatus = sal_False;
153     }
154         if ( mbStatus && mnWidth && mnHeight && mnDepth )
155     {
156         *mpOStm << (sal_uInt32)0x59a66a95 << (sal_uInt32)mnWidth << (sal_uInt32)mnHeight
157             << (sal_uInt32)mnDepth
158             << (sal_uInt32)(( ( ( ( mnWidth * mnDepth ) + 15 ) >> 4 ) << 1 ) * mnHeight)
159             << (sal_uInt32)2;
160 
161         if ( mnDepth > 8 )
162             *mpOStm << (sal_uInt32)0 << (sal_uInt32)0;
163         else
164         {
165 
166             *mpOStm << (sal_uInt32)1 << (sal_uInt32)( mnColors * 3 );
167         }
168     }
169     else mbStatus = sal_False;
170 
171     return mbStatus;
172 }
173 
174 // ------------------------------------------------------------------------
175 
ImplWritePalette()176 void RASWriter::ImplWritePalette()
177 {
178     sal_uInt16 i;
179 
180     for ( i = 0; i < mnColors; *mpOStm << mpAcc->GetPaletteColor( i++ ).GetRed() ) ;
181     for ( i = 0; i < mnColors; *mpOStm << mpAcc->GetPaletteColor( i++ ).GetGreen() ) ;
182     for ( i = 0; i < mnColors; *mpOStm << mpAcc->GetPaletteColor( i++ ).GetBlue() ) ;
183 }
184 
185 // ------------------------------------------------------------------------
186 
ImplWriteBody()187 void RASWriter::ImplWriteBody()
188 {
189     sal_uLong   x, y;
190 
191     if ( mnDepth == 24 )
192     {
193         for ( y = 0; y < mnHeight; y++ )
194         {
195             ImplCallback( y );                              // processing output
196             for ( x = 0; x < mnWidth; x++ )
197             {
198                 BitmapColor aColor( mpAcc->GetPixel( y, x ) );
199                 ImplPutByte( aColor.GetBlue() );            // Format ist BGR
200                 ImplPutByte( aColor.GetGreen() );
201                 ImplPutByte( aColor.GetRed() );
202             }
203             if ( x & 1 ) ImplPutByte( 0 );      // WORD ALIGNMENT ???
204         }
205     }
206     else if ( mnDepth == 8 )
207     {
208         for ( y = 0; y < mnHeight; y++ )
209         {
210             ImplCallback( y );                              // processing output
211             for ( x = 0; x < mnWidth; x++ )
212             {
213                 ImplPutByte ( mpAcc->GetPixelIndex( y, x ) );
214             }
215             if ( x & 1 ) ImplPutByte( 0 );      // WORD ALIGNMENT ???
216         }
217     }
218     else if ( mnDepth == 1 )
219     {
220         sal_uInt8 nDat = 0;
221 
222         for ( y = 0; y < mnHeight; y++ )
223         {
224             ImplCallback( y );                              // processing output
225             for ( x = 0; x < mnWidth; x++ )
226             {
227                 nDat = ( ( nDat << 1 ) | ( mpAcc->GetPixelIndex( y, x ) & 1 ) );
228                 if ( ( x & 7 ) == 7 )
229                     ImplPutByte( nDat );
230             }
231             if ( x & 7 )
232                 ImplPutByte( sal::static_int_cast< sal_uInt8 >(nDat << ( ( ( x & 7 ) ^ 7 ) + 1)) );// write remaining bits
233             if (!( ( x - 1 ) & 0x8 ) )
234                 ImplPutByte( 0 );               // WORD ALIGNMENT ???
235         }
236     }
237     ImplPutByte( mnRepVal + 1 );    // end of RLE decoding
238 }
239 
240 // ------------------------------------------------------------------------
241 
ImplPutByte(sal_uInt8 nPutThis)242 void RASWriter::ImplPutByte( sal_uInt8 nPutThis )
243 {
244     if ( mnRepCount == 0xffffffff )
245     {
246         mnRepCount = 0;
247         mnRepVal = nPutThis;
248     }
249     else
250     {
251         if ( ( nPutThis == mnRepVal ) && ( mnRepCount != 0xff ) )
252             mnRepCount++;
253         else
254         {
255             if ( mnRepCount == 0 )
256             {
257                 *mpOStm << (sal_uInt8)mnRepVal;
258                 if ( mnRepVal == 0x80 )
259                     *mpOStm << (sal_uInt8)0;
260             }
261             else
262             {
263                 *mpOStm << (sal_uInt8)0x80;
264                 *mpOStm << (sal_uInt8)mnRepCount;
265                 *mpOStm << (sal_uInt8)mnRepVal;
266             }
267             mnRepVal = nPutThis;
268             mnRepCount = 0;
269         }
270     }
271 }
272 
273 // ------------------------------------------------------------------------
274 
275 // ---------------------
276 // - exported function -
277 // ---------------------
278 
GraphicExport(SvStream & rStream,Graphic & rGraphic,FilterConfigItem * pFilterConfigItem,sal_Bool)279 extern "C" sal_Bool __LOADONCALLAPI GraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pFilterConfigItem, sal_Bool )
280 {
281     RASWriter aRASWriter;
282 
283     return aRASWriter.WriteRAS( rGraphic, rStream, pFilterConfigItem );
284 }
285