27#include <com/sun/star/task/XStatusIndicator.hpp>
39 sal_uInt32 nMinPercent;
40 sal_uInt32 nMaxPercent;
41 sal_uInt32 nLastPercent;
44 sal_Int32 nInterlaced;
48 void MayCallback(sal_uInt32 nPercent);
49 void WriteSignature(
bool bGIF89a );
50 void WriteGlobalHeader(
const Size& rSize );
51 void WriteLoopExtension(
const Animation& rAnimation );
52 void WriteLogSizeExtension(
const Size& rSize100 );
54 void WriteLocalHeader();
57 void WriteTerminator();
59 bool CreateAccess(
const BitmapEx& rBmpEx );
63 void WriteBitmapEx(
const BitmapEx& rBmpEx,
const Point& rPoint,
bool bExtended,
66 css::uno::Reference< css::task::XStatusIndicator > xStatusIndicator;
70 explicit GIFWriter(
SvStream &rStream);
77GIFWriter::GIFWriter(
SvStream &rStream)
94 if ( pFilterConfigItem )
97 if ( xStatusIndicator.is() )
99 xStatusIndicator->start( OUString(), 100 );
105 bool bLogSize = (
aMap.GetMapUnit() != MapUnit::MapPixel );
115 if ( pFilterConfigItem )
116 nInterlaced = pFilterConfigItem->
ReadInt32(
"Interlaced", 0 );
118 m_rGIF.SetEndian( SvStreamEndian::LITTLE );
124 WriteSignature(
true );
132 WriteLoopExtension( rAnimation );
148 WriteSignature( bGrafTrans || bLogSize );
155 WriteBitmapEx( aBmpEx,
Point(), bGrafTrans );
162 WriteLogSizeExtension( aSize100 );
167 if ( xStatusIndicator.is() )
168 xStatusIndicator->end();
174void GIFWriter::WriteBitmapEx(
const BitmapEx& rBmpEx,
const Point& rPoint,
177 if( !CreateAccess( rBmpEx ) )
184 WriteImageExtension( nTimer, eDisposal );
210 const double fStep = 100. /
nCount;
213 nMaxPercent =
static_cast<sal_uInt32
>(fStep);
215 for( sal_uInt16 i = 0;
i <
nCount;
i++ )
221 nMinPercent = nMaxPercent;
222 nMaxPercent =
static_cast<sal_uInt32
>(nMaxPercent + fStep);
227void GIFWriter::MayCallback(sal_uInt32 nPercent)
229 if ( xStatusIndicator.is() )
231 if( nPercent >= nLastPercent + 3 )
233 nLastPercent = nPercent;
234 if ( nPercent <= 100 )
235 xStatusIndicator->setValue( nPercent );
241bool GIFWriter::CreateAccess(
const BitmapEx& rBmpEx )
248 bTransparent =
false;
250 if( !aMask.IsEmpty() )
264 m_pAcc = aAccBmp.AcquireReadAccess();
274void GIFWriter::DestroyAccess()
281void GIFWriter::WriteSignature(
bool bGIF89a )
285 m_rGIF.WriteBytes(bGIF89a ?
"GIF89a" :
"GIF87a" , 6);
287 if( m_rGIF.GetError() )
293void GIFWriter::WriteGlobalHeader(
const Size& rSize )
299 const sal_uInt16 nWidth =
static_cast<sal_uInt16
>(rSize.
Width());
300 const sal_uInt16 nHeight =
static_cast<sal_uInt16
>(rSize.
Height());
301 const sal_uInt8 cFlags = 128 | ( 7 << 4 );
304 m_rGIF.WriteUInt16( nWidth );
305 m_rGIF.WriteUInt16( nHeight );
306 m_rGIF.WriteUChar( cFlags );
307 m_rGIF.WriteUChar( 0x00 );
308 m_rGIF.WriteUChar( 0x00 );
313 m_rGIF.WriteUInt16( 0 );
314 m_rGIF.WriteUInt16( 255 );
315 m_rGIF.WriteUInt16( 65535 );
317 if( m_rGIF.GetError() )
322void GIFWriter::WriteLoopExtension(
const Animation& rAnimation )
326 sal_uInt16 nLoopCount =
static_cast<sal_uInt16
>(rAnimation.
GetLoopCount());
331 if( nLoopCount == 1 )
342 m_rGIF.WriteUChar( 0x21 );
343 m_rGIF.WriteUChar( 0xff );
344 m_rGIF.WriteUChar( 0x0b );
345 m_rGIF.WriteBytes(
"NETSCAPE2.0", 11 );
346 m_rGIF.WriteUChar( 0x03 );
347 m_rGIF.WriteUChar( 0x01 );
348 m_rGIF.WriteUChar( cLoByte );
349 m_rGIF.WriteUChar( cHiByte );
350 m_rGIF.WriteUChar( 0x00 );
354void GIFWriter::WriteLogSizeExtension(
const Size& rSize100 )
359 m_rGIF.WriteUChar( 0x21 );
360 m_rGIF.WriteUChar( 0xff );
361 m_rGIF.WriteUChar( 0x0b );
362 m_rGIF.WriteBytes(
"STARDIV 5.0", 11 );
363 m_rGIF.WriteUChar( 0x09 );
364 m_rGIF.WriteUChar( 0x01 );
365 m_rGIF.WriteUInt32( rSize100.
Width() );
366 m_rGIF.WriteUInt32( rSize100.
Height() );
367 m_rGIF.WriteUChar( 0x00 );
377 const sal_uInt16 nDelay =
static_cast<sal_uInt16
>(nTimer);
386 cFlags |= ( 2 << 2 );
388 cFlags |= ( 3 << 2 );
390 m_rGIF.WriteUChar( 0x21 );
391 m_rGIF.WriteUChar( 0xf9 );
392 m_rGIF.WriteUChar( 0x04 );
393 m_rGIF.WriteUChar( cFlags );
394 m_rGIF.WriteUInt16( nDelay );
396 m_rGIF.WriteUChar( 0x00 );
398 if( m_rGIF.GetError() )
403void GIFWriter::WriteLocalHeader()
408 const sal_uInt16 nPosX =
static_cast<sal_uInt16
>(nActX);
409 const sal_uInt16 nPosY =
static_cast<sal_uInt16
>(nActY);
410 const sal_uInt16 nWidth =
static_cast<sal_uInt16
>(m_pAcc->Width());
411 const sal_uInt16 nHeight =
static_cast<sal_uInt16
>(m_pAcc->Height());
421 m_rGIF.WriteUChar( 0x2c );
422 m_rGIF.WriteUInt16( nPosX );
423 m_rGIF.WriteUInt16( nPosY );
424 m_rGIF.WriteUInt16( nWidth );
425 m_rGIF.WriteUInt16( nHeight );
426 m_rGIF.WriteUChar( cFlags );
428 if( m_rGIF.GetError() )
433void GIFWriter::WritePalette()
435 if( !(bStatus && m_pAcc->HasPalette()) )
438 const sal_uInt16
nCount = m_pAcc->GetPaletteEntryCount();
439 const sal_uInt16 nMaxCount = ( 1 << m_pAcc->GetBitCount() );
441 for ( sal_uInt16 i = 0;
i <
nCount;
i++ )
443 const BitmapColor& rColor = m_pAcc->GetPaletteColor( i );
445 m_rGIF.WriteUChar( rColor.
GetRed() );
446 m_rGIF.WriteUChar( rColor.
GetGreen() );
447 m_rGIF.WriteUChar( rColor.
GetBlue() );
451 if( nCount < nMaxCount )
452 m_rGIF.SeekRel( ( nMaxCount - nCount ) * 3 );
454 if( m_rGIF.GetError() )
459void GIFWriter::WriteAccess()
464 std::unique_ptr<sal_uInt8[]> pBuffer;
470 if( !(bStatus && ( 8 == m_pAcc->GetBitCount() ) && m_pAcc->HasPalette()) )
485 nT =
i - ( ( nHeight + 7 ) >> 3 );
490 nT -= ( nHeight + 3 ) >> 3;
491 nY = ( nT << 2 ) + 2;
495 nT -= ( ( nHeight + 1 ) >> 2 );
496 nY = ( nT << 1 ) + 1;
505 aCompressor.
Compress( m_pAcc->GetScanline( nY ), nWidth );
508 Scanline pScanline = m_pAcc->GetScanline( nY );
510 pBuffer[ nX ] = m_pAcc->GetIndexFromData( pScanline, nX );
512 aCompressor.
Compress( pBuffer.get(), nWidth );
515 if ( m_rGIF.GetError() )
518 MayCallback( nMinPercent + ( nMaxPercent - nMinPercent ) * i / nHeight );
526 if ( m_rGIF.GetError() )
531void GIFWriter::WriteTerminator()
535 m_rGIF.WriteUChar( 0x3b );
537 if( m_rGIF.GetError() )
545 GIFWriter aWriter(rStream);
546 return aWriter.WriteGIF(rGraphic, pConfigItem);
SvStream & WriteAnimation(SvStream &rOStm, const Animation &rAnimation)
const Size & GetDisplaySizePixel() const
const AnimationFrame & Get(sal_uInt16 nAnimation) const
sal_uInt32 GetLoopCount() const
const AlphaMask & GetAlphaMask() const
Bitmap GetBitmap(Color aTransparentReplaceColor) const
const Size & GetSizePixel() const
bool Convert(BmpConversion eConversion)
Convert bitmap format.
static void ReleaseAccess(BitmapInfoAccess *pAccess)
sal_uInt8 GetBlue() const
sal_uInt8 GetGreen() const
css::uno::Reference< css::task::XStatusIndicator > GetStatusIndicator() const
sal_Int32 ReadInt32(const OUString &rKey, sal_Int32 nDefault)
void Compress(sal_uInt8 *pSrc, sal_uInt32 nSize)
void StartCompression(SvStream &rGIF, sal_uInt16 nPixelSize)
Animation GetAnimation() const
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
MapMode GetPrefMapMode() const
bool IsTransparent() const
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
constexpr tools::Long Y() const
constexpr tools::Long X() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
#define DBG_ASSERT(sCon, aError)
bool ExportGifGraphic(SvStream &rStream, const Graphic &rGraphic, FilterConfigItem *pConfigItem)
HashMap_OWString_Interface aMap