Update ooo320-m1
[ooovba.git] / goodies / source / filter.vcl / egif / egif.cxx
blob07ec6529a77f2380396489ffc60bad12a7c13566
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: egif.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_goodies.hxx"
34 #include <vcl/graph.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <vcl/window.hxx>
38 #include <svtools/solar.hrc>
39 #include <svtools/fltcall.hxx>
40 #include <svtools/FilterConfigItem.hxx>
41 #include "giflzwc.hxx"
42 #include "strings.hrc"
43 #include "dlgegif.hrc"
44 #include "dlgegif.hxx"
46 // -------------
47 // - GIFWriter -
48 // -------------
50 class GIFWriter
52 Bitmap aAccBmp;
53 BitmapReadAccess* pAcc;
54 SvStream* pGIF;
55 ULONG nMinPercent;
56 ULONG nMaxPercent;
57 ULONG nLastPercent;
58 long nActX;
59 long nActY;
60 sal_Int32 nInterlaced;
61 BOOL bStatus;
62 BOOL bTransparent;
64 void MayCallback( ULONG nPercent );
65 void WriteSignature( BOOL bGIF89a );
66 void WriteGlobalHeader( const Size& rSize );
67 void WriteLoopExtension( const Animation& rAnimation );
68 void WriteLogSizeExtension( const Size& rSize100 );
69 void WriteImageExtension( long nTimer, Disposal eDisposal );
70 void WriteLocalHeader();
71 void WritePalette();
72 void WriteAccess();
73 void WriteTerminator();
75 BOOL CreateAccess( const BitmapEx& rBmpEx );
76 void DestroyAccess();
78 void WriteAnimation( const Animation& rAnimation );
79 void WriteBitmapEx( const BitmapEx& rBmpEx, const Point& rPoint, BOOL bExtended,
80 long nTimer = 0, Disposal eDisposal = DISPOSE_NOT );
82 com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
84 public:
86 GIFWriter() {}
87 ~GIFWriter() {}
89 BOOL WriteGIF( const Graphic& rGraphic, SvStream& rGIF,
90 FilterConfigItem* pConfigItem );
93 // ------------------------------------------------------------------------
95 BOOL GIFWriter::WriteGIF( const Graphic& rGraphic, SvStream& rGIF,
96 FilterConfigItem* pFilterConfigItem )
98 if ( pFilterConfigItem )
100 xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
101 if ( xStatusIndicator.is() )
103 rtl::OUString aMsg;
104 xStatusIndicator->start( aMsg, 100 );
108 Size aSize100;
109 const MapMode aMap( rGraphic.GetPrefMapMode() );
110 BOOL bLogSize = ( aMap.GetMapUnit() != MAP_PIXEL );
112 if( bLogSize )
113 aSize100 = Application::GetDefaultDevice()->LogicToLogic( rGraphic.GetPrefSize(), aMap, MAP_100TH_MM );
115 pGIF = &rGIF;
116 bStatus = TRUE;
117 nLastPercent = 0;
118 nInterlaced = 0;
119 pAcc = NULL;
121 if ( pFilterConfigItem )
122 nInterlaced = pFilterConfigItem->ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Interlaced" ) ), 0 );
124 pGIF->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
126 if( rGraphic.IsAnimated() )
128 const Animation& rAnimation = rGraphic.GetAnimation();
130 WriteSignature( TRUE );
132 if ( bStatus )
134 WriteGlobalHeader( rAnimation.GetDisplaySizePixel() );
136 if( bStatus )
138 WriteLoopExtension( rAnimation );
140 if( bStatus )
141 WriteAnimation( rAnimation );
145 else
147 const BOOL bGrafTrans = rGraphic.IsTransparent();
149 BitmapEx aBmpEx;
151 if( bGrafTrans )
152 aBmpEx = rGraphic.GetBitmapEx();
153 else
154 aBmpEx = BitmapEx( rGraphic.GetBitmap() );
156 nMinPercent = 0;
157 nMaxPercent = 100;
159 WriteSignature( bGrafTrans || bLogSize );
161 if( bStatus )
163 WriteGlobalHeader( aBmpEx.GetSizePixel() );
165 if( bStatus )
166 WriteBitmapEx( aBmpEx, Point(), bGrafTrans );
170 if( bStatus )
172 if( bLogSize )
173 WriteLogSizeExtension( aSize100 );
175 WriteTerminator();
178 if ( xStatusIndicator.is() )
179 xStatusIndicator->end();
181 return bStatus;
184 // ------------------------------------------------------------------------
186 void GIFWriter::WriteBitmapEx( const BitmapEx& rBmpEx, const Point& rPoint,
187 BOOL bExtended, long nTimer, Disposal eDisposal )
189 if( CreateAccess( rBmpEx ) )
191 nActX = rPoint.X();
192 nActY = rPoint.Y();
194 if( bExtended )
195 WriteImageExtension( nTimer, eDisposal );
197 if( bStatus )
199 WriteLocalHeader();
201 if( bStatus )
203 WritePalette();
205 if( bStatus )
206 WriteAccess();
210 DestroyAccess();
214 // ------------------------------------------------------------------------
216 void GIFWriter::WriteAnimation( const Animation& rAnimation )
218 const USHORT nCount = rAnimation.Count();
220 if( nCount )
222 const double fStep = 100. / nCount;
224 nMinPercent = 0L;
225 nMaxPercent = (ULONG) fStep;
227 for( USHORT i = 0; i < nCount; i++ )
229 const AnimationBitmap& rAnimBmp = rAnimation.Get( i );
231 WriteBitmapEx( rAnimBmp.aBmpEx, rAnimBmp.aPosPix, TRUE,
232 rAnimBmp.nWait, rAnimBmp.eDisposal );
233 nMinPercent = nMaxPercent;
234 nMaxPercent = (ULONG) ( nMaxPercent + fStep );
239 // ------------------------------------------------------------------------
241 void GIFWriter::MayCallback( ULONG nPercent )
243 if ( xStatusIndicator.is() )
245 if( nPercent >= nLastPercent + 3 )
247 nLastPercent = nPercent;
248 if ( nPercent <= 100 )
249 xStatusIndicator->setValue( nPercent );
254 // ------------------------------------------------------------------------
256 BOOL GIFWriter::CreateAccess( const BitmapEx& rBmpEx )
258 if( bStatus )
260 Bitmap aMask( rBmpEx.GetMask() );
262 aAccBmp = rBmpEx.GetBitmap();
263 bTransparent = FALSE;
265 if( !!aMask )
267 if( aAccBmp.Convert( BMP_CONVERSION_8BIT_TRANS ) )
269 aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
270 aAccBmp.Replace( aMask, BMP_COL_TRANS );
271 bTransparent = TRUE;
273 else
274 aAccBmp.Convert( BMP_CONVERSION_8BIT_COLORS );
276 else
277 aAccBmp.Convert( BMP_CONVERSION_8BIT_COLORS );
279 pAcc = aAccBmp.AcquireReadAccess();
281 if( !pAcc )
282 bStatus = FALSE;
285 return bStatus;
288 // ------------------------------------------------------------------------
290 void GIFWriter::DestroyAccess()
292 aAccBmp.ReleaseAccess( pAcc );
293 pAcc = NULL;
296 // ------------------------------------------------------------------------
298 void GIFWriter::WriteSignature( BOOL bGIF89a )
300 if( bStatus )
302 pGIF->Write( bGIF89a ? "GIF89a" : "GIF87a" , 6 );
304 if( pGIF->GetError() )
305 bStatus = FALSE;
309 // ------------------------------------------------------------------------
311 void GIFWriter::WriteGlobalHeader( const Size& rSize )
313 if( bStatus )
315 // 256 Farben
316 const UINT16 nWidth = (UINT16) rSize.Width();
317 const UINT16 nHeight = (UINT16) rSize.Height();
318 const BYTE cFlags = 128 | ( 7 << 4 );
320 // Werte rausschreiben
321 *pGIF << nWidth;
322 *pGIF << nHeight;
323 *pGIF << cFlags;
324 *pGIF << (BYTE) 0x00;
325 *pGIF << (BYTE) 0x00;
327 // Dummy-Palette mit zwei Eintraegen (Schwarz/Weiss) schreiben;
328 // dieses nur wegen Photoshop-Bug, da die keine Bilder ohne
329 // globale Farbpalette lesen koennen
330 *pGIF << (UINT16) 0;
331 *pGIF << (UINT16) 255;
332 *pGIF << (UINT16) 65535;
334 if( pGIF->GetError() )
335 bStatus = FALSE;
339 // ------------------------------------------------------------------------
341 void GIFWriter::WriteLoopExtension( const Animation& rAnimation )
343 DBG_ASSERT( rAnimation.Count() > 0, "Animation has no bitmaps!" );
345 USHORT nLoopCount = (USHORT) rAnimation.GetLoopCount();
347 // falls nur ein Durchlauf stattfinden soll,
348 // wird keine LoopExtension geschrieben;
349 // Default ist dann immer ein Durchlauf
350 if( nLoopCount != 1 )
352 // Netscape interpretiert den LoopCount
353 // als reine Anzahl der _Wiederholungen_
354 if( nLoopCount )
355 nLoopCount--;
357 const BYTE cLoByte = (const BYTE) nLoopCount;
358 const BYTE cHiByte = (const BYTE) ( nLoopCount >> 8 );
360 *pGIF << (BYTE) 0x21;
361 *pGIF << (BYTE) 0xff;
362 *pGIF << (BYTE) 0x0b;
363 pGIF->Write( "NETSCAPE2.0", 11 );
364 *pGIF << (BYTE) 0x03;
365 *pGIF << (BYTE) 0x01;
366 *pGIF << cLoByte;
367 *pGIF << cHiByte;
368 *pGIF << (BYTE) 0x00;
372 // ------------------------------------------------------------------------
374 void GIFWriter::WriteLogSizeExtension( const Size& rSize100 )
376 // PrefSize in 100th-mm als ApplicationExtension schreiben
377 if( rSize100.Width() && rSize100.Height() )
379 *pGIF << (BYTE) 0x21;
380 *pGIF << (BYTE) 0xff;
381 *pGIF << (BYTE) 0x0b;
382 pGIF->Write( "STARDIV 5.0", 11 );
383 *pGIF << (BYTE) 0x09;
384 *pGIF << (BYTE) 0x01;
385 *pGIF << (UINT32) rSize100.Width();
386 *pGIF << (UINT32) rSize100.Height();
387 *pGIF << (BYTE) 0x00;
391 // ------------------------------------------------------------------------
393 void GIFWriter::WriteImageExtension( long nTimer, Disposal eDisposal )
395 if( bStatus )
397 const UINT16 nDelay = (UINT16) nTimer;
398 BYTE cFlags = 0;
400 // Transparent-Flag setzen
401 if( bTransparent )
402 cFlags |= 1;
404 // Disposal-Wert setzen
405 if( eDisposal == DISPOSE_BACK )
406 cFlags |= ( 2 << 2 );
407 else if( eDisposal == DISPOSE_PREVIOUS )
408 cFlags |= ( 3 << 2 );
410 *pGIF << (BYTE) 0x21;
411 *pGIF << (BYTE) 0xf9;
412 *pGIF << (BYTE) 0x04;
413 *pGIF << cFlags;
414 *pGIF << nDelay;
415 *pGIF << (BYTE) pAcc->GetBestPaletteIndex( BMP_COL_TRANS );
416 *pGIF << (BYTE) 0x00;
418 if( pGIF->GetError() )
419 bStatus = FALSE;
423 // ------------------------------------------------------------------------
425 void GIFWriter::WriteLocalHeader()
427 if( bStatus )
429 const UINT16 nPosX = (UINT16) nActX;
430 const UINT16 nPosY = (UINT16) nActY;
431 const UINT16 nWidth = (UINT16) pAcc->Width();
432 const UINT16 nHeight = (UINT16) pAcc->Height();
433 BYTE cFlags = (BYTE) ( pAcc->GetBitCount() - 1 );
435 // Interlaced-Flag setzen
436 if( nInterlaced )
437 cFlags |= 0x40;
439 // Flag fuer lokale Farbpalette setzen
440 cFlags |= 0x80;
442 // alles rausschreiben
443 *pGIF << (BYTE) 0x2c;
444 *pGIF << nPosX;
445 *pGIF << nPosY;
446 *pGIF << nWidth;
447 *pGIF << nHeight;
448 *pGIF << cFlags;
450 if( pGIF->GetError() )
451 bStatus = FALSE;
455 // ------------------------------------------------------------------------
457 void GIFWriter::WritePalette()
459 if( bStatus && pAcc->HasPalette() )
461 const USHORT nCount = pAcc->GetPaletteEntryCount();
462 const USHORT nMaxCount = ( 1 << pAcc->GetBitCount() );
464 for ( USHORT i = 0; i < nCount; i++ )
466 const BitmapColor& rColor = pAcc->GetPaletteColor( i );
468 *pGIF << rColor.GetRed();
469 *pGIF << rColor.GetGreen();
470 *pGIF << rColor.GetBlue();
473 // Rest mit 0 auffuellen
474 if( nCount < nMaxCount )
475 pGIF->SeekRel( ( nMaxCount - nCount ) * 3 );
477 if( pGIF->GetError() )
478 bStatus = FALSE;
482 // ------------------------------------------------------------------------
484 void GIFWriter::WriteAccess()
486 GIFLZWCompressor aCompressor;
487 const long nWidth = pAcc->Width();
488 const long nHeight = pAcc->Height();
489 BYTE* pBuffer = NULL;
490 const ULONG nFormat = pAcc->GetScanlineFormat();
491 long nY;
492 long nT;
493 long i;
494 BOOL bNative = ( BMP_FORMAT_8BIT_PAL == nFormat );
496 if( !bNative )
497 pBuffer = new BYTE[ nWidth ];
499 if( bStatus && ( 8 == pAcc->GetBitCount() ) && pAcc->HasPalette() )
501 aCompressor.StartCompression( *pGIF, pAcc->GetBitCount() );
503 for( i = 0; i < nHeight; i++ )
505 if( nInterlaced )
507 nY = i << 3;
509 if( nY >= nHeight )
511 nT = i - ( ( nHeight + 7 ) >> 3 );
512 nY= ( nT << 3 ) + 4;
514 if( nY >= nHeight )
516 nT -= ( nHeight + 3 ) >> 3;
517 nY = ( nT << 2 ) + 2;
519 if ( nY >= nHeight )
521 nT -= ( ( nHeight + 1 ) >> 2 );
522 nY = ( nT << 1 ) + 1;
527 else
528 nY = i;
530 if( bNative )
531 aCompressor.Compress( pAcc->GetScanline( nY ), nWidth );
532 else
534 for( long nX = 0L; nX < nWidth; nX++ )
535 pBuffer[ nX ] = (BYTE) pAcc->GetPixel( nY, nX );
537 aCompressor.Compress( pBuffer, nWidth );
540 if ( pGIF->GetError() )
541 bStatus = FALSE;
543 MayCallback( nMinPercent + ( nMaxPercent - nMinPercent ) * i / nHeight );
545 if( !bStatus )
546 break;
549 aCompressor.EndCompression();
551 if ( pGIF->GetError() )
552 bStatus = FALSE;
555 delete[] pBuffer;
558 // ------------------------------------------------------------------------
560 void GIFWriter::WriteTerminator()
562 if( bStatus )
564 *pGIF << (BYTE) 0x3b;
566 if( pGIF->GetError() )
567 bStatus = FALSE;
571 // ------------------------------------------------------------------------
573 extern "C" BOOL __LOADONCALLAPI GraphicExport( SvStream& rStream, Graphic& rGraphic,
574 FilterConfigItem* pConfigItem, BOOL )
576 return GIFWriter().WriteGIF( rGraphic, rStream, pConfigItem );
579 // ------------------------------------------------------------------------
581 extern "C" BOOL __LOADONCALLAPI DoExportDialog( FltCallDialogParameter& rPara )
583 BOOL bRet = FALSE;
585 if ( rPara.pWindow )
587 ByteString aResMgrName( "egi" );
588 ResMgr* pResMgr;
590 pResMgr = ResMgr::CreateResMgr( aResMgrName.GetBuffer(), Application::GetSettings().GetUILocale() );
592 if( pResMgr )
594 rPara.pResMgr = pResMgr;
595 bRet = ( DlgExportEGIF( rPara ).Execute() == RET_OK );
596 delete pResMgr;
598 else
599 bRet = TRUE;
602 return bRet;
605 // ------------------------------------------------------------------------
606 #ifndef GCC
607 #endif
609 #ifdef WIN
611 static HINSTANCE hDLLInst = 0;
613 extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR )
615 #ifndef WNT
616 if ( nHeap )
617 UnlockData( 0 );
618 #endif
620 hDLLInst = hDLL;
622 return TRUE;
625 // ------------------------------------------------------------------------
627 extern "C" int CALLBACK WEP( int )
629 return 1;
632 #endif