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