diff options
Diffstat (limited to 'filter/source/graphicfilter/egif/egif.cxx')
-rw-r--r-- | filter/source/graphicfilter/egif/egif.cxx | 549 |
1 files changed, 0 insertions, 549 deletions
diff --git a/filter/source/graphicfilter/egif/egif.cxx b/filter/source/graphicfilter/egif/egif.cxx deleted file mode 100644 index 7a70d337e6c5..000000000000 --- a/filter/source/graphicfilter/egif/egif.cxx +++ /dev/null @@ -1,549 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include <tools/stream.hxx> -#include <tools/debug.hxx> -#include <vcl/BitmapReadAccess.hxx> -#include <vcl/graph.hxx> -#include <vcl/outdev.hxx> -#include <vcl/FilterConfigItem.hxx> -#include <com/sun/star/task/XStatusIndicator.hpp> -#include "giflzwc.hxx" -#include <memory> - -namespace { - -class GIFWriter -{ - Bitmap aAccBmp; - SvStream& m_rGIF; - BitmapReadAccess* m_pAcc; - sal_uInt32 nMinPercent; - sal_uInt32 nMaxPercent; - sal_uInt32 nLastPercent; - tools::Long nActX; - tools::Long nActY; - sal_Int32 nInterlaced; - bool bStatus; - bool bTransparent; - - void MayCallback(sal_uInt32 nPercent); - void WriteSignature( bool bGIF89a ); - void WriteGlobalHeader( const Size& rSize ); - void WriteLoopExtension( const Animation& rAnimation ); - void WriteLogSizeExtension( const Size& rSize100 ); - void WriteImageExtension( tools::Long nTimer, Disposal eDisposal ); - void WriteLocalHeader(); - void WritePalette(); - void WriteAccess(); - void WriteTerminator(); - - bool CreateAccess( const BitmapEx& rBmpEx ); - void DestroyAccess(); - - void WriteAnimation( const Animation& rAnimation ); - void WriteBitmapEx( const BitmapEx& rBmpEx, const Point& rPoint, bool bExtended, - tools::Long nTimer = 0, Disposal eDisposal = Disposal::Not ); - - css::uno::Reference< css::task::XStatusIndicator > xStatusIndicator; - -public: - - explicit GIFWriter(SvStream &rStream); - - bool WriteGIF( const Graphic& rGraphic, FilterConfigItem* pConfigItem ); -}; - -} - -GIFWriter::GIFWriter(SvStream &rStream) - : m_rGIF(rStream) - , m_pAcc(nullptr) - , nMinPercent(0) - , nMaxPercent(0) - , nLastPercent(0) - , nActX(0) - , nActY(0) - , nInterlaced(0) - , bStatus(false) - , bTransparent(false) -{ -} - - -bool GIFWriter::WriteGIF(const Graphic& rGraphic, FilterConfigItem* pFilterConfigItem) -{ - if ( pFilterConfigItem ) - { - xStatusIndicator = pFilterConfigItem->GetStatusIndicator(); - if ( xStatusIndicator.is() ) - { - xStatusIndicator->start( OUString(), 100 ); - } - } - - Size aSize100; - const MapMode aMap( rGraphic.GetPrefMapMode() ); - bool bLogSize = ( aMap.GetMapUnit() != MapUnit::MapPixel ); - - if( bLogSize ) - aSize100 = OutputDevice::LogicToLogic(rGraphic.GetPrefSize(), aMap, MapMode(MapUnit::Map100thMM)); - - bStatus = true; - nLastPercent = 0; - nInterlaced = 0; - m_pAcc = nullptr; - - if ( pFilterConfigItem ) - nInterlaced = pFilterConfigItem->ReadInt32( "Interlaced", 0 ); - - m_rGIF.SetEndian( SvStreamEndian::LITTLE ); - - if( rGraphic.IsAnimated() ) - { - const Animation& rAnimation = rGraphic.GetAnimation(); - - WriteSignature( true ); - - if ( bStatus ) - { - WriteGlobalHeader( rAnimation.GetDisplaySizePixel() ); - - if( bStatus ) - { - WriteLoopExtension( rAnimation ); - - if( bStatus ) - WriteAnimation( rAnimation ); - } - } - } - else - { - const bool bGrafTrans = rGraphic.IsTransparent(); - - BitmapEx aBmpEx = rGraphic.GetBitmapEx(); - - nMinPercent = 0; - nMaxPercent = 100; - - WriteSignature( bGrafTrans || bLogSize ); - - if( bStatus ) - { - WriteGlobalHeader( aBmpEx.GetSizePixel() ); - - if( bStatus ) - WriteBitmapEx( aBmpEx, Point(), bGrafTrans ); - } - } - - if( bStatus ) - { - if( bLogSize ) - WriteLogSizeExtension( aSize100 ); - - WriteTerminator(); - } - - if ( xStatusIndicator.is() ) - xStatusIndicator->end(); - - return bStatus; -} - - -void GIFWriter::WriteBitmapEx( const BitmapEx& rBmpEx, const Point& rPoint, - bool bExtended, tools::Long nTimer, Disposal eDisposal ) -{ - if( !CreateAccess( rBmpEx ) ) - return; - - nActX = rPoint.X(); - nActY = rPoint.Y(); - - if( bExtended ) - WriteImageExtension( nTimer, eDisposal ); - - if( bStatus ) - { - WriteLocalHeader(); - - if( bStatus ) - { - WritePalette(); - - if( bStatus ) - WriteAccess(); - } - } - - DestroyAccess(); -} - - -void GIFWriter::WriteAnimation( const Animation& rAnimation ) -{ - const sal_uInt16 nCount = rAnimation.Count(); - - if( !nCount ) - return; - - const double fStep = 100. / nCount; - - nMinPercent = 0; - nMaxPercent = static_cast<sal_uInt32>(fStep); - - for( sal_uInt16 i = 0; i < nCount; i++ ) - { - const AnimationBitmap& rAnimationBitmap = rAnimation.Get( i ); - - WriteBitmapEx(rAnimationBitmap.maBitmapEx, rAnimationBitmap.maPositionPixel, true, - rAnimationBitmap.mnWait, rAnimationBitmap.meDisposal ); - nMinPercent = nMaxPercent; - nMaxPercent = static_cast<sal_uInt32>(nMaxPercent + fStep); - } -} - - -void GIFWriter::MayCallback(sal_uInt32 nPercent) -{ - if ( xStatusIndicator.is() ) - { - if( nPercent >= nLastPercent + 3 ) - { - nLastPercent = nPercent; - if ( nPercent <= 100 ) - xStatusIndicator->setValue( nPercent ); - } - } -} - - -bool GIFWriter::CreateAccess( const BitmapEx& rBmpEx ) -{ - if( bStatus ) - { - Bitmap aMask( rBmpEx.GetMask() ); - - aAccBmp = rBmpEx.GetBitmap(); - bTransparent = false; - - if( !!aMask ) - { - if( aAccBmp.Convert( BmpConversion::N8BitTrans ) ) - { - aMask.Convert( BmpConversion::N1BitThreshold ); - aAccBmp.Replace( aMask, BMP_COL_TRANS ); - bTransparent = true; - } - else - aAccBmp.Convert( BmpConversion::N8BitColors ); - } - else - aAccBmp.Convert( BmpConversion::N8BitColors ); - - m_pAcc = aAccBmp.AcquireReadAccess(); - - if( !m_pAcc ) - bStatus = false; - } - - return bStatus; -} - - -void GIFWriter::DestroyAccess() -{ - Bitmap::ReleaseAccess( m_pAcc ); - m_pAcc = nullptr; -} - - -void GIFWriter::WriteSignature( bool bGIF89a ) -{ - if( bStatus ) - { - m_rGIF.WriteBytes(bGIF89a ? "GIF89a" : "GIF87a" , 6); - - if( m_rGIF.GetError() ) - bStatus = false; - } -} - - -void GIFWriter::WriteGlobalHeader( const Size& rSize ) -{ - if( !bStatus ) - return; - - // 256 colors - const sal_uInt16 nWidth = static_cast<sal_uInt16>(rSize.Width()); - const sal_uInt16 nHeight = static_cast<sal_uInt16>(rSize.Height()); - const sal_uInt8 cFlags = 128 | ( 7 << 4 ); - - // write values - m_rGIF.WriteUInt16( nWidth ); - m_rGIF.WriteUInt16( nHeight ); - m_rGIF.WriteUChar( cFlags ); - m_rGIF.WriteUChar( 0x00 ); - m_rGIF.WriteUChar( 0x00 ); - - // write dummy palette with two entries (black/white); - // we do this only because of a bug in Photoshop, since those can't - // read pictures without a global color palette - m_rGIF.WriteUInt16( 0 ); - m_rGIF.WriteUInt16( 255 ); - m_rGIF.WriteUInt16( 65535 ); - - if( m_rGIF.GetError() ) - bStatus = false; -} - - -void GIFWriter::WriteLoopExtension( const Animation& rAnimation ) -{ - DBG_ASSERT( rAnimation.Count() > 0, "Animation has no bitmaps!" ); - - sal_uInt16 nLoopCount = static_cast<sal_uInt16>(rAnimation.GetLoopCount()); - - // if only one run should take place - // the LoopExtension won't be written - // The default in this case is a single run - if( nLoopCount == 1 ) - return; - - // Netscape interprets the LoopCount - // as the sole number of _repetitions_ - if( nLoopCount ) - nLoopCount--; - - const sal_uInt8 cLoByte = static_cast<sal_uInt8>(nLoopCount); - const sal_uInt8 cHiByte = static_cast<sal_uInt8>( nLoopCount >> 8 ); - - m_rGIF.WriteUChar( 0x21 ); - m_rGIF.WriteUChar( 0xff ); - m_rGIF.WriteUChar( 0x0b ); - m_rGIF.WriteBytes( "NETSCAPE2.0", 11 ); - m_rGIF.WriteUChar( 0x03 ); - m_rGIF.WriteUChar( 0x01 ); - m_rGIF.WriteUChar( cLoByte ); - m_rGIF.WriteUChar( cHiByte ); - m_rGIF.WriteUChar( 0x00 ); -} - - -void GIFWriter::WriteLogSizeExtension( const Size& rSize100 ) -{ - // writer PrefSize in 100th-mm as ApplicationExtension - if( rSize100.Width() && rSize100.Height() ) - { - m_rGIF.WriteUChar( 0x21 ); - m_rGIF.WriteUChar( 0xff ); - m_rGIF.WriteUChar( 0x0b ); - m_rGIF.WriteBytes( "STARDIV 5.0", 11 ); - m_rGIF.WriteUChar( 0x09 ); - m_rGIF.WriteUChar( 0x01 ); - m_rGIF.WriteUInt32( rSize100.Width() ); - m_rGIF.WriteUInt32( rSize100.Height() ); - m_rGIF.WriteUChar( 0x00 ); - } -} - - -void GIFWriter::WriteImageExtension( tools::Long nTimer, Disposal eDisposal ) -{ - if( !bStatus ) - return; - - const sal_uInt16 nDelay = static_cast<sal_uInt16>(nTimer); - sal_uInt8 cFlags = 0; - - // set Transparency-Flag - if( bTransparent ) - cFlags |= 1; - - // set Disposal-value - if( eDisposal == Disposal::Back ) - cFlags |= ( 2 << 2 ); - else if( eDisposal == Disposal::Previous ) - cFlags |= ( 3 << 2 ); - - m_rGIF.WriteUChar( 0x21 ); - m_rGIF.WriteUChar( 0xf9 ); - m_rGIF.WriteUChar( 0x04 ); - m_rGIF.WriteUChar( cFlags ); - m_rGIF.WriteUInt16( nDelay ); - m_rGIF.WriteUChar( m_pAcc->GetBestPaletteIndex( BMP_COL_TRANS ) ); - m_rGIF.WriteUChar( 0x00 ); - - if( m_rGIF.GetError() ) - bStatus = false; -} - - -void GIFWriter::WriteLocalHeader() -{ - if( !bStatus ) - return; - - const sal_uInt16 nPosX = static_cast<sal_uInt16>(nActX); - const sal_uInt16 nPosY = static_cast<sal_uInt16>(nActY); - const sal_uInt16 nWidth = static_cast<sal_uInt16>(m_pAcc->Width()); - const sal_uInt16 nHeight = static_cast<sal_uInt16>(m_pAcc->Height()); - sal_uInt8 cFlags = static_cast<sal_uInt8>( m_pAcc->GetBitCount() - 1 ); - - // set Interlaced-Flag - if( nInterlaced ) - cFlags |= 0x40; - - // set Flag for the local color palette - cFlags |= 0x80; - - m_rGIF.WriteUChar( 0x2c ); - m_rGIF.WriteUInt16( nPosX ); - m_rGIF.WriteUInt16( nPosY ); - m_rGIF.WriteUInt16( nWidth ); - m_rGIF.WriteUInt16( nHeight ); - m_rGIF.WriteUChar( cFlags ); - - if( m_rGIF.GetError() ) - bStatus = false; -} - - -void GIFWriter::WritePalette() -{ - if( !(bStatus && m_pAcc->HasPalette()) ) - return; - - const sal_uInt16 nCount = m_pAcc->GetPaletteEntryCount(); - const sal_uInt16 nMaxCount = ( 1 << m_pAcc->GetBitCount() ); - - for ( sal_uInt16 i = 0; i < nCount; i++ ) - { - const BitmapColor& rColor = m_pAcc->GetPaletteColor( i ); - - m_rGIF.WriteUChar( rColor.GetRed() ); - m_rGIF.WriteUChar( rColor.GetGreen() ); - m_rGIF.WriteUChar( rColor.GetBlue() ); - } - - // fill up the rest with 0 - if( nCount < nMaxCount ) - m_rGIF.SeekRel( ( nMaxCount - nCount ) * 3 ); - - if( m_rGIF.GetError() ) - bStatus = false; -} - - -void GIFWriter::WriteAccess() -{ - GIFLZWCompressor aCompressor; - const tools::Long nWidth = m_pAcc->Width(); - const tools::Long nHeight = m_pAcc->Height(); - std::unique_ptr<sal_uInt8[]> pBuffer; - bool bNative = m_pAcc->GetScanlineFormat() == ScanlineFormat::N8BitPal; - - if( !bNative ) - pBuffer.reset(new sal_uInt8[ nWidth ]); - - if( !(bStatus && ( 8 == m_pAcc->GetBitCount() ) && m_pAcc->HasPalette()) ) - return; - - aCompressor.StartCompression( m_rGIF, m_pAcc->GetBitCount() ); - - tools::Long nY, nT; - - for( tools::Long i = 0; i < nHeight; ++i ) - { - if( nInterlaced ) - { - nY = i << 3; - - if( nY >= nHeight ) - { - nT = i - ( ( nHeight + 7 ) >> 3 ); - nY= ( nT << 3 ) + 4; - - if( nY >= nHeight ) - { - nT -= ( nHeight + 3 ) >> 3; - nY = ( nT << 2 ) + 2; - - if ( nY >= nHeight ) - { - nT -= ( ( nHeight + 1 ) >> 2 ); - nY = ( nT << 1 ) + 1; - } - } - } - } - else - nY = i; - - if( bNative ) - aCompressor.Compress( m_pAcc->GetScanline( nY ), nWidth ); - else - { - Scanline pScanline = m_pAcc->GetScanline( nY ); - for( tools::Long nX = 0; nX < nWidth; nX++ ) - pBuffer[ nX ] = m_pAcc->GetIndexFromData( pScanline, nX ); - - aCompressor.Compress( pBuffer.get(), nWidth ); - } - - if ( m_rGIF.GetError() ) - bStatus = false; - - MayCallback( nMinPercent + ( nMaxPercent - nMinPercent ) * i / nHeight ); - - if( !bStatus ) - break; - } - - aCompressor.EndCompression(); - - if ( m_rGIF.GetError() ) - bStatus = false; -} - - -void GIFWriter::WriteTerminator() -{ - if( bStatus ) - { - m_rGIF.WriteUChar( 0x3b ); - - if( m_rGIF.GetError() ) - bStatus = false; - } -} - - -extern "C" SAL_DLLPUBLIC_EXPORT bool -egiGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem ) -{ - GIFWriter aWriter(rStream); - return aWriter.WriteGIF(rGraphic, pConfigItem); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |