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