Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  _xoutbmp.cxx   Sprache: C

 
/* -*- 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 <sal/config.h>
#include <sal/log.hxx>

#include <comphelper/base64.hxx>
#include <comphelper/graphicmimetype.hxx>
#include <tools/debug.hxx>
#include <vcl/virdev.hxx>
#include <sfx2/docfile.hxx>
#include <svx/svdpntv.hxx>
#include <svx/xoutbmp.hxx>
#include <vcl/graphicfilter.hxx>
#include <vcl/cvtgrf.hxx>
#include <vcl/gdimtf.hxx>
#include <vcl/svapp.hxx>

#include <UnoGraphicExporter.hxx>

#include <memory>

#include <com/sun/star/beans/XPropertySet.hpp>

constexpr OUStringLiteral FORMAT_SVG = u"svg";
constexpr OUStringLiteral FORMAT_WMF = u"wmf";
constexpr OUString FORMAT_EMF = u"emf"_ustr;
constexpr OUStringLiteral FORMAT_PDF = u"pdf";

constexpr OUString FORMAT_BMP = u"bmp"_ustr;
constexpr OUString FORMAT_GIF = u"gif"_ustr;
constexpr OUStringLiteral FORMAT_JPG = u"jpg";
constexpr OUString FORMAT_PNG = u"png"_ustr;
constexpr OUStringLiteral FORMAT_TIF = u"tif";
constexpr OUStringLiteral FORMAT_WEBP = u"webp";

using namespace com::sun::star;

Animation XOutBitmap::MirrorAnimation( const Animation& rAnimation, bool bHMirr, bool bVMirr )
{
    Animation aNewAnim( rAnimation );

    if( bHMirr || bVMirr )
    {
        const Size& rGlobalSize = aNewAnim.GetDisplaySizePixel();
        BmpMirrorFlags nMirrorFlags = BmpMirrorFlags::NONE;

        if( bHMirr )
            nMirrorFlags |= BmpMirrorFlags::Horizontal;

        if( bVMirr )
            nMirrorFlags |= BmpMirrorFlags::Vertical;

        for( sal_uInt16 i = 0, nCount = aNewAnim.Count(); i < nCount; i++ )
        {
            AnimationFrame aAnimationFrame( aNewAnim.Get( i ) );

            // mirror the BitmapEx
            aAnimationFrame.maBitmapEx.Mirror( nMirrorFlags );

            // Adjust the positions inside the whole bitmap
            if( bHMirr )
                aAnimationFrame.maPositionPixel.setX(rGlobalSize.Width() - aAnimationFrame.maPositionPixel.X() -
                                       aAnimationFrame.maSizePixel.Width());

            if( bVMirr )
                aAnimationFrame.maPositionPixel.setY(rGlobalSize.Height() - aAnimationFrame.maPositionPixel.Y() -
                                       aAnimationFrame.maSizePixel.Height());

            aNewAnim.Replace(aAnimationFrame, i);
        }
    }

    return aNewAnim;
}

Graphic XOutBitmap::MirrorGraphic( const Graphic& rGraphic, const BmpMirrorFlags nMirrorFlags )
{
    Graphic aRetGraphic;

    if( nMirrorFlags != BmpMirrorFlags::NONE )
    {
        if( rGraphic.IsAnimated() )
        {
            aRetGraphic = MirrorAnimation( rGraphic.GetAnimation(),
                                           bool( nMirrorFlags & BmpMirrorFlags::Horizontal ),
                                           bool( nMirrorFlags & BmpMirrorFlags::Vertical ) );
        }
        else
        {
            BitmapEx aBmp( rGraphic.GetBitmapEx() );
            aBmp.Mirror( nMirrorFlags );
            aRetGraphic = aBmp;
        }
    }
    else
        aRetGraphic = rGraphic;

    return aRetGraphic;
}

static OUString match(std::u16string_view filter, const OUString& expected, bool matchEmpty = true)
{
    return (matchEmpty && filter.empty()) || expected.equalsIgnoreAsciiCase(filter) ? expected
                                                                                    : OUString();
}

static OUString isKnownVectorFormat(const Graphic& rGraphic, std::u16string_view rFilter)
{
    const auto& pData(rGraphic.getVectorGraphicData());
    if (!pData || pData->getBinaryDataContainer().getSize() == 0)
        return {};

    if (FORMAT_EMF.equalsIgnoreAsciiCase(rFilter)
        && (pData->getType() == VectorGraphicDataType::Emf || rGraphic.GetGfxLink().IsEMF()))
        return FORMAT_EMF;

    // Does the filter name match the original format?
    switch (pData->getType())
    {
        case VectorGraphicDataType::Svg:
            return match(rFilter, FORMAT_SVG, false);
        case VectorGraphicDataType::Wmf:
            return match(rFilter, FORMAT_WMF, false);
        case VectorGraphicDataType::Emf:
            break;
        case VectorGraphicDataType::Pdf:
            return match(rFilter, FORMAT_PDF, false);
    }

    return {};
}

static OUString isKnownRasterFormat(const GfxLink& rLink, std::u16string_view rFilter)
{
    // tdf#60684: use native format if possible but it must correspond to filter name
    // or no specific format has been required
    // without this, you may save for example file with png extension but jpg content
    switch (rLink.GetType())
    {
        case GfxLinkType::NativeGif:
            return match(rFilter, FORMAT_GIF);

        // #i15508# added BMP type for better exports (no call/trigger found, prob used in HTML export)
        case GfxLinkType::NativeBmp:
            return match(rFilter, FORMAT_BMP);

        case GfxLinkType::NativeJpg:
            return match(rFilter, FORMAT_JPG);
        case GfxLinkType::NativePng:
            return match(rFilter, FORMAT_PNG);
        case GfxLinkType::NativeTif:
            return match(rFilter, FORMAT_TIF);
        case GfxLinkType::NativeWebp:
            return match(rFilter, FORMAT_WEBP);
        default:
            return {};
    }
}

ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
                                 const OUString& rFilterName, const XOutFlags nFlags,
                                 const Size* pMtfSize_100TH_MM,
                                 const css::uno::Sequence< css::beans::PropertyValue >* pFilterData,
                                 OUString* pMediaType )
{
    if( rGraphic.GetType() == GraphicType::NONE )
        return ERRCODE_NONE;

    INetURLObject   aURL( rFileName );
    GraphicFilter&  rFilter = GraphicFilter::GetGraphicFilter();

    DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "XOutBitmap::WriteGraphic(...): invalid URL" );

    // calculate correct file name
    if( !( nFlags & XOutFlags::DontExpandFilename ) )
    {
        OUString aStr( OUString::number( rGraphic.GetChecksum(), 16 ) );
        if ( aStr[0] == '-' )
            aStr = OUString::Concat("m") + aStr.subView(1);
        OUString aName = aURL.getBase() + "_" + aURL.getExtension() + "_" + aStr;
        aURL.setBase( aName );
    }

    // #i121128# use shortcut to write Vector Graphic Data data in original form (if possible)
    if (OUString aExt = isKnownVectorFormat(rGraphic, rFilterName); !aExt.isEmpty())
    {
        if (!(nFlags & XOutFlags::DontAddExtension))
            aURL.setExtension(aExt);

        rFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
        if (pMediaType)
            if (auto xGraphic = rGraphic.GetXGraphic().query<css::beans::XPropertySet>())
                xGraphic->getPropertyValue(u"MimeType"_ustr) >>= *pMediaType;

        SfxMedium aMedium(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::WRITE | StreamMode::SHARE_DENYNONE | StreamMode::TRUNC);
        SvStream* pOStm = aMedium.GetOutStream();

        if (pOStm)
        {
            rGraphic.getVectorGraphicData()->getBinaryDataContainer().writeToStream(*pOStm);
            aMedium.Commit();

            if (!aMedium.GetErrorIgnoreWarning())
                return ERRCODE_NONE;
        }
    }

    if( ( nFlags & XOutFlags::UseNativeIfPossible ) &&
        !( nFlags & XOutFlags::MirrorHorz ) &&
        !( nFlags & XOutFlags::MirrorVert ) &&
        ( rGraphic.GetType() != GraphicType::GdiMetafile ) && rGraphic.IsGfxLink() )
    {
        // try to write native link
        const GfxLink aGfxLink( rGraphic.GetGfxLink() );
        if (OUString aExt = isKnownRasterFormat(aGfxLink, rFilterName); !aExt.isEmpty())
        {
            if( !(nFlags & XOutFlags::DontAddExtension) )
                aURL.setExtension( aExt );
            rFileName = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
            if (pMediaType)
                if (auto xGraphic = rGraphic.GetXGraphic().query<css::beans::XPropertySet>())
                    xGraphic->getPropertyValue(u"MimeType"_ustr) >>= *pMediaType;

            SfxMedium   aMedium(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::WRITE | StreamMode::SHARE_DENYNONE | StreamMode::TRUNC);
            SvStream*   pOStm = aMedium.GetOutStream();

            if( pOStm && aGfxLink.GetDataSize() && aGfxLink.GetData() )
            {
                pOStm->WriteBytes(aGfxLink.GetData(), aGfxLink.GetDataSize());
                aMedium.Commit();

                if( !aMedium.GetErrorIgnoreWarning() )
                    return ERRCODE_NONE;
            }
        }
    }

    OUString  aFilter( rFilterName );
    bool bTransparent = rGraphic.IsTransparent(), bAnimated = rGraphic.IsAnimated();
    bool    bWriteTransGrf = ( aFilter.equalsIgnoreAsciiCase( "transgrf" ) ) ||
                                ( aFilter.equalsIgnoreAsciiCase( "gif" ) ) ||
                                ( nFlags & XOutFlags::UseGifIfPossible ) ||
                                ( ( nFlags & XOutFlags::UseGifIfSensible ) && ( bAnimated || bTransparent ) );

    // get filter and extension
    if( bWriteTransGrf )
        aFilter = FORMAT_GIF;

    sal_uInt16 nFilter = rFilter.GetExportFormatNumberForShortName( aFilter );

    if( GRFILTER_FORMAT_NOTFOUND == nFilter )
    {
        nFilter = rFilter.GetExportFormatNumberForShortName( FORMAT_PNG );

        if( GRFILTER_FORMAT_NOTFOUND == nFilter )
            nFilter = rFilter.GetExportFormatNumberForShortName( FORMAT_BMP );
    }

    if( GRFILTER_FORMAT_NOTFOUND != nFilter )
    {
        Graphic aGraphic;

        if (bAnimated)
            aGraphic = rGraphic;
        else if (rGraphic.GetType() == GraphicType::GdiMetafile
                 && rGraphic.GetGDIMetaFile().GetActionSize())
        {
            Size aSize;
            const Size* pSize = nullptr;
            if (pMtfSize_100TH_MM)
            {
                aSize = Application::GetDefaultDevice()->LogicToPixel(*pMtfSize_100TH_MM,
                                                                      MapMode(MapUnit::Map100thMM));
                pSize = &aSize;
            }
            aGraphic = GetBitmapFromMetaFile(rGraphic.GetGDIMetaFile(), pSize);
        }
        else if (pMtfSize_100TH_MM && (rGraphic.GetType() != GraphicType::Bitmap))
        {
            ScopedVclPtrInstance< VirtualDevice > pVDev;
            const Size aSize(pVDev->LogicToPixel(*pMtfSize_100TH_MM, MapMode(MapUnit::Map100thMM)));

            if( pVDev->SetOutputSizePixel( aSize ) )
            {
                if (bWriteTransGrf)
                {
                    const Wallpaper aWallpaper( pVDev->GetBackground() );
                    const Point     aPt;

                    pVDev->SetBackground( Wallpaper( COL_BLACK ) );
                    pVDev->Erase();
                    rGraphic.Draw(*pVDev, aPt, aSize);

                    const Bitmap aBitmap( pVDev->GetBitmap( aPt, aSize ) );

                    pVDev->SetBackground( aWallpaper );
                    pVDev->Erase();
                    rGraphic.Draw(*pVDev, aPt, aSize);

                    pVDev->SetRasterOp( RasterOp::Xor );
                    pVDev->DrawBitmap( aPt, aSize, aBitmap );
                    aGraphic = BitmapEx( aBitmap, pVDev->GetBitmap( aPt, aSize ) );
                }
                else
                {
                    rGraphic.Draw(*pVDev, Point(), aSize);
                    aGraphic = BitmapEx(pVDev->GetBitmap(Point(), aSize));
                }
            }
            else
                aGraphic = rGraphic.GetBitmapEx();
        }
        else
            aGraphic = rGraphic.GetBitmapEx();

        // mirror?
        if( ( nFlags & XOutFlags::MirrorHorz ) || ( nFlags & XOutFlags::MirrorVert ) )
        {
            BmpMirrorFlags nBmpMirrorFlags = BmpMirrorFlags::NONE;
            if( nFlags & XOutFlags::MirrorHorz )
                nBmpMirrorFlags |= BmpMirrorFlags::Horizontal;
            if( nFlags & XOutFlags::MirrorVert )
                nBmpMirrorFlags |= BmpMirrorFlags::Vertical;
            aGraphic = MirrorGraphic( aGraphic, nBmpMirrorFlags );
        }

        if (aGraphic.GetType() != GraphicType::NONE)
        {
            if( !(nFlags & XOutFlags::DontAddExtension) )
                aURL.setExtension(rFilter.GetExportFormatShortName(nFilter).toAsciiLowerCase());
            rFileName = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
            if (pMediaType)
                *pMediaType = rFilter.GetExportFormatMediaType(nFilter);
            return ExportGraphic( aGraphic, aURL, rFilter, nFilter, pFilterData );
        }
    }

    return ERRCODE_GRFILTER_FILTERERROR;
}

bool XOutBitmap::GraphicToBase64(const Graphic& rGraphic, OUString& rOUStringbool bAddPrefix,
                                 ConvertDataFormat aTargetFormat)
{
    SvMemoryStream aOStm;
    GfxLink aLink = rGraphic.GetGfxLink();

    if (aTargetFormat == ConvertDataFormat::Unknown)
    {
        switch (aLink.GetType())
        {
            case GfxLinkType::NativeJpg:
                aTargetFormat = ConvertDataFormat::JPG;
                break;
            case GfxLinkType::NativePng:
                aTargetFormat = ConvertDataFormat::PNG;
                break;
            case GfxLinkType::NativeSvg:
                aTargetFormat = ConvertDataFormat::SVG;
                break;
            default:
                // save everything else (including gif) into png
                aTargetFormat = ConvertDataFormat::PNG;
                break;
        }
    }

    ErrCode nErr = GraphicConverter::Export(aOStm,rGraphic,aTargetFormat);
    if ( nErr )
    {
        SAL_WARN("svx""XOutBitmap::GraphicToBase64() invalid Graphic? error: " << nErr );
        return false;
    }
    css::uno::Sequence<sal_Int8> aOStmSeq( static_cast<sal_Int8 const *>(aOStm.GetData()),aOStm.TellEnd() );
    OUStringBuffer aStrBuffer;
    ::comphelper::Base64::encode(aStrBuffer,aOStmSeq);
    rOUString = aStrBuffer.makeStringAndClear();

    if (bAddPrefix)
    {
        OUString aMimeType
            = comphelper::GraphicMimeTypeHelper::GetMimeTypeForConvertDataFormat(aTargetFormat);
        rOUString = aMimeType + ";base64," + rOUString;
    }

    return true;
}

ErrCode XOutBitmap::ExportGraphic( const Graphic& rGraphic, const INetURLObject&&nbsp;rURL,
                                  GraphicFilter& rFilter, const sal_uInt16 nFormat,
                                  const css::uno::Sequence< css::beans::PropertyValue >* pFilterData )
{
    DBG_ASSERT( rURL.GetProtocol() != INetProtocol::NotValid, "XOutBitmap::ExportGraphic(...): invalid URL" );

    SfxMedium   aMedium( rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::WRITE | StreamMode::SHARE_DENYNONE | StreamMode::TRUNC );
    SvStream*   pOStm = aMedium.GetOutStream();
    ErrCode     nRet = ERRCODE_GRFILTER_IOERROR;

    if( pOStm )
    {
        nRet = rFilter.ExportGraphic( rGraphic, rURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), *pOStm, nFormat, pFilterData );

        aMedium.Commit();

        if( aMedium.GetErrorIgnoreWarning() && ( ERRCODE_NONE == nRet  ) )
            nRet = ERRCODE_GRFILTER_IOERROR;
    }

    return nRet;
}


/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=95 H=93 G=93

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge