xref: /AOO41X/main/filter/source/graphicfilter/expm/expm.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 
31 //============================ XPMWriter ==================================
32 
33 class XPMWriter {
34 
35 private:
36 
37     SvStream*           mpOStm;             // Die auszugebende XPM-Datei
38     sal_uInt16              mpOStmOldModus;
39 
40     sal_Bool                mbStatus;
41     sal_Bool                mbTrans;
42     BitmapReadAccess*   mpAcc;
43     sal_uLong               mnWidth, mnHeight;  // Bildausmass in Pixeln
44     sal_uInt16              mnColors;
45 
46     com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
47 
48     void                ImplCallback( sal_uInt16 nPercent );
49     sal_Bool                ImplWriteHeader();
50     void                ImplWritePalette();
51     void                ImplWriteColor( sal_uInt16 );
52     void                ImplWriteBody();
53     void                ImplWriteNumber( sal_Int32 );
54     void                ImplWritePixel( sal_uLong );
55 
56 public:
57                         XPMWriter();
58                         ~XPMWriter();
59 
60     sal_Bool                WriteXPM( const Graphic& rGraphic, SvStream& rXPM, FilterConfigItem* pFilterConfigItem );
61 };
62 
63 //=================== Methoden von XPMWriter ==============================
64 
XPMWriter()65 XPMWriter::XPMWriter() :
66     mbStatus    ( sal_True ),
67     mbTrans     ( sal_False ),
68     mpAcc       ( NULL )
69 {
70 }
71 
72 // ------------------------------------------------------------------------
73 
~XPMWriter()74 XPMWriter::~XPMWriter()
75 {
76 }
77 
78 // ------------------------------------------------------------------------
79 
ImplCallback(sal_uInt16 nPercent)80 void XPMWriter::ImplCallback( sal_uInt16 nPercent )
81 {
82     if ( xStatusIndicator.is() )
83     {
84         if ( nPercent <= 100 )
85             xStatusIndicator->setValue( nPercent );
86     }
87 }
88 
89 //  ------------------------------------------------------------------------
90 
WriteXPM(const Graphic & rGraphic,SvStream & rXPM,FilterConfigItem * pFilterConfigItem)91 sal_Bool XPMWriter::WriteXPM( const Graphic& rGraphic, SvStream& rXPM, FilterConfigItem* pFilterConfigItem)
92 {
93     Bitmap  aBmp;
94 
95     mpOStm = &rXPM;
96 
97     if ( pFilterConfigItem )
98     {
99         xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
100         if ( xStatusIndicator.is() )
101         {
102             rtl::OUString aMsg;
103             xStatusIndicator->start( aMsg, 100 );
104         }
105     }
106 
107     BitmapEx    aBmpEx( rGraphic.GetBitmapEx() );
108     aBmp = aBmpEx.GetBitmap();
109 
110     if ( rGraphic.IsTransparent() )                 // event. transparente Farbe erzeugen
111     {
112         mbTrans = sal_True;
113         if ( aBmp.GetBitCount() >= 8 )              // wenn noetig Bild auf 8 bit konvertieren
114             aBmp.Convert( BMP_CONVERSION_8BIT_TRANS );
115         else
116             aBmp.Convert( BMP_CONVERSION_4BIT_TRANS );
117         aBmp.Replace( aBmpEx.GetMask(), BMP_COL_TRANS );
118     }
119     else
120     {
121         if ( aBmp.GetBitCount() > 8 )               // wenn noetig Bild auf 8 bit konvertieren
122             aBmp.Convert( BMP_CONVERSION_8BIT_COLORS );
123     }
124     mpAcc = aBmp.AcquireReadAccess();
125     if ( mpAcc )
126     {
127         mnColors = mpAcc->GetPaletteEntryCount();
128         mpOStmOldModus = mpOStm->GetNumberFormatInt();
129         mpOStm->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
130 
131         if ( ImplWriteHeader() )
132         {
133             ImplWritePalette();
134             ImplWriteBody();
135             *mpOStm << "\x22XPMENDEXT\x22\x0a};";
136         }
137         aBmp.ReleaseAccess( mpAcc );
138     }
139     else
140         mbStatus = sal_False;
141 
142     mpOStm->SetNumberFormatInt( mpOStmOldModus );
143 
144     if ( xStatusIndicator.is() )
145         xStatusIndicator->end();
146 
147     return mbStatus;
148 }
149 
150 // ------------------------------------------------------------------------
151 
ImplWriteHeader()152 sal_Bool XPMWriter::ImplWriteHeader()
153 {
154     mnWidth = mpAcc->Width();
155     mnHeight = mpAcc->Height();
156     if ( mnWidth && mnHeight && mnColors )
157     {
158         *mpOStm << "/* XPM */\x0astatic char * image[] = \x0a{\x0a\x22";
159         ImplWriteNumber( mnWidth );
160         *mpOStm << (sal_uInt8)32;
161         ImplWriteNumber( mnHeight );
162         *mpOStm << (sal_uInt8)32;
163         ImplWriteNumber( mnColors );
164         *mpOStm << (sal_uInt8)32;
165         ImplWriteNumber( ( mnColors > 26 ) ? 2 : 1 );
166         *mpOStm << "\x22,\x0a";
167     }
168     else mbStatus = sal_False;
169     return mbStatus;
170 }
171 
172 // ------------------------------------------------------------------------
173 
ImplWritePalette()174 void XPMWriter::ImplWritePalette()
175 {
176     sal_uInt16 nTransIndex = 0xffff;
177 
178     if ( mbTrans )
179         nTransIndex = mpAcc->GetBestPaletteIndex( BMP_COL_TRANS );
180     for ( sal_uInt16 i = 0; i < mnColors; i++ )
181     {
182         *mpOStm << "\x22";
183         ImplWritePixel( i );
184         *mpOStm << (sal_uInt8)32;
185         if ( nTransIndex != i )
186         {
187             ImplWriteColor( i );
188             *mpOStm << "\x22,\x0a";
189         }
190         else
191             *mpOStm << "c none\x22,\x0a";
192     }
193 }
194 
195 // ------------------------------------------------------------------------
196 
ImplWriteBody()197 void XPMWriter::ImplWriteBody()
198 {
199     for ( sal_uLong y = 0; y < mnHeight; y++ )
200     {
201         ImplCallback( (sal_uInt16)( ( 100 * y ) / mnHeight ) );         // processing output in percent
202         *mpOStm << (sal_uInt8)0x22;
203         for ( sal_uLong x = 0; x < mnWidth; x++ )
204         {
205             ImplWritePixel( mpAcc->GetPixelIndex( y, x ) );
206         }
207         *mpOStm << "\x22,\x0a";
208     }
209 }
210 
211 // ------------------------------------------------------------------------
212 // eine Dezimalzahl im ASCII format wird in den Stream geschrieben
213 
ImplWriteNumber(sal_Int32 nNumber)214 void XPMWriter::ImplWriteNumber( sal_Int32 nNumber )
215 {
216     const ByteString aNum( ByteString::CreateFromInt32( nNumber ) );
217 
218     for( sal_Int16 n = 0UL, nLen = aNum.Len(); n < nLen; n++  )
219         *mpOStm << aNum.GetChar( n );
220 
221 }
222 
223 // ------------------------------------------------------------------------
224 
ImplWritePixel(sal_uLong nCol)225 void XPMWriter::ImplWritePixel( sal_uLong nCol )
226 {
227     if ( mnColors > 26 )
228     {
229         sal_uInt8 nDiff = (sal_uInt8) ( nCol / 26 );
230         *mpOStm << (sal_uInt8)( nDiff + 'A' );
231         *mpOStm << (sal_uInt8)( nCol - ( nDiff*26 ) + 'A' );
232     }
233     else
234         *mpOStm << (sal_uInt8)( nCol + 'A' );
235 }
236 
237 // ------------------------------------------------------------------------
238 // ein Farbwert wird im Hexadezimalzahlformat in den Stream geschrieben
ImplWriteColor(sal_uInt16 nNumber)239 void XPMWriter::ImplWriteColor( sal_uInt16 nNumber )
240 {
241     sal_uLong   nTmp;
242     sal_uInt8   j;
243 
244     *mpOStm << "c #";   // # zeigt einen folgenden Hexwert an
245     const BitmapColor& rColor = mpAcc->GetPaletteColor( nNumber );
246     nTmp = ( rColor.GetRed() << 16 ) | ( rColor.GetGreen() << 8 ) | rColor.GetBlue();
247     for ( signed char i = 20; i >= 0 ; i-=4 )
248     {
249         if ( ( j = (sal_uInt8)( nTmp >> i ) & 0xf ) > 9 )
250             j += 'A' - 10;
251         else
252             j += '0';
253         *mpOStm << j;
254     }
255 }
256 
257 // ------------------------------------------------------------------------
258 
259 // ---------------------
260 // - exported function -
261 // ---------------------
262 
GraphicExport(SvStream & rStream,Graphic & rGraphic,FilterConfigItem * pFilterConfigItem,sal_Bool)263 extern "C" sal_Bool __LOADONCALLAPI GraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pFilterConfigItem, sal_Bool )
264 {
265     XPMWriter aXPMWriter;
266 
267     return aXPMWriter.WriteXPM( rGraphic, rStream, pFilterConfigItem );
268 }
269 
270