LibreOffice Module vcl (master) 1
graphicfilter.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <config_folders.h>
21
22#include <sal/log.hxx>
27#include <tools/fract.hxx>
29#include <tools/stream.hxx>
30#include <tools/urlobj.hxx>
31#include <tools/zcodec.hxx>
32#include <rtl/crc.h>
33#include <fltcall.hxx>
34#include <vcl/salctype.hxx>
39#include <vcl/virdev.hxx>
40#include <impgraph.hxx>
41#include <vcl/svapp.hxx>
42#include <osl/file.hxx>
43#include <vcl/graphicfilter.hxx>
45#include <vcl/wmf.hxx>
46#include "igif/gifread.hxx"
47#include <vcl/pdfread.hxx>
48#include "jpeg/jpeg.hxx"
49#include "png/png.hxx"
50#include "ixbm/xbmread.hxx"
51#include <filter/XpmReader.hxx>
52#include <filter/TiffReader.hxx>
53#include <filter/TiffWriter.hxx>
54#include <filter/TgaReader.hxx>
55#include <filter/PictReader.hxx>
56#include <filter/MetReader.hxx>
57#include <filter/RasReader.hxx>
58#include <filter/PcxReader.hxx>
59#include <filter/EpsReader.hxx>
60#include <filter/EpsWriter.hxx>
61#include <filter/PsdReader.hxx>
62#include <filter/PcdReader.hxx>
63#include <filter/PbmReader.hxx>
64#include <filter/DxfReader.hxx>
65#include <filter/GifWriter.hxx>
66#include <filter/BmpReader.hxx>
67#include <filter/BmpWriter.hxx>
68#include <filter/WebpReader.hxx>
69#include <filter/WebpWriter.hxx>
70#include <osl/module.hxx>
71#include <com/sun/star/uno/Reference.h>
72#include <com/sun/star/awt/Size.hpp>
73#include <com/sun/star/uno/XInterface.hpp>
74#include <com/sun/star/io/XActiveDataSource.hpp>
75#include <com/sun/star/io/XOutputStream.hpp>
76#include <com/sun/star/svg/XSVGWriter.hpp>
77#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
78#include <com/sun/star/xml/sax/Writer.hpp>
80#include <rtl/bootstrap.hxx>
81#include <tools/svlibrary.h>
82#include <comphelper/string.hxx>
84#include <vector>
85#include <memory>
86#include <mutex>
87#include <string_view>
88#include <o3tl/string_view.hxx>
90
91#include "FilterConfigCache.hxx"
92
95
96// Support for GfxLinkType::NativeWebp is so far disabled,
97// as enabling it would write .webp images e.g. to .odt documents,
98// making those images unreadable for older readers. So for now
99// disable the support so that .webp images will be written out as .png,
100// and somewhen later enable the support unconditionally.
101static bool supportNativeWebp()
102{
103 const char* const testname = getenv("LO_TESTNAME");
104 if(testname == nullptr)
105 return false;
106 // Enable support only for those unittests that test it.
107 if( std::string_view("_anonymous_namespace___GraphicTest__testUnloadedGraphicLoading_") == testname
108 || std::string_view("VclFiltersTest__testExportImport_") == testname
109 || o3tl::starts_with(std::string_view(testname), "WebpFilterTest__"))
110 return true;
111 return false;
112}
113
114static std::vector< GraphicFilter* > gaFilterHdlList;
115
116static std::mutex& getListMutex()
117{
118 static std::mutex s_aListProtection;
119 return s_aListProtection;
120}
121
122namespace {
123
124class ImpFilterOutputStream : public ::cppu::WeakImplHelper< css::io::XOutputStream >
125{
126 SvStream& mrStm;
127
128 virtual void SAL_CALL writeBytes( const css::uno::Sequence< sal_Int8 >& rData ) override
129 { mrStm.WriteBytes(rData.getConstArray(), rData.getLength()); }
130 virtual void SAL_CALL flush() override
131 { mrStm.FlushBuffer(); }
132 virtual void SAL_CALL closeOutput() override {}
133
134public:
135
136 explicit ImpFilterOutputStream( SvStream& rStm ) : mrStm( rStm ) {}
137};
138
139}
140
141// Helper functions
142
143static OUString ImpGetExtension( std::u16string_view rPath )
144{
145 OUString aExt;
146 INetURLObject aURL( rPath );
147 aExt = aURL.GetFileExtension().toAsciiUpperCase();
148 return aExt;
149}
150
151ErrCode GraphicFilter::ImpTestOrFindFormat( std::u16string_view rPath, SvStream& rStream, sal_uInt16& rFormat )
152{
153 // determine or check the filter/format by reading into it
154 if( rFormat == GRFILTER_FORMAT_DONTKNOW )
155 {
156 OUString aFormatExt;
157 if (vcl::peekGraphicFormat(rStream, aFormatExt, false))
158 {
159 rFormat = pConfig->GetImportFormatNumberForExtension( aFormatExt );
160 if( rFormat != GRFILTER_FORMAT_DONTKNOW )
161 return ERRCODE_NONE;
162 }
163 // determine filter by file extension
164 if( !rPath.empty() )
165 {
166 OUString aExt( ImpGetExtension( rPath ) );
168 if( rFormat != GRFILTER_FORMAT_DONTKNOW )
169 return ERRCODE_NONE;
170 }
172 }
173 else
174 {
175 OUString aTmpStr( pConfig->GetImportFormatExtension( rFormat ) );
176 aTmpStr = aTmpStr.toAsciiUpperCase();
177 if (!vcl::peekGraphicFormat(rStream, aTmpStr, true))
179 if ( pConfig->GetImportFormatExtension( rFormat ).equalsIgnoreAsciiCase( "pcd" ) )
180 {
181 sal_Int32 nBase = 2; // default Base0
182 if ( pConfig->GetImportFilterType( rFormat ).equalsIgnoreAsciiCase( "pcd_Photo_CD_Base4" ) )
183 nBase = 1;
184 else if ( pConfig->GetImportFilterType( rFormat ).equalsIgnoreAsciiCase( "pcd_Photo_CD_Base16" ) )
185 nBase = 0;
186 FilterConfigItem aFilterConfigItem( u"Office.Common/Filter/Graphic/Import/PCD" );
187 aFilterConfigItem.WriteInt32( "Resolution", nBase );
188 }
189 }
190
191 return ERRCODE_NONE;
192}
193
194static Graphic ImpGetScaledGraphic( const Graphic& rGraphic, FilterConfigItem& rConfigItem )
195{
196 Graphic aGraphic;
197
198 sal_Int32 nLogicalWidth = rConfigItem.ReadInt32( "LogicalWidth", 0 );
199 sal_Int32 nLogicalHeight = rConfigItem.ReadInt32( "LogicalHeight", 0 );
200
201 if ( rGraphic.GetType() != GraphicType::NONE )
202 {
203 sal_Int32 nMode = rConfigItem.ReadInt32( "ExportMode", -1 );
204
205 if ( nMode == -1 ) // the property is not there, this is possible, if the graphic filter
206 { // is called via UnoGraphicExporter and not from a graphic export Dialog
207 nMode = 0; // then we are defaulting this mode to 0
208 if ( nLogicalWidth || nLogicalHeight )
209 nMode = 2;
210 }
211
212 Size aOriginalSize;
213 Size aPrefSize( rGraphic.GetPrefSize() );
214 MapMode aPrefMapMode( rGraphic.GetPrefMapMode() );
215 if (aPrefMapMode.GetMapUnit() == MapUnit::MapPixel)
216 aOriginalSize = Application::GetDefaultDevice()->PixelToLogic(aPrefSize, MapMode(MapUnit::Map100thMM));
217 else
218 aOriginalSize = OutputDevice::LogicToLogic(aPrefSize, aPrefMapMode, MapMode(MapUnit::Map100thMM));
219 if ( !nLogicalWidth )
220 nLogicalWidth = aOriginalSize.Width();
221 if ( !nLogicalHeight )
222 nLogicalHeight = aOriginalSize.Height();
223 if( rGraphic.GetType() == GraphicType::Bitmap )
224 {
225
226 // Resolution is set
227 if( nMode == 1 )
228 {
229 BitmapEx aBitmap( rGraphic.GetBitmapEx() );
230 MapMode aMap( MapUnit::Map100thInch );
231
232 sal_Int32 nDPI = rConfigItem.ReadInt32( "Resolution", 75 );
233 Fraction aFrac( 1, std::clamp( nDPI, sal_Int32(75), sal_Int32(600) ) );
234
235 aMap.SetScaleX( aFrac );
236 aMap.SetScaleY( aFrac );
237
238 Size aOldSize = aBitmap.GetSizePixel();
239 aGraphic = rGraphic;
240 aGraphic.SetPrefMapMode( aMap );
241 aGraphic.SetPrefSize( Size( aOldSize.Width() * 100,
242 aOldSize.Height() * 100 ) );
243 }
244 // Size is set
245 else if( nMode == 2 )
246 {
247 aGraphic = rGraphic;
248 aGraphic.SetPrefMapMode( MapMode( MapUnit::Map100thMM ) );
249 aGraphic.SetPrefSize( Size( nLogicalWidth, nLogicalHeight ) );
250 }
251 else
252 aGraphic = rGraphic;
253
254 sal_Int32 nColors = rConfigItem.ReadInt32( "Color", 0 );
255 if ( nColors ) // graphic conversion necessary ?
256 {
257 BitmapEx aBmpEx( aGraphic.GetBitmapEx() );
258 aBmpEx.Convert( static_cast<BmpConversion>(nColors) ); // the entries in the xml section have the same meaning as
259 aGraphic = aBmpEx; // they have in the BmpConversion enum, so it should be
260 } // allowed to cast them
261 }
262 else
263 {
264 if( ( nMode == 1 ) || ( nMode == 2 ) )
265 {
266 GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
267 Size aNewSize( OutputDevice::LogicToLogic(Size(nLogicalWidth, nLogicalHeight), MapMode(MapUnit::Map100thMM), aMtf.GetPrefMapMode()) );
268
269 if( aNewSize.Width() && aNewSize.Height() )
270 {
271 const Size aPreferredSize( aMtf.GetPrefSize() );
272 aMtf.Scale( Fraction( aNewSize.Width(), aPreferredSize.Width() ),
273 Fraction( aNewSize.Height(), aPreferredSize.Height() ) );
274 }
275 aGraphic = Graphic( aMtf );
276 }
277 else
278 aGraphic = rGraphic;
279 }
280
281 }
282 else
283 aGraphic = rGraphic;
284
285 return aGraphic;
286}
287
289 : bUseConfig(bConfig)
290{
291 ImplInit();
292}
293
295{
296 {
297 std::scoped_lock aGuard( getListMutex() );
298 auto it = std::find(gaFilterHdlList.begin(), gaFilterHdlList.end(), this);
299 if( it != gaFilterHdlList.end() )
300 gaFilterHdlList.erase( it );
301
302 if( gaFilterHdlList.empty() )
303 delete pConfig;
304 }
305
306 mxErrorEx.reset();
307}
308
310{
311 {
312 std::scoped_lock aGuard( getListMutex() );
313
314 if ( gaFilterHdlList.empty() )
316 else
317 pConfig = gaFilterHdlList.front()->pConfig;
318
319 gaFilterHdlList.push_back( this );
320 }
321
322 if( bUseConfig )
323 {
324 OUString url("$BRAND_BASE_DIR/" LIBO_LIB_FOLDER);
325 rtl::Bootstrap::expandMacros(url); //TODO: detect failure
326 osl::FileBase::getSystemPathFromFileURL(url, aFilterPath);
327 }
328
330}
331
333{
334 mxErrorEx = pStm ? pStm->GetError() : ERRCODE_NONE;
335 return nError;
336}
337
339{
341}
342
343sal_uInt16 GraphicFilter::GetImportFormatNumber( std::u16string_view rFormatName )
344{
345 return pConfig->GetImportFormatNumber( rFormatName );
346}
347
348sal_uInt16 GraphicFilter::GetImportFormatNumberForShortName( std::u16string_view rShortName )
349{
350 return pConfig->GetImportFormatNumberForShortName( rShortName );
351}
352
353sal_uInt16 GraphicFilter::GetImportFormatNumberForTypeName( std::u16string_view rType )
354{
356}
357
358OUString GraphicFilter::GetImportFormatName( sal_uInt16 nFormat )
359{
360 return pConfig->GetImportFormatName( nFormat );
361}
362
363OUString GraphicFilter::GetImportFormatTypeName( sal_uInt16 nFormat )
364{
365 return pConfig->GetImportFilterTypeName( nFormat );
366}
367
368#ifdef _WIN32
369OUString GraphicFilter::GetImportFormatMediaType( sal_uInt16 nFormat )
370{
371 return pConfig->GetImportFormatMediaType( nFormat );
372}
373#endif
374
375OUString GraphicFilter::GetImportFormatShortName( sal_uInt16 nFormat )
376{
377 return pConfig->GetImportFormatShortName( nFormat );
378}
379
380OUString GraphicFilter::GetImportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry )
381{
382 return pConfig->GetImportWildcard( nFormat, nEntry );
383}
384
386{
388}
389
390sal_uInt16 GraphicFilter::GetExportFormatNumber( std::u16string_view rFormatName )
391{
392 return pConfig->GetExportFormatNumber( rFormatName );
393}
394
395sal_uInt16 GraphicFilter::GetExportFormatNumberForMediaType( std::u16string_view rMediaType )
396{
397 return pConfig->GetExportFormatNumberForMediaType( rMediaType );
398}
399
400sal_uInt16 GraphicFilter::GetExportFormatNumberForShortName( std::u16string_view rShortName )
401{
402 return pConfig->GetExportFormatNumberForShortName( rShortName );
403}
404
405OUString GraphicFilter::GetExportInternalFilterName( sal_uInt16 nFormat )
406{
407 return pConfig->GetExportInternalFilterName( nFormat );
408}
409
410sal_uInt16 GraphicFilter::GetExportFormatNumberForTypeName( std::u16string_view rType )
411{
413}
414
415OUString GraphicFilter::GetExportFormatName( sal_uInt16 nFormat )
416{
417 return pConfig->GetExportFormatName( nFormat );
418}
419
420OUString GraphicFilter::GetExportFormatMediaType( sal_uInt16 nFormat )
421{
422 return pConfig->GetExportFormatMediaType( nFormat );
423}
424
425OUString GraphicFilter::GetExportFormatShortName( sal_uInt16 nFormat )
426{
427 return pConfig->GetExportFormatShortName( nFormat );
428}
429
430OUString GraphicFilter::GetExportWildcard( sal_uInt16 nFormat )
431{
432 return pConfig->GetExportWildcard( nFormat, 0 );
433}
434
435bool GraphicFilter::IsExportPixelFormat( sal_uInt16 nFormat )
436{
437 return pConfig->IsExportPixelFormat( nFormat );
438}
439
441 sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat )
442{
444 SAL_WARN_IF( rPath.GetProtocol() == INetProtocol::NotValid, "vcl.filter", "GraphicFilter::CanImportGraphic() : ProtType == INetProtocol::NotValid" );
445
446 OUString aMainUrl( rPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
447 std::unique_ptr<SvStream> xStream(::utl::UcbStreamHelper::CreateStream( aMainUrl, StreamMode::READ | StreamMode::SHARE_DENYNONE ));
448 if (xStream)
449 {
450 nRetValue = CanImportGraphic( aMainUrl, *xStream, nFormat, pDeterminedFormat );
451 }
452 return nRetValue;
453}
454
455ErrCode GraphicFilter::CanImportGraphic( std::u16string_view rMainUrl, SvStream& rIStream,
456 sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat )
457{
458 sal_uInt64 nStreamPos = rIStream.Tell();
459 ErrCode nRes = ImpTestOrFindFormat( rMainUrl, rIStream, nFormat );
460
461 rIStream.Seek(nStreamPos);
462
463 if( nRes==ERRCODE_NONE && pDeterminedFormat!=nullptr )
464 *pDeterminedFormat = nFormat;
465
466 return ImplSetError( nRes, &rIStream );
467}
468
469//SJ: TODO, we need to create a GraphicImporter component
471 sal_uInt16 nFormat, sal_uInt16 * pDeterminedFormat, GraphicFilterImportFlags nImportFlags )
472{
474 SAL_WARN_IF( rPath.GetProtocol() == INetProtocol::NotValid, "vcl.filter", "GraphicFilter::ImportGraphic() : ProtType == INetProtocol::NotValid" );
475
476 OUString aMainUrl( rPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
477 std::unique_ptr<SvStream> xStream(::utl::UcbStreamHelper::CreateStream( aMainUrl, StreamMode::READ | StreamMode::SHARE_DENYNONE ));
478 if (xStream)
479 {
480 nRetValue = ImportGraphic( rGraphic, aMainUrl, *xStream, nFormat, pDeterminedFormat, nImportFlags );
481 }
482 return nRetValue;
483}
484
485namespace {
486
489struct GraphicImportContext
490{
492 std::unique_ptr<SvStream> m_pStream;
494 std::shared_ptr<Graphic> m_pGraphic;
496 std::unique_ptr<BitmapScopedWriteAccess> m_pAccess;
497 std::unique_ptr<AlphaScopedWriteAccess> m_pAlphaAccess;
498 // Need to have an AlphaMask instance to keep its lifetime.
499 AlphaMask mAlphaMask;
503 GfxLinkType m_eLinkType = GfxLinkType::NONE;
505 sal_uInt64 m_nStreamBegin = 0;
508};
509
511class GraphicImportTask : public comphelper::ThreadTask
512{
513 GraphicImportContext& m_rContext;
514public:
515 GraphicImportTask(const std::shared_ptr<comphelper::ThreadTaskTag>& pTag, GraphicImportContext& rContext);
516 void doWork() override;
518 static void doImport(GraphicImportContext& rContext);
519};
520
521}
522
523GraphicImportTask::GraphicImportTask(const std::shared_ptr<comphelper::ThreadTaskTag>& pTag, GraphicImportContext& rContext)
524 : comphelper::ThreadTask(pTag),
525 m_rContext(rContext)
526{
527}
528
529void GraphicImportTask::doWork()
530{
531 GraphicImportTask::doImport(m_rContext);
532}
533
534void GraphicImportTask::doImport(GraphicImportContext& rContext)
535{
536 if(rContext.m_eLinkType == GfxLinkType::NativeJpg)
537 {
538 if (!ImportJPEG(*rContext.m_pStream, *rContext.m_pGraphic, rContext.m_nImportFlags | GraphicFilterImportFlags::UseExistingBitmap, rContext.m_pAccess.get()))
539 rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
540 }
541 else if(rContext.m_eLinkType == GfxLinkType::NativePng)
542 {
543 if (!vcl::ImportPNG(*rContext.m_pStream, *rContext.m_pGraphic,
544 rContext.m_nImportFlags | GraphicFilterImportFlags::UseExistingBitmap,
545 rContext.m_pAccess.get(), rContext.m_pAlphaAccess.get()))
546 {
547 rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
548 }
549 }
550}
551
552void GraphicFilter::ImportGraphics(std::vector< std::shared_ptr<Graphic> >& rGraphics, std::vector< std::unique_ptr<SvStream> > vStreams)
553{
554 static bool bThreads = !getenv("VCL_NO_THREAD_IMPORT");
555 std::vector<GraphicImportContext> aContexts;
556 aContexts.reserve(vStreams.size());
558 std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag();
559
560 for (auto& pStream : vStreams)
561 {
562 aContexts.emplace_back();
563 GraphicImportContext& rContext = aContexts.back();
564
565 if (pStream)
566 {
567 rContext.m_pStream = std::move(pStream);
568 rContext.m_pGraphic = std::make_shared<Graphic>();
569 rContext.m_nStatus = ERRCODE_NONE;
570
571 // Detect the format.
573 rContext.m_nStreamBegin = rContext.m_pStream->Tell();
574 sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
575 rContext.m_nStatus = ImpTestOrFindFormat(u"", *rContext.m_pStream, nFormat);
576 rContext.m_pStream->Seek(rContext.m_nStreamBegin);
577
578 // Import the graphic.
579 if (rContext.m_nStatus == ERRCODE_NONE && !rContext.m_pStream->GetError())
580 {
581 OUString aFilterName = pConfig->GetImportFilterName(nFormat);
582
583 if (aFilterName.equalsIgnoreAsciiCase(IMP_JPEG))
584 {
585 rContext.m_eLinkType = GfxLinkType::NativeJpg;
586 rContext.m_nImportFlags = GraphicFilterImportFlags::SetLogsizeForJpeg;
587
588 if (ImportJPEG( *rContext.m_pStream, *rContext.m_pGraphic, rContext.m_nImportFlags | GraphicFilterImportFlags::OnlyCreateBitmap, nullptr))
589 {
590 Bitmap& rBitmap = const_cast<Bitmap&>(rContext.m_pGraphic->GetBitmapExRef().GetBitmap());
591 rContext.m_pAccess = std::make_unique<BitmapScopedWriteAccess>(rBitmap);
592 rContext.m_pStream->Seek(rContext.m_nStreamBegin);
593 if (bThreads)
594 rSharedPool.pushTask(std::make_unique<GraphicImportTask>(pTag, rContext));
595 else
596 GraphicImportTask::doImport(rContext);
597 }
598 else
599 rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
600 }
601 else if (aFilterName.equalsIgnoreAsciiCase(IMP_PNG))
602 {
603 rContext.m_eLinkType = GfxLinkType::NativePng;
604
605 if (vcl::ImportPNG( *rContext.m_pStream, *rContext.m_pGraphic, rContext.m_nImportFlags | GraphicFilterImportFlags::OnlyCreateBitmap, nullptr, nullptr))
606 {
607 const BitmapEx& rBitmapEx = rContext.m_pGraphic->GetBitmapExRef();
608 Bitmap& rBitmap = const_cast<Bitmap&>(rBitmapEx.GetBitmap());
609 rContext.m_pAccess = std::make_unique<BitmapScopedWriteAccess>(rBitmap);
610 if(rBitmapEx.IsAlpha())
611 {
612 // The separate alpha bitmap causes a number of complications. Not only
613 // we need to have an extra bitmap access for it, but we also need
614 // to keep an AlphaMask instance in the context. This is because
615 // BitmapEx internally keeps Bitmap and not AlphaMask (because the Bitmap
616 // may be also a mask, not alpha). So BitmapEx::GetAlpha() returns
617 // a temporary, and direct access to the Bitmap wouldn't work
618 // with AlphaScopedBitmapAccess. *sigh*
619 rContext.mAlphaMask = rBitmapEx.GetAlphaMask();
620 rContext.m_pAlphaAccess = std::make_unique<AlphaScopedWriteAccess>(rContext.mAlphaMask);
621 }
622 rContext.m_pStream->Seek(rContext.m_nStreamBegin);
623 if (bThreads)
624 rSharedPool.pushTask(std::make_unique<GraphicImportTask>(pTag, rContext));
625 else
626 GraphicImportTask::doImport(rContext);
627 }
628 else
629 rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
630 }
631 else
632 rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
633 }
634 }
635 }
636
637 rSharedPool.waitUntilDone(pTag);
638
639 // Process data after import.
640 for (auto& rContext : aContexts)
641 {
642 if(rContext.m_pAlphaAccess) // Need to move the AlphaMask back to the BitmapEx.
643 *rContext.m_pGraphic = BitmapEx( rContext.m_pGraphic->GetBitmapExRef().GetBitmap(), rContext.mAlphaMask );
644 rContext.m_pAccess.reset();
645 rContext.m_pAlphaAccess.reset();
646
647 if (rContext.m_nStatus == ERRCODE_NONE && (rContext.m_eLinkType != GfxLinkType::NONE) && !rContext.m_pGraphic->GetReaderContext())
648 {
649 BinaryDataContainer aGraphicContent;
650
651 const sal_uInt64 nStreamEnd = rContext.m_pStream->Tell();
652 sal_Int32 nGraphicContentSize = nStreamEnd - rContext.m_nStreamBegin;
653
654 if (nGraphicContentSize > 0)
655 {
656 try
657 {
658 rContext.m_pStream->Seek(rContext.m_nStreamBegin);
659 aGraphicContent = BinaryDataContainer(*rContext.m_pStream, nGraphicContentSize);
660 }
661 catch (const std::bad_alloc&)
662 {
663 rContext.m_nStatus = ERRCODE_GRFILTER_TOOBIG;
664 }
665 }
666
667 if (rContext.m_nStatus == ERRCODE_NONE)
668 rContext.m_pGraphic->SetGfxLink(std::make_shared<GfxLink>(aGraphicContent, rContext.m_eLinkType));
669 }
670
671 if (rContext.m_nStatus != ERRCODE_NONE)
672 rContext.m_pGraphic = nullptr;
673
674 rGraphics.push_back(rContext.m_pGraphic);
675 }
676}
677
678void GraphicFilter::MakeGraphicsAvailableThreaded(std::vector<Graphic*>& graphics)
679{
680 // Graphic::makeAvailable() is not thread-safe. Only the jpeg and png loaders are, so here
681 // we process only jpeg and png images that also have their stream data, load new Graphic's
682 // from them and then update the passed objects using them.
683 std::vector< Graphic* > toLoad;
684 for(auto graphic : graphics)
685 {
686 // Need to use GetSharedGfxLink, to access the pointer without copying.
687 if(!graphic->isAvailable() && graphic->IsGfxLink()
688 && graphic->GetSharedGfxLink()->GetDataSize() != 0
689 && (graphic->GetSharedGfxLink()->GetType() == GfxLinkType::NativeJpg
690 || graphic->GetSharedGfxLink()->GetType() == GfxLinkType::NativePng))
691 {
692 // Graphic objects share internal ImpGraphic, do not process any of those twice.
693 const auto predicate = [graphic](Graphic* item) { return item->ImplGetImpGraphic() == graphic->ImplGetImpGraphic(); };
694 if( std::none_of(toLoad.begin(), toLoad.end(), predicate ))
695 toLoad.push_back( graphic );
696 }
697 }
698 if( toLoad.empty())
699 return;
700 std::vector< std::unique_ptr<SvStream>> streams;
701 for( auto graphic : toLoad )
702 {
703 streams.push_back( std::make_unique<SvMemoryStream>( const_cast<sal_uInt8*>(graphic->GetSharedGfxLink()->GetData()),
704 graphic->GetSharedGfxLink()->GetDataSize(), StreamMode::READ | StreamMode::WRITE));
705 }
706 std::vector< std::shared_ptr<Graphic>> loadedGraphics;
707 ImportGraphics(loadedGraphics, std::move(streams));
708 assert(loadedGraphics.size() == toLoad.size());
709 for( size_t i = 0; i < toLoad.size(); ++i )
710 {
711 if(loadedGraphics[ i ] != nullptr)
712 toLoad[ i ]->ImplGetImpGraphic()->updateFromLoadedGraphic(loadedGraphics[ i ]->ImplGetImpGraphic());
713 }
714}
715
717 const Size* pSizeHint)
718{
719 Graphic aGraphic;
720 sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
721 GfxLinkType eLinkType = GfxLinkType::NONE;
722
724
725 const sal_uInt64 nStreamBegin = rIStream.Tell();
726
727 rIStream.Seek(nStreamBegin);
728
729 ErrCode nStatus = ImpTestOrFindFormat(u"", rIStream, nFormat);
730
731 rIStream.Seek(nStreamBegin);
732 sal_uInt32 nStreamLength(rIStream.remainingSize());
733 if (sizeLimit && sizeLimit < nStreamLength)
734 nStreamLength = sizeLimit;
735
736 OUString aFilterName = pConfig->GetImportFilterName(nFormat);
737
738 BinaryDataContainer aGraphicContent;
739
740 // read graphic
741 {
742 if (aFilterName.equalsIgnoreAsciiCase(IMP_GIF))
743 {
744 eLinkType = GfxLinkType::NativeGif;
745 }
746 else if (aFilterName.equalsIgnoreAsciiCase(IMP_PNG))
747 {
748 // check if this PNG contains a GIF chunk!
749 aGraphicContent = vcl::PngImageReader::getMicrosoftGifChunk(rIStream);
750 if (!aGraphicContent.isEmpty())
751 eLinkType = GfxLinkType::NativeGif;
752 else
753 eLinkType = GfxLinkType::NativePng;
754 }
755 else if (aFilterName.equalsIgnoreAsciiCase(IMP_JPEG))
756 {
757 eLinkType = GfxLinkType::NativeJpg;
758 }
759 else if (aFilterName.equalsIgnoreAsciiCase(IMP_SVG))
760 {
761 bool bOkay(false);
762
763 if (nStreamLength > 0)
764 {
765 std::vector<sal_uInt8> aTwoBytes(2);
766 rIStream.ReadBytes(aTwoBytes.data(), 2);
767 rIStream.Seek(nStreamBegin);
768
769 if (aTwoBytes[0] == 0x1F && aTwoBytes[1] == 0x8B)
770 {
771 SvMemoryStream aMemStream;
772 ZCodec aCodec;
773 tools::Long nMemoryLength;
774
775 aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/true);
776 nMemoryLength = aCodec.Decompress(rIStream, aMemStream);
777 aCodec.EndCompression();
778
779 if (!rIStream.GetError() && nMemoryLength >= 0)
780 {
781 aMemStream.Seek(STREAM_SEEK_TO_BEGIN);
782 aGraphicContent = BinaryDataContainer(aMemStream, nMemoryLength);
783
784 bOkay = true;
785 }
786 }
787 else
788 {
789 aGraphicContent = BinaryDataContainer(rIStream, nStreamLength);
790
791 bOkay = true;
792 }
793 }
794
795 if (bOkay)
796 {
797 eLinkType = GfxLinkType::NativeSvg;
798 }
799 else
800 {
802 }
803 }
804 else if (aFilterName.equalsIgnoreAsciiCase(IMP_BMP))
805 {
806 eLinkType = GfxLinkType::NativeBmp;
807 }
808 else if (aFilterName.equalsIgnoreAsciiCase(IMP_MOV))
809 {
810 eLinkType = GfxLinkType::NativeMov;
811 }
812 else if (aFilterName.equalsIgnoreAsciiCase(IMP_WMF) ||
813 aFilterName.equalsIgnoreAsciiCase(IMP_EMF) ||
814 aFilterName.equalsIgnoreAsciiCase(IMP_WMZ) ||
815 aFilterName.equalsIgnoreAsciiCase(IMP_EMZ))
816 {
817 rIStream.Seek(nStreamBegin);
818 if (ZCodec::IsZCompressed(rIStream))
819 {
820 ZCodec aCodec;
821 SvMemoryStream aMemStream;
822 tools::Long nMemoryLength;
823 aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/true);
824 nMemoryLength = aCodec.Decompress(rIStream, aMemStream);
825 aCodec.EndCompression();
826
827 if (!rIStream.GetError() && nMemoryLength >= 0)
828 {
829 aMemStream.Seek(STREAM_SEEK_TO_BEGIN);
830 aGraphicContent = BinaryDataContainer(aMemStream, nMemoryLength);
831 }
832 }
833 else
834 {
835 aGraphicContent = BinaryDataContainer(rIStream, nStreamLength);
836 }
837 if (!rIStream.GetError())
838 {
839 eLinkType = GfxLinkType::NativeWmf;
840 }
841 else
842 {
844 }
845 }
846 else if (aFilterName == IMP_PDF)
847 {
848 eLinkType = GfxLinkType::NativePdf;
849 }
850 else if (aFilterName == IMP_TIFF)
851 {
852 eLinkType = GfxLinkType::NativeTif;
853 }
854 else if (aFilterName == IMP_PICT)
855 {
856 eLinkType = GfxLinkType::NativePct;
857 }
858 else if (aFilterName == IMP_MET)
859 {
860 eLinkType = GfxLinkType::NativeMet;
861 }
862 else if (aFilterName.equalsIgnoreAsciiCase(IMP_WEBP))
863 {
865 eLinkType = GfxLinkType::NativeWebp;
866 else
868 }
869 else
870 {
872 }
873 }
874
875 if (nStatus == ERRCODE_NONE && eLinkType != GfxLinkType::NONE)
876 {
877 if (aGraphicContent.isEmpty())
878 {
879 if (nStreamLength > 0)
880 {
881 try
882 {
883 rIStream.Seek(nStreamBegin);
884 aGraphicContent = BinaryDataContainer(rIStream, nStreamLength);
885 }
886 catch (const std::bad_alloc&)
887 {
888 nStatus = ERRCODE_GRFILTER_TOOBIG;
889 }
890 }
891 }
892
893 if( nStatus == ERRCODE_NONE )
894 {
895 bool bAnimated = false;
896 Size aLogicSize;
897 if (eLinkType == GfxLinkType::NativeGif && !aGraphicContent.isEmpty())
898 {
899 std::shared_ptr<SvStream> pMemoryStream = aGraphicContent.getAsStream();
900 bAnimated = IsGIFAnimated(*pMemoryStream, aLogicSize);
901 if (!pSizeHint && aLogicSize.getWidth() && aLogicSize.getHeight())
902 {
903 pSizeHint = &aLogicSize;
904 }
905 }
906 aGraphic.SetGfxLink(std::make_shared<GfxLink>(aGraphicContent, eLinkType));
907 aGraphic.ImplGetImpGraphic()->setPrepared(bAnimated, pSizeHint);
908 }
909 }
910
911 // Set error code or try to set native buffer
912 if (nStatus != ERRCODE_NONE)
913 ImplSetError(nStatus, &rIStream);
914 if (nStatus != ERRCODE_NONE || eLinkType == GfxLinkType::NONE)
915 rIStream.Seek(nStreamBegin);
916
917 return aGraphic;
918}
919
920ErrCode GraphicFilter::readGIF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
921{
922 if (ImportGIF(rStream, rGraphic))
923 {
924 rLinkType = GfxLinkType::NativeGif;
925 return ERRCODE_NONE;
926 }
927 else
929}
930
931ErrCode GraphicFilter::readPNG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, BinaryDataContainer& rpGraphicContent)
932{
933 ErrCode aReturnCode = ERRCODE_NONE;
934
935 // check if this PNG contains a GIF chunk!
936 if (auto aMSGifChunk = vcl::PngImageReader::getMicrosoftGifChunk(rStream);
937 !aMSGifChunk.isEmpty())
938 {
939 std::shared_ptr<SvStream> pIStrm(aMSGifChunk.getAsStream());
940 ImportGIF(*pIStrm, rGraphic);
941 rLinkType = GfxLinkType::NativeGif;
942 rpGraphicContent = aMSGifChunk;
943 return aReturnCode;
944 }
945
946 // PNG has no GIF chunk
947 vcl::PngImageReader aPNGReader(rStream);
948 BitmapEx aBitmapEx(aPNGReader.read());
949 if (!aBitmapEx.IsEmpty())
950 {
951 rGraphic = aBitmapEx;
952 rLinkType = GfxLinkType::NativePng;
953 }
954 else
955 aReturnCode = ERRCODE_GRFILTER_FILTERERROR;
956
957 return aReturnCode;
958}
959
961{
962 ErrCode aReturnCode = ERRCODE_NONE;
963
964 // set LOGSIZE flag always, if not explicitly disabled
965 // (see #90508 and #106763)
967 {
969 }
970
971 sal_uInt64 nPosition = rStream.Tell();
972 if (!ImportJPEG(rStream, rGraphic, nImportFlags | GraphicFilterImportFlags::OnlyCreateBitmap, nullptr))
973 aReturnCode = ERRCODE_GRFILTER_FILTERERROR;
974 else
975 {
976 Bitmap& rBitmap = const_cast<Bitmap&>(rGraphic.GetBitmapExRef().GetBitmap());
977 BitmapScopedWriteAccess pWriteAccess(rBitmap);
978 rStream.Seek(nPosition);
979 if (!ImportJPEG(rStream, rGraphic, nImportFlags | GraphicFilterImportFlags::UseExistingBitmap, &pWriteAccess))
980 aReturnCode = ERRCODE_GRFILTER_FILTERERROR;
981 else
982 rLinkType = GfxLinkType::NativeJpg;
983 }
984
985 return aReturnCode;
986}
987
988ErrCode GraphicFilter::readSVG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, BinaryDataContainer& rpGraphicContent)
989{
990 ErrCode aReturnCode = ERRCODE_NONE;
991
992 const sal_uInt64 nStreamPosition(rStream.Tell());
993 const sal_uInt64 nStreamLength(rStream.remainingSize());
994
995 bool bOkay(false);
996
997 if (nStreamLength > 0)
998 {
999 std::vector<sal_uInt8> aTwoBytes(2);
1000 rStream.ReadBytes(aTwoBytes.data(), 2);
1001 rStream.Seek(nStreamPosition);
1002
1003 if (aTwoBytes[0] == 0x1F && aTwoBytes[1] == 0x8B)
1004 {
1005 SvMemoryStream aMemStream;
1006 ZCodec aCodec;
1007 tools::Long nMemoryLength;
1008
1009 aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/true);
1010 nMemoryLength = aCodec.Decompress(rStream, aMemStream);
1011 aCodec.EndCompression();
1012
1013 if (!rStream.GetError() && nMemoryLength >= 0)
1014 {
1015 aMemStream.Seek(STREAM_SEEK_TO_BEGIN);
1016 rpGraphicContent = BinaryDataContainer(aMemStream, nMemoryLength);
1017
1018 // Make a uncompressed copy for GfxLink
1019 if (!aMemStream.GetError())
1020 {
1021 auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(rpGraphicContent, VectorGraphicDataType::Svg);
1022 rGraphic = Graphic(aVectorGraphicDataPtr);
1023 bOkay = true;
1024 }
1025 }
1026 }
1027 else
1028 {
1029 BinaryDataContainer aNewData(rStream, nStreamLength);
1030
1031 if (!rStream.GetError())
1032 {
1033 auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(aNewData, VectorGraphicDataType::Svg);
1034 rGraphic = Graphic(aVectorGraphicDataPtr);
1035 bOkay = true;
1036 }
1037 }
1038 }
1039
1040 if (bOkay)
1041 {
1042 rLinkType = GfxLinkType::NativeSvg;
1043 }
1044 else
1045 {
1046 aReturnCode = ERRCODE_GRFILTER_FILTERERROR;
1047 }
1048
1049 return aReturnCode;
1050}
1051
1053{
1054 if (ImportXBM(rStream, rGraphic))
1055 return ERRCODE_NONE;
1056 else
1058}
1059
1061{
1062 if (ImportXPM(rStream, rGraphic))
1063 return ERRCODE_NONE;
1064 else
1066}
1067
1069{
1070 // use new UNO API service, do not directly import but create a
1071 // Graphic that contains the original data and decomposes to
1072 // primitives on demand
1073 sal_uInt32 nStreamLength(rStream.remainingSize());
1074 SvStream* aNewStream = &rStream;
1076 SvMemoryStream aMemStream;
1077 if (ZCodec::IsZCompressed(rStream))
1078 {
1079 ZCodec aCodec;
1080 aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/true);
1081 auto nDecompressLength = aCodec.Decompress(rStream, aMemStream);
1082 aCodec.EndCompression();
1083 aMemStream.Seek(STREAM_SEEK_TO_BEGIN);
1084 if (nDecompressLength >= 0)
1085 {
1086 nStreamLength = nDecompressLength;
1087 aNewStream = &aMemStream;
1088 }
1089 }
1090 BinaryDataContainer aNewData(*aNewStream, nStreamLength);
1091 if (!aNewStream->GetError())
1092 {
1093 auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(aNewData, eType);
1094
1095 rGraphic = Graphic(aVectorGraphicDataPtr);
1096 rLinkType = GfxLinkType::NativeWmf;
1097 aReturnCode = ERRCODE_NONE;
1098 }
1099
1100 return aReturnCode;
1101}
1102
1103ErrCode GraphicFilter::readWMF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
1104{
1105 return readWMF_EMF(rStream, rGraphic, rLinkType,VectorGraphicDataType::Wmf);
1106}
1107
1108ErrCode GraphicFilter::readEMF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
1109{
1110 return readWMF_EMF(rStream, rGraphic, rLinkType, VectorGraphicDataType::Emf);
1111}
1112
1113ErrCode GraphicFilter::readPDF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
1114{
1115 if (vcl::ImportPDF(rStream, rGraphic))
1116 {
1117 rLinkType = GfxLinkType::NativePdf;
1118 return ERRCODE_NONE;
1119 }
1120 else
1122}
1123
1125{
1126 if (ImportTiffGraphicImport(rStream, rGraphic))
1127 {
1128 rLinkType = GfxLinkType::NativeTif;
1129 return ERRCODE_NONE;
1130 }
1131 else
1133}
1134
1135ErrCode GraphicFilter::readWithTypeSerializer(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, std::u16string_view aFilterName)
1136{
1138
1139 // SV internal filters for import bitmaps and MetaFiles
1140 TypeSerializer aSerializer(rStream);
1141 aSerializer.readGraphic(rGraphic);
1142
1143 if (!rStream.GetError())
1144 {
1145 if (o3tl::equalsIgnoreAsciiCase(aFilterName, u"" IMP_MOV))
1146 {
1147 rGraphic.SetDefaultType();
1148 rStream.Seek(STREAM_SEEK_TO_END);
1149 rLinkType = GfxLinkType::NativeMov;
1150 }
1151 aReturnCode = ERRCODE_NONE;
1152 }
1153 return aReturnCode;
1154}
1155
1156ErrCode GraphicFilter::readBMP(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
1157{
1158 if (BmpReader(rStream, rGraphic))
1159 {
1160 rLinkType = GfxLinkType::NativeBmp;
1161 return ERRCODE_NONE;
1162 }
1163 else
1165}
1166
1168{
1169 if (ImportTgaGraphic(rStream, rGraphic))
1170 return ERRCODE_NONE;
1171 else
1173}
1174
1176{
1177 if (ImportPictGraphic(rStream, rGraphic))
1178 {
1179 rLinkType = GfxLinkType::NativePct;
1180 return ERRCODE_NONE;
1181 }
1182 else
1184}
1185
1186ErrCode GraphicFilter::readMET(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
1187{
1188 if (ImportMetGraphic(rStream, rGraphic))
1189 {
1190 rLinkType = GfxLinkType::NativeMet;
1191 return ERRCODE_NONE;
1192 }
1193 else
1195}
1196
1198{
1199 if (ImportRasGraphic(rStream, rGraphic))
1200 return ERRCODE_NONE;
1201 else
1203}
1204
1206{
1207 if (ImportPcxGraphic(rStream, rGraphic))
1208 return ERRCODE_NONE;
1209 else
1211}
1212
1214{
1215 if (ImportEpsGraphic(rStream, rGraphic))
1216 return ERRCODE_NONE;
1217 else
1219}
1220
1222{
1223 if (ImportPsdGraphic(rStream, rGraphic))
1224 return ERRCODE_NONE;
1225 else
1227}
1228
1230{
1231 std::unique_ptr<FilterConfigItem> pFilterConfigItem;
1233 {
1234 OUString aFilterConfigPath( "Office.Common/Filter/Graphic/Import/PCD" );
1235 pFilterConfigItem = std::make_unique<FilterConfigItem>(aFilterConfigPath);
1236 }
1237
1238 if (ImportPcdGraphic(rStream, rGraphic, pFilterConfigItem.get()))
1239 return ERRCODE_NONE;
1240 else
1242}
1243
1245{
1246 if (ImportPbmGraphic(rStream, rGraphic))
1247 return ERRCODE_NONE;
1248 else
1250}
1251
1253{
1254 if (ImportDxfGraphic(rStream, rGraphic))
1255 return ERRCODE_NONE;
1256 else
1258}
1259
1261{
1262 if (ImportWebpGraphic(rStream, rGraphic))
1263 {
1264 if(supportNativeWebp())
1265 rLinkType = GfxLinkType::NativeWebp;
1266 return ERRCODE_NONE;
1267 }
1268 else
1270}
1271
1272ErrCode GraphicFilter::ImportGraphic(Graphic& rGraphic, std::u16string_view rPath, SvStream& rIStream,
1273 sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, GraphicFilterImportFlags nImportFlags)
1274{
1275 OUString aFilterName;
1276 sal_uInt64 nStreamBegin;
1277 ErrCode nStatus;
1278 GfxLinkType eLinkType = GfxLinkType::NONE;
1279 const bool bLinkSet = rGraphic.IsGfxLink();
1280
1281 BinaryDataContainer aGraphicContent;
1282
1284
1285 std::shared_ptr<GraphicReader> pContext = rGraphic.GetReaderContext();
1286 bool bDummyContext = rGraphic.IsDummyContext();
1287 if( !pContext || bDummyContext )
1288 {
1289 if( bDummyContext )
1290 {
1291 rGraphic.SetDummyContext( false );
1292 nStreamBegin = 0;
1293 }
1294 else
1295 nStreamBegin = rIStream.Tell();
1296
1297 nStatus = ImpTestOrFindFormat( rPath, rIStream, nFormat );
1298 // if pending, return ERRCODE_NONE in order to request more bytes
1299 if( rIStream.GetError() == ERRCODE_IO_PENDING )
1300 {
1301 rGraphic.SetDummyContext(true);
1302 rIStream.ResetError();
1303 rIStream.Seek( nStreamBegin );
1304 return ImplSetError( ERRCODE_NONE );
1305 }
1306
1307 rIStream.Seek( nStreamBegin );
1308
1309 if( ( nStatus != ERRCODE_NONE ) || rIStream.GetError() )
1310 return ImplSetError( ( nStatus != ERRCODE_NONE ) ? nStatus : ERRCODE_GRFILTER_OPENERROR, &rIStream );
1311
1312 if( pDeterminedFormat )
1313 *pDeterminedFormat = nFormat;
1314
1315 aFilterName = pConfig->GetImportFilterName( nFormat );
1316 }
1317 else
1318 {
1319 aFilterName = pContext->GetUpperFilterName();
1320
1321 nStreamBegin = 0;
1322 nStatus = ERRCODE_NONE;
1323 }
1324
1325 // read graphic
1326 {
1327 if (aFilterName.equalsIgnoreAsciiCase(IMP_GIF))
1328 {
1329 nStatus = readGIF(rIStream, rGraphic, eLinkType);
1330 }
1331 else if (aFilterName.equalsIgnoreAsciiCase(IMP_PNG))
1332 {
1333 nStatus = readPNG(rIStream, rGraphic, eLinkType, aGraphicContent);
1334 }
1335 else if (aFilterName.equalsIgnoreAsciiCase(IMP_JPEG))
1336 {
1337 nStatus = readJPEG(rIStream, rGraphic, eLinkType, nImportFlags);
1338 }
1339 else if (aFilterName.equalsIgnoreAsciiCase(IMP_SVG) || aFilterName.equalsIgnoreAsciiCase(IMP_SVGZ))
1340 {
1341 nStatus = readSVG(rIStream, rGraphic, eLinkType, aGraphicContent);
1342 }
1343 else if( aFilterName.equalsIgnoreAsciiCase( IMP_XBM ) )
1344 {
1345 nStatus = readXBM(rIStream, rGraphic);
1346 }
1347 else if( aFilterName.equalsIgnoreAsciiCase( IMP_XPM ) )
1348 {
1349 nStatus = readXPM(rIStream, rGraphic);
1350 }
1351 else if (aFilterName.equalsIgnoreAsciiCase(IMP_BMP))
1352 {
1353 nStatus = readBMP(rIStream, rGraphic, eLinkType);
1354 }
1355 else if (aFilterName.equalsIgnoreAsciiCase(IMP_SVMETAFILE))
1356 {
1357 nStatus = readWithTypeSerializer(rIStream, rGraphic, eLinkType, aFilterName);
1358 }
1359 else if( aFilterName.equalsIgnoreAsciiCase(IMP_MOV))
1360 {
1361 nStatus = readWithTypeSerializer(rIStream, rGraphic, eLinkType, aFilterName);
1362 }
1363 else if (aFilterName.equalsIgnoreAsciiCase(IMP_WMF) || aFilterName.equalsIgnoreAsciiCase(IMP_WMZ))
1364 {
1365 nStatus = readWMF(rIStream, rGraphic, eLinkType);
1366 }
1367 else if (aFilterName.equalsIgnoreAsciiCase(IMP_EMF) || aFilterName.equalsIgnoreAsciiCase(IMP_EMZ))
1368 {
1369 nStatus = readEMF(rIStream, rGraphic, eLinkType);
1370 }
1371 else if (aFilterName.equalsIgnoreAsciiCase(IMP_PDF))
1372 {
1373 nStatus = readPDF(rIStream, rGraphic, eLinkType);
1374 }
1375 else if (aFilterName.equalsIgnoreAsciiCase(IMP_TIFF) )
1376 {
1377 nStatus = readTIFF(rIStream, rGraphic, eLinkType);
1378 }
1379 else if (aFilterName.equalsIgnoreAsciiCase(IMP_TGA) )
1380 {
1381 nStatus = readTGA(rIStream, rGraphic);
1382 }
1383 else if (aFilterName.equalsIgnoreAsciiCase(IMP_PICT))
1384 {
1385 nStatus = readPICT(rIStream, rGraphic, eLinkType);
1386 }
1387 else if (aFilterName.equalsIgnoreAsciiCase(IMP_MET))
1388 {
1389 nStatus = readMET(rIStream, rGraphic, eLinkType);
1390 }
1391 else if (aFilterName.equalsIgnoreAsciiCase(IMP_RAS))
1392 {
1393 nStatus = readRAS(rIStream, rGraphic);
1394 }
1395 else if (aFilterName.equalsIgnoreAsciiCase(IMP_PCX))
1396 {
1397 nStatus = readPCX(rIStream, rGraphic);
1398 }
1399 else if (aFilterName.equalsIgnoreAsciiCase(IMP_EPS))
1400 {
1401 nStatus = readEPS(rIStream, rGraphic);
1402 }
1403 else if (aFilterName.equalsIgnoreAsciiCase(IMP_PSD))
1404 {
1405 nStatus = readPSD(rIStream, rGraphic);
1406 }
1407 else if (aFilterName.equalsIgnoreAsciiCase(IMP_PCD))
1408 {
1409 nStatus = readPCD(rIStream, rGraphic);
1410 }
1411 else if (aFilterName.equalsIgnoreAsciiCase(IMP_PBM))
1412 {
1413 nStatus = readPBM(rIStream, rGraphic);
1414 }
1415 else if (aFilterName.equalsIgnoreAsciiCase(IMP_DXF))
1416 {
1417 nStatus = readDXF(rIStream, rGraphic);
1418 }
1419 else if (aFilterName.equalsIgnoreAsciiCase(IMP_WEBP))
1420 {
1421 nStatus = readWEBP(rIStream, rGraphic, eLinkType);
1422 }
1423 else
1425 }
1426
1427 if( nStatus == ERRCODE_NONE && ( eLinkType != GfxLinkType::NONE ) && !rGraphic.GetReaderContext() && !bLinkSet )
1428 {
1429 if (aGraphicContent.isEmpty())
1430 {
1431 const sal_uInt64 nStreamEnd = rIStream.Tell();
1432 const sal_uInt64 nGraphicContentSize = nStreamEnd - nStreamBegin;
1433
1434 if (nGraphicContentSize > 0)
1435 {
1436 try
1437 {
1438 rIStream.Seek(nStreamBegin);
1439 aGraphicContent = BinaryDataContainer(rIStream, nGraphicContentSize);
1440 }
1441 catch (const std::bad_alloc&)
1442 {
1443 nStatus = ERRCODE_GRFILTER_TOOBIG;
1444 }
1445 }
1446 }
1447 if( nStatus == ERRCODE_NONE )
1448 {
1449 rGraphic.SetGfxLink(std::make_shared<GfxLink>(aGraphicContent, eLinkType));
1450 }
1451 }
1452
1453 // Set error code or try to set native buffer
1454 if( nStatus != ERRCODE_NONE )
1455 {
1456 ImplSetError( nStatus, &rIStream );
1457 rIStream.Seek( nStreamBegin );
1458 rGraphic.Clear();
1459 }
1460
1461 return nStatus;
1462}
1463
1465 sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue >* pFilterData )
1466{
1467 SAL_INFO( "vcl.filter", "GraphicFilter::ExportGraphic() (thb)" );
1469 SAL_WARN_IF( rPath.GetProtocol() == INetProtocol::NotValid, "vcl.filter", "GraphicFilter::ExportGraphic() : ProtType == INetProtocol::NotValid" );
1470
1471 OUString aMainUrl(rPath.GetMainURL(INetURLObject::DecodeMechanism::NONE));
1472 bool bAlreadyExists = utl::UCBContentHelper::IsDocument(aMainUrl);
1473
1474 std::unique_ptr<SvStream> xStream(::utl::UcbStreamHelper::CreateStream( aMainUrl, StreamMode::WRITE | StreamMode::TRUNC ));
1475 if (xStream)
1476 {
1477 nRetValue = ExportGraphic( rGraphic, aMainUrl, *xStream, nFormat, pFilterData );
1478 xStream.reset();
1479
1480 if( ( ERRCODE_NONE != nRetValue ) && !bAlreadyExists )
1482 }
1483 return nRetValue;
1484}
1485
1486ErrCode GraphicFilter::ExportGraphic( const Graphic& rGraphic, std::u16string_view rPath,
1487 SvStream& rOStm, sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue >* pFilterData )
1488{
1489 SAL_INFO( "vcl.filter", "GraphicFilter::ExportGraphic() (thb)" );
1490 sal_uInt16 nFormatCount = GetExportFormatCount();
1491
1493 bool bShouldCompress = false;
1494 SvMemoryStream rCompressableStm;
1495
1496 if( nFormat == GRFILTER_FORMAT_DONTKNOW )
1497 {
1498 OUString aExt = ImpGetExtension( rPath );
1499 for( sal_uInt16 i = 0; i < nFormatCount; i++ )
1500 {
1501 if ( pConfig->GetExportFormatExtension( i ).equalsIgnoreAsciiCase( aExt ) )
1502 {
1503 nFormat=i;
1504 break;
1505 }
1506 }
1507 }
1508 if( nFormat >= nFormatCount )
1510
1511 FilterConfigItem aConfigItem( pFilterData );
1512 OUString aFilterName( pConfig->GetExportFilterName( nFormat ) );
1513 ErrCode nStatus = ERRCODE_NONE;
1515 Graphic aGraphic = ImpGetScaledGraphic( rGraphic, aConfigItem );
1516 eType = aGraphic.GetType();
1517
1518 if( pConfig->IsExportPixelFormat( nFormat ) )
1519 {
1520 if( eType != GraphicType::Bitmap )
1521 {
1522 Size aSizePixel;
1523 sal_uLong nBitsPerPixel,nNeededMem,nMaxMem;
1525
1526 nMaxMem = 1024;
1527 nMaxMem *= 1024; // In Bytes
1528
1529 // Calculate how big the image would normally be:
1530 aSizePixel=aVirDev->LogicToPixel(aGraphic.GetPrefSize(),aGraphic.GetPrefMapMode());
1531
1532 // Calculate how much memory the image will take up
1533 nBitsPerPixel=aVirDev->GetBitCount();
1534 nNeededMem=(static_cast<sal_uLong>(aSizePixel.Width())*static_cast<sal_uLong>(aSizePixel.Height())*nBitsPerPixel+7)/8;
1535
1536 // is the image larger than available memory?
1537 if (nMaxMem<nNeededMem)
1538 {
1539 double fFak=sqrt(static_cast<double>(nMaxMem)/static_cast<double>(nNeededMem));
1540 aSizePixel.setWidth(static_cast<sal_uLong>(static_cast<double>(aSizePixel.Width())*fFak) );
1541 aSizePixel.setHeight(static_cast<sal_uLong>(static_cast<double>(aSizePixel.Height())*fFak) );
1542 }
1543
1544 aVirDev->SetMapMode(MapMode(MapUnit::MapPixel));
1545 aVirDev->SetOutputSizePixel(aSizePixel);
1546 Graphic aGraphic2=aGraphic;
1547 aGraphic2.Draw(*aVirDev, Point(0, 0), aSizePixel); // this changes the MapMode
1548 aVirDev->SetMapMode(MapMode(MapUnit::MapPixel));
1549 aGraphic=Graphic(aVirDev->GetBitmapEx(Point(0,0),aSizePixel));
1550 }
1551 }
1552 if( rOStm.GetError() )
1553 nStatus = ERRCODE_GRFILTER_IOERROR;
1554 if( ERRCODE_NONE == nStatus )
1555 {
1556 if( aFilterName.equalsIgnoreAsciiCase( EXP_BMP ) )
1557 {
1558 if (!BmpWriter(rOStm, aGraphic, &aConfigItem))
1560 if (rOStm.GetError())
1561 nStatus = ERRCODE_GRFILTER_IOERROR;
1562 }
1563 else if (aFilterName.equalsIgnoreAsciiCase(EXP_TIFF))
1564 {
1565 if (!ExportTiffGraphicImport(rOStm, aGraphic, &aConfigItem))
1567
1568 if( rOStm.GetError() )
1569 nStatus = ERRCODE_GRFILTER_IOERROR;
1570 }
1571 else if (aFilterName.equalsIgnoreAsciiCase(EXP_GIF))
1572 {
1573 if (!ExportGifGraphic(rOStm, aGraphic, &aConfigItem))
1575
1576 if( rOStm.GetError() )
1577 nStatus = ERRCODE_GRFILTER_IOERROR;
1578 }
1579 else if( aFilterName.equalsIgnoreAsciiCase( EXP_SVMETAFILE ) )
1580 {
1581 sal_Int32 nVersion = aConfigItem.ReadInt32( "Version", 0 ) ;
1582 if ( nVersion )
1583 rOStm.SetVersion( nVersion );
1584
1585 // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
1586 GDIMetaFile aMTF(aGraphic.GetGDIMetaFile());
1587
1588 SvmWriter aWriter( rOStm );
1589 aWriter.Write( aMTF );
1590
1591 if( rOStm.GetError() )
1592 nStatus = ERRCODE_GRFILTER_IOERROR;
1593 }
1594 else if ( aFilterName.equalsIgnoreAsciiCase( EXP_WMF ) || aFilterName.equalsIgnoreAsciiCase( EXP_WMZ ) )
1595 {
1596 bool bDone(false);
1597 SvStream* rTempStm = &rOStm;
1598 if (aFilterName.equalsIgnoreAsciiCase(EXP_WMZ))
1599 {
1600 // Write to a different stream so that we can compress to rOStm later
1601 rCompressableStm.SetBufferSize( rOStm.GetBufferSize() );
1602 rTempStm = &rCompressableStm;
1603 bShouldCompress = true;
1604 }
1605 // do we have a native Vector Graphic Data RenderGraphic, whose data can be written directly?
1606 auto const & rVectorGraphicDataPtr(rGraphic.getVectorGraphicData());
1607
1608 bool bIsEMF = rGraphic.GetGfxLink().IsEMF();
1609
1610 // VectorGraphicDataType::Wmf means WMF or EMF, allow direct write in the WMF case
1611 // only.
1612 if (rVectorGraphicDataPtr
1613 && rVectorGraphicDataPtr->getType() == VectorGraphicDataType::Wmf
1614 && !rVectorGraphicDataPtr->getBinaryDataContainer().isEmpty()
1615 && !bIsEMF)
1616 {
1617 rVectorGraphicDataPtr->getBinaryDataContainer().writeToStream(*rTempStm);
1618 if (rTempStm->GetError())
1619 {
1620 nStatus = ERRCODE_GRFILTER_IOERROR;
1621 }
1622 else
1623 {
1624 bDone = true;
1625 }
1626 }
1627
1628 if (!bDone)
1629 {
1630 // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
1631 if (!ConvertGraphicToWMF(aGraphic, *rTempStm, &aConfigItem))
1633
1634 if (rTempStm->GetError())
1635 nStatus = ERRCODE_GRFILTER_IOERROR;
1636 }
1637 }
1638 else if ( aFilterName.equalsIgnoreAsciiCase( EXP_EMF ) || aFilterName.equalsIgnoreAsciiCase( EXP_EMZ ) )
1639 {
1640 bool bDone(false);
1641 SvStream* rTempStm = &rOStm;
1642 if (aFilterName.equalsIgnoreAsciiCase(EXP_EMZ))
1643 {
1644 // Write to a different stream so that we can compress to rOStm later
1645 rCompressableStm.SetBufferSize( rOStm.GetBufferSize() );
1646 rTempStm = &rCompressableStm;
1647 bShouldCompress = true;
1648 }
1649 // do we have a native Vector Graphic Data RenderGraphic, whose data can be written directly?
1650 auto const & rVectorGraphicDataPtr(rGraphic.getVectorGraphicData());
1651
1652 if (rVectorGraphicDataPtr
1653 && rVectorGraphicDataPtr->getType() == VectorGraphicDataType::Emf
1654 && !rVectorGraphicDataPtr->getBinaryDataContainer().isEmpty())
1655 {
1656 rVectorGraphicDataPtr->getBinaryDataContainer().writeToStream(*rTempStm);
1657 if (rTempStm->GetError())
1658 {
1659 nStatus = ERRCODE_GRFILTER_IOERROR;
1660 }
1661 else
1662 {
1663 bDone = true;
1664 }
1665 }
1666
1667 if (!bDone)
1668 {
1669 // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
1670 if (!ConvertGDIMetaFileToEMF(aGraphic.GetGDIMetaFile(), *rTempStm))
1672
1673 if (rTempStm->GetError())
1674 nStatus = ERRCODE_GRFILTER_IOERROR;
1675 }
1676 }
1677 else if( aFilterName.equalsIgnoreAsciiCase( EXP_JPEG ) )
1678 {
1679 bool bExportedGrayJPEG = false;
1680 if( !ExportJPEG( rOStm, aGraphic, pFilterData, &bExportedGrayJPEG ) )
1682
1683 if( rOStm.GetError() )
1684 nStatus = ERRCODE_GRFILTER_IOERROR;
1685 }
1686 else if (aFilterName.equalsIgnoreAsciiCase(EXP_EPS))
1687 {
1688 if (!ExportEpsGraphic(rOStm, aGraphic, &aConfigItem))
1690
1691 if (rOStm.GetError())
1692 nStatus = ERRCODE_GRFILTER_IOERROR;
1693 }
1694 else if ( aFilterName.equalsIgnoreAsciiCase( EXP_PNG ) )
1695 {
1696 auto aBitmapEx = aGraphic.GetBitmapEx();
1697 vcl::PngImageWriter aPNGWriter( rOStm );
1698 if ( pFilterData )
1699 aPNGWriter.setParameters( *pFilterData );
1700 aPNGWriter.write( aBitmapEx );
1701
1702 if( rOStm.GetError() )
1703 nStatus = ERRCODE_GRFILTER_IOERROR;
1704 }
1705 else if( aFilterName.equalsIgnoreAsciiCase( EXP_SVG ) || aFilterName.equalsIgnoreAsciiCase( EXP_SVGZ ) )
1706 {
1707 bool bDone(false);
1708 SvStream* rTempStm = &rOStm;
1709 if (aFilterName.equalsIgnoreAsciiCase(EXP_SVGZ))
1710 {
1711 // Write to a different stream so that we can compress to rOStm later
1712 rCompressableStm.SetBufferSize(rOStm.GetBufferSize());
1713 rTempStm = &rCompressableStm;
1714 bShouldCompress = true;
1715 }
1716
1717 // do we have a native Vector Graphic Data RenderGraphic, whose data can be written directly?
1718 auto const & rVectorGraphicDataPtr(rGraphic.getVectorGraphicData());
1719
1720 if (rVectorGraphicDataPtr
1721 && rVectorGraphicDataPtr->getType() == VectorGraphicDataType::Svg
1722 && !rVectorGraphicDataPtr->getBinaryDataContainer().isEmpty())
1723 {
1724 rVectorGraphicDataPtr->getBinaryDataContainer().writeToStream(*rTempStm);
1725 if( rTempStm->GetError() )
1726 {
1727 nStatus = ERRCODE_GRFILTER_IOERROR;
1728 }
1729 else
1730 {
1731 bDone = true;
1732 }
1733 }
1734
1735 if( !bDone )
1736 {
1737 // do the normal GDIMetaFile export instead
1738 try
1739 {
1740 css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1741
1742 css::uno::Reference< css::xml::sax::XDocumentHandler > xSaxWriter(
1743 css::xml::sax::Writer::create( xContext ), css::uno::UNO_QUERY_THROW);
1744 css::uno::Sequence< css::uno::Any > aArguments{ css::uno::Any(
1745 aConfigItem.GetFilterData()) };
1746 css::uno::Reference< css::svg::XSVGWriter > xSVGWriter(
1747 xContext->getServiceManager()->createInstanceWithArgumentsAndContext( "com.sun.star.svg.SVGWriter", aArguments, xContext),
1748 css::uno::UNO_QUERY );
1749 if( xSaxWriter.is() && xSVGWriter.is() )
1750 {
1751 css::uno::Reference< css::io::XActiveDataSource > xActiveDataSource(
1752 xSaxWriter, css::uno::UNO_QUERY );
1753
1754 if( xActiveDataSource.is() )
1755 {
1756 const css::uno::Reference< css::uno::XInterface > xStmIf(
1757 getXWeak( new ImpFilterOutputStream( *rTempStm ) ) );
1758
1759 SvMemoryStream aMemStm( 65535, 65535 );
1760
1761 // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
1762 SvmWriter aWriter( aMemStm );
1763 aWriter.Write( aGraphic.GetGDIMetaFile() );
1764
1765 xActiveDataSource->setOutputStream( css::uno::Reference< css::io::XOutputStream >(
1766 xStmIf, css::uno::UNO_QUERY ) );
1767 css::uno::Sequence< sal_Int8 > aMtfSeq( static_cast<sal_Int8 const *>(aMemStm.GetData()), aMemStm.Tell() );
1768 xSVGWriter->write( xSaxWriter, aMtfSeq );
1769 }
1770 }
1771 }
1772 catch(const css::uno::Exception&)
1773 {
1774 nStatus = ERRCODE_GRFILTER_IOERROR;
1775 }
1776 }
1777 }
1778 else if (aFilterName.equalsIgnoreAsciiCase(EXP_WEBP))
1779 {
1780 if (!ExportWebpGraphic(rOStm, aGraphic, &aConfigItem))
1782
1783 if( rOStm.GetError() )
1784 nStatus = ERRCODE_GRFILTER_IOERROR;
1785 }
1786 else
1788 }
1789 if( nStatus != ERRCODE_NONE )
1790 {
1791 ImplSetError( nStatus, &rOStm );
1792 }
1793 else if ( bShouldCompress )
1794 {
1795 sal_uInt32 nUncompressedCRC32
1796 = rtl_crc32( 0, rCompressableStm.GetData(), rCompressableStm.GetSize() );
1797 ZCodec aCodec;
1798 rCompressableStm.Seek( 0 );
1799 aCodec.BeginCompression( ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/true );
1800 // the inner modify time/filename doesn't really matter in this context because
1801 // compressed graphic formats are meant to be opened as is - not to be extracted
1802 aCodec.SetCompressionMetadata( "inner", 0, nUncompressedCRC32 );
1803 aCodec.Compress( rCompressableStm, rOStm );
1804 tools::Long nCompressedLength = aCodec.EndCompression();
1805 if ( rOStm.GetError() || nCompressedLength <= 0 )
1806 nStatus = ERRCODE_GRFILTER_IOERROR;
1807 }
1808 return nStatus;
1809}
1810
1811
1813{
1815}
1816
1818{
1819 Link<ConvertData&,bool> aLink( LINK( const_cast<GraphicFilter*>(this), GraphicFilter, FilterCallback ) );
1820 return aLink;
1821}
1822
1823IMPL_LINK( GraphicFilter, FilterCallback, ConvertData&, rData, bool )
1824{
1825 bool bRet = false;
1826
1827 sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
1828 OUString aShortName;
1829 css::uno::Sequence< css::beans::PropertyValue > aFilterData;
1830 switch( rData.mnFormat )
1831 {
1832 case ConvertDataFormat::BMP: aShortName = BMP_SHORTNAME; break;
1833 case ConvertDataFormat::GIF: aShortName = GIF_SHORTNAME; break;
1834 case ConvertDataFormat::JPG: aShortName = JPG_SHORTNAME; break;
1835 case ConvertDataFormat::MET: aShortName = MET_SHORTNAME; break;
1836 case ConvertDataFormat::PCT: aShortName = PCT_SHORTNAME; break;
1837 case ConvertDataFormat::PNG: aShortName = PNG_SHORTNAME; break;
1838 case ConvertDataFormat::SVM: aShortName = SVM_SHORTNAME; break;
1839 case ConvertDataFormat::TIF: aShortName = TIF_SHORTNAME; break;
1840 case ConvertDataFormat::WMF: aShortName = WMF_SHORTNAME; break;
1841 case ConvertDataFormat::EMF: aShortName = EMF_SHORTNAME; break;
1842 case ConvertDataFormat::SVG: aShortName = SVG_SHORTNAME; break;
1843 case ConvertDataFormat::WEBP: aShortName = WEBP_SHORTNAME; break;
1844
1845 default:
1846 break;
1847 }
1848 if( GraphicType::NONE == rData.maGraphic.GetType() || rData.maGraphic.GetReaderContext() ) // Import
1849 {
1850 // Import
1851 nFormat = GetImportFormatNumberForShortName( aShortName );
1852 bRet = ImportGraphic( rData.maGraphic, u"", rData.mrStm, nFormat ) == ERRCODE_NONE;
1853 }
1854 else if( !aShortName.isEmpty() )
1855 {
1856 // Export
1857#if defined(IOS) || defined(ANDROID)
1858 if (aShortName == PNG_SHORTNAME)
1859 {
1860 aFilterData.realloc(aFilterData.getLength() + 1);
1861 auto pFilterData = aFilterData.getArray();
1862 pFilterData[aFilterData.getLength() - 1].Name = "Compression";
1863 // We "know" that this gets passed to zlib's deflateInit2_(). 1 means best speed.
1864 pFilterData[aFilterData.getLength() - 1].Value <<= static_cast<sal_Int32>(1);
1865 }
1866#endif
1867 nFormat = GetExportFormatNumberForShortName( aShortName );
1868 bRet = ExportGraphic( rData.maGraphic, u"", rData.mrStm, nFormat, &aFilterData ) == ERRCODE_NONE;
1869 }
1870
1871 return bRet;
1872}
1873
1874namespace
1875{
1876 class StandardGraphicFilter
1877 {
1878 public:
1879 StandardGraphicFilter()
1880 {
1881 m_aFilter.GetImportFormatCount();
1882 }
1883 GraphicFilter m_aFilter;
1884 };
1885}
1886
1888{
1889 static StandardGraphicFilter gStandardFilter;
1890 return gStandardFilter.m_aFilter;
1891}
1892
1893ErrCode GraphicFilter::LoadGraphic( const OUString &rPath, const OUString &rFilterName,
1894 Graphic& rGraphic, GraphicFilter* pFilter,
1895 sal_uInt16* pDeterminedFormat )
1896{
1897 if ( !pFilter )
1898 pFilter = &GetGraphicFilter();
1899
1900 const sal_uInt16 nFilter = !rFilterName.isEmpty() && pFilter->GetImportFormatCount()
1901 ? pFilter->GetImportFormatNumber( rFilterName )
1903
1904 INetURLObject aURL( rPath );
1905 if ( aURL.HasError() )
1906 {
1907 aURL.SetSmartProtocol( INetProtocol::File );
1908 aURL.SetSmartURL( rPath );
1909 }
1910
1911 std::unique_ptr<SvStream> pStream;
1912 if ( INetProtocol::File != aURL.GetProtocol() )
1913 pStream = ::utl::UcbStreamHelper::CreateStream( rPath, StreamMode::READ );
1914
1915 ErrCode nRes = ERRCODE_NONE;
1916 if ( !pStream )
1917 nRes = pFilter->ImportGraphic( rGraphic, aURL, nFilter, pDeterminedFormat );
1918 else
1919 nRes = pFilter->ImportGraphic( rGraphic, rPath, *pStream, nFilter, pDeterminedFormat );
1920
1921#ifdef DBG_UTIL
1922 OUString aReturnString;
1923
1924 if (nRes == ERRCODE_GRFILTER_OPENERROR)
1925 aReturnString="open error";
1926 else if (nRes == ERRCODE_GRFILTER_IOERROR)
1927 aReturnString="IO error";
1928 else if (nRes == ERRCODE_GRFILTER_FORMATERROR)
1929 aReturnString="format error";
1930 else if (nRes == ERRCODE_GRFILTER_VERSIONERROR)
1931 aReturnString="version error";
1932 else if (nRes == ERRCODE_GRFILTER_FILTERERROR)
1933 aReturnString="filter error";
1934 else if (nRes == ERRCODE_GRFILTER_TOOBIG)
1935 aReturnString="graphic is too big";
1936
1937 SAL_INFO_IF( nRes, "vcl.filter", "Problem importing graphic " << rPath << ". Reason: " << aReturnString );
1938#endif
1939
1940 return nRes;
1941}
1942
1944{
1945 css::uno::Sequence< css::beans::PropertyValue > aFilterData{ comphelper::makePropertyValue(
1946 "Compression", sal_uInt32(9)) };
1947
1948 sal_uInt16 nFilterFormat = GetExportFormatNumberForShortName(u"PNG");
1949 return ExportGraphic(rGraphic, u"", rOutputStream, nFilterFormat, &aFilterData);
1950}
1951
1952/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool BmpReader(SvStream &rStream, Graphic &rGraphic)
Definition: BmpReader.cxx:23
bool BmpWriter(SvStream &rStream, const Graphic &rGraphic, FilterConfigItem *pFilterConfigItem)
Definition: BmpWriter.cxx:23
Reference< XInputStream > xStream
oslInterlockedCount m_nStatus
static OutputDevice * GetDefaultDevice()
Get the default "device" (in this case the default window).
Definition: svapp.cxx:1060
Container for the binary data, whose responsibility is to manage the make it as simple as possible to...
std::shared_ptr< SvStream > getAsStream()
const AlphaMask & GetAlphaMask() const
Definition: bitmapex.hxx:70
bool Convert(BmpConversion eConversion)
Convert bitmap format.
Definition: BitmapEx.cxx:369
bool IsAlpha() const
Definition: BitmapEx.cxx:193
bool IsEmpty() const
Definition: BitmapEx.cxx:177
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:203
const Size & GetSizePixel() const
Definition: bitmapex.hxx:72
Cache to keep list of graphic filters + the filters themselves.
bool IsExportPixelFormat(sal_uInt16 nFormat)
sal_uInt16 GetExportFormatNumberForShortName(std::u16string_view rShortName)
OUString GetImportFormatName(sal_uInt16 nFormat)
sal_uInt16 GetImportFormatNumber(std::u16string_view rFormatName)
sal_uInt16 GetExportFormatNumber(std::u16string_view rFormatName)
sal_uInt16 GetImportFormatNumberForShortName(std::u16string_view rShortName)
OUString GetExportWildcard(sal_uInt16 nFormat, sal_Int32 nEntry)
OUString GetImportFormatShortName(sal_uInt16 nFormat)
sal_uInt16 GetImportFormatNumberForExtension(std::u16string_view rExt)
get the index of the filter that matches this extension
OUString GetImportWildcard(sal_uInt16 nFormat, sal_Int32 nEntry)
OUString GetImportFilterTypeName(sal_uInt16 nFormat)
OUString GetExportFilterName(sal_uInt16 nFormat)
OUString GetExportFormatShortName(sal_uInt16 nFormat)
OUString GetExportFormatName(sal_uInt16 nFormat)
OUString GetExportFormatExtension(sal_uInt16 nFormat, sal_Int32 nEntry=0)
OUString GetImportFilterName(sal_uInt16 nFormat)
sal_uInt16 GetExportFormatNumberForTypeName(std::u16string_view rType)
sal_uInt16 GetImportFormatCount() const
sal_uInt16 GetExportFormatNumberForMediaType(std::u16string_view rMediaType)
sal_uInt16 GetImportFormatNumberForTypeName(std::u16string_view rType)
OUString GetImportFormatExtension(sal_uInt16 nFormat, sal_Int32 nEntry=0)
OUString GetImportFilterType(sal_uInt16 nFormat)
sal_uInt16 GetExportFormatCount() const
OUString GetExportFormatMediaType(sal_uInt16 nFormat)
OUString GetImportFormatMediaType(sal_uInt16 nFormat)
OUString GetExportInternalFilterName(sal_uInt16 nFormat)
void WriteInt32(const OUString &rKey, sal_Int32 nValue)
sal_Int32 ReadInt32(const OUString &rKey, sal_Int32 nDefault)
const css::uno::Sequence< css::beans::PropertyValue > & GetFilterData() const
void Scale(double fScaleX, double fScaleY)
Definition: gdimtf.cxx:726
const Size & GetPrefSize() const
Definition: gdimtf.hxx:172
const MapMode & GetPrefMapMode() const
Definition: gdimtf.hxx:175
Class to import and export graphic formats.
OUString GetImportFormatShortName(sal_uInt16 nFormat)
static ErrCode readEPS(SvStream &rStream, Graphic &rGraphic)
sal_uInt16 GetExportFormatNumberForShortName(std::u16string_view rShortName)
static ErrCode readPSD(SvStream &rStream, Graphic &rGraphic)
static ErrCode readWithTypeSerializer(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType, std::u16string_view aFilterName)
ErrCode ImplSetError(ErrCode nError, const SvStream *pStm=nullptr)
sal_uInt16 GetExportFormatNumberForTypeName(std::u16string_view rType)
OUString aFilterPath
Graphic ImportUnloadedGraphic(SvStream &rIStream, sal_uInt64 sizeLimit=0, const Size *pSizeHint=nullptr)
void MakeGraphicsAvailableThreaded(std::vector< Graphic * > &rGraphics)
Tries to ensure all Graphic objects are available (Graphic::isAvailable()).
static ErrCode readPCD(SvStream &rStream, Graphic &rGraphic)
sal_uInt16 GetImportFormatNumberForTypeName(std::u16string_view rType)
static ErrCode readWEBP(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
OUString GetExportWildcard(sal_uInt16 nFormat)
static GraphicFilter & GetGraphicFilter()
Link< ConvertData &, bool > GetFilterCallback() const
static ErrCode readDXF(SvStream &rStream, Graphic &rGraphic)
bool IsExportPixelFormat(sal_uInt16 nFormat)
static ErrCode readBMP(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
static ErrCode readPDF(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
static ErrCode readXPM(SvStream &rStream, Graphic &rGraphic)
sal_uInt16 GetExportFormatNumber(std::u16string_view rFormatName)
static ErrCode readJPEG(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType, GraphicFilterImportFlags nImportFlags)
static ErrCode readMET(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
static ErrCode readXBM(SvStream &rStream, Graphic &rGraphic)
sal_uInt16 GetExportFormatNumberForMediaType(std::u16string_view rShortName)
sal_uInt16 GetImportFormatNumber(std::u16string_view rFormatName)
ErrCode CanImportGraphic(const INetURLObject &rPath, sal_uInt16 nFormat, sal_uInt16 *pDeterminedFormat)
OUString GetExportFormatName(sal_uInt16 nFormat)
OUString GetImportFormatName(sal_uInt16 nFormat)
static ErrCode readEMF(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
ErrCode ExportGraphic(const Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData=nullptr)
static ErrCode readPICT(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
static ErrCode readWMF_EMF(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType, VectorGraphicDataType eType)
sal_uInt16 GetImportFormatCount() const
sal_uInt16 GetExportFormatCount() const
static ErrCode readWMF(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
OUString GetExportFormatShortName(sal_uInt16 nFormat)
static ErrCode readTGA(SvStream &rStream, Graphic &rGraphic)
sal_uInt16 GetImportFormatNumberForShortName(std::u16string_view rShortName)
static ErrCode readPBM(SvStream &rStream, Graphic &rGraphic)
ErrCode ImpTestOrFindFormat(std::u16string_view rPath, SvStream &rStream, sal_uInt16 &rFormat)
static ErrCode readRAS(SvStream &rStream, Graphic &rGraphic)
GraphicFilter(bool bUseConfig=true)
OUString GetImportWildcard(sal_uInt16 nFormat, sal_Int32 nEntry)
ErrCode ImportGraphic(Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat=GRFILTER_FORMAT_DONTKNOW, sal_uInt16 *pDeterminedFormat=nullptr, GraphicFilterImportFlags nImportFlags=GraphicFilterImportFlags::NONE)
static ErrCode readPCX(SvStream &rStream, Graphic &rGraphic)
FilterConfigCache * pConfig
OUString GetExportFormatMediaType(sal_uInt16 nFormat)
static ErrCode readGIF(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
static ErrCode LoadGraphic(const OUString &rPath, const OUString &rFilter, Graphic &rGraphic, GraphicFilter *pFilter=nullptr, sal_uInt16 *pDeterminedFormat=nullptr)
OUString GetExportInternalFilterName(sal_uInt16 nFormat)
std::optional< ErrCode > mxErrorEx
Information about errors during the GraphicFilter operation.
OUString GetImportFormatTypeName(sal_uInt16 nFormat)
ErrCode compressAsPNG(const Graphic &rGraphic, SvStream &rOutputStream)
static ErrCode readSVG(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType, BinaryDataContainer &rpGraphicContent)
static ErrCode readTIFF(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
void ImportGraphics(std::vector< std::shared_ptr< Graphic > > &rGraphics, std::vector< std::unique_ptr< SvStream > > vStreams)
Imports multiple graphics.
static ErrCode readPNG(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType, BinaryDataContainer &rpGraphicContent)
Size GetPrefSize() const
Definition: graph.cxx:364
void SetPrefMapMode(const MapMode &rPrefMapMode)
Definition: graph.cxx:380
void SetDummyContext(bool value)
Definition: graph.cxx:489
const GDIMetaFile & GetGDIMetaFile() const
Definition: graph.cxx:340
bool IsDummyContext() const
Definition: graph.cxx:494
GraphicType GetType() const
Definition: graph.cxx:294
void SetGfxLink(const std::shared_ptr< GfxLink > &rGfxLink)
Definition: graph.cxx:499
GfxLink GetGfxLink() const
Definition: graph.cxx:510
const BitmapEx & GetBitmapExRef() const
Gives direct access to the contained BitmapEx.
Definition: graph.cxx:345
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
Definition: graph.cxx:330
MapMode GetPrefMapMode() const
Definition: graph.cxx:375
void Clear()
Definition: graph.cxx:288
void Draw(OutputDevice &rOutDev, const Point &rDestPt) const
Definition: graph.cxx:429
bool IsGfxLink() const
Definition: graph.cxx:515
std::shared_ptr< GraphicReader > & GetReaderContext()
Definition: graph.cxx:479
void SetPrefSize(const Size &rPrefSize)
Definition: graph.cxx:369
const std::shared_ptr< VectorGraphicData > & getVectorGraphicData() const
Definition: graph.cxx:525
void SetDefaultType()
Definition: graph.cxx:299
SAL_DLLPRIVATE ImpGraphic * ImplGetImpGraphic() const
Definition: graph.hxx:89
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
INetProtocol GetProtocol() const
void setPrepared(bool bAnimated, const Size *pSizeHint)
Definition: impgraph.cxx:381
MapUnit GetMapUnit() const
Definition: mapmod.cxx:146
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1123
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1593
constexpr tools::Long getHeight() const
constexpr tools::Long Height() const
constexpr tools::Long getWidth() const
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
const void * GetData()
sal_uInt64 GetSize()
virtual void ResetError()
sal_uInt64 Tell() const
void SetBufferSize(sal_uInt16 m_nBufSize)
sal_uInt16 GetBufferSize() const
std::size_t WriteBytes(const void *pData, std::size_t nSize)
void SetVersion(sal_Int32 n)
sal_uInt64 Seek(sal_uInt64 nPos)
std::size_t ReadBytes(void *pData, std::size_t nSize)
ErrCode GetError() const
void FlushBuffer()
sal_uInt64 remainingSize()
SvStream & Write(const GDIMetaFile &rMetaFile)
Definition: SvmWriter.cxx:38
void readGraphic(Graphic &rGraphic)
tools::Long Decompress(SvStream &rIStm, SvStream &rOStm)
void SetCompressionMetadata(const OString &sFilename, sal_uInt32 nLastModifiedTime, sal_uInt32 nInBufCRC32)
static bool IsZCompressed(SvStream &rIStm)
tools::Long EndCompression()
void BeginCompression(int nCompressLevel=ZCODEC_DEFAULT_COMPRESSION, bool gzLib=false)
void Compress(SvStream &rIStm, SvStream &rOStm)
static ThreadPool & getSharedOptimalPool()
void waitUntilDone(const std::shared_ptr< ThreadTaskTag > &, bool bJoin=true)
static std::shared_ptr< ThreadTaskTag > createThreadTaskTag()
void pushTask(std::unique_ptr< ThreadTask > pTask)
virtual void doWork()=0
static bool IsFuzzing()
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
bool read(BitmapEx &rBitmap)
static BinaryDataContainer getMicrosoftGifChunk(SvStream &rStream)
void setParameters(css::uno::Sequence< css::beans::PropertyValue > const &rParameters)
bool write(const BitmapEx &rBitmap)
This template handles BitmapAccess the RAII way.
URL aURL
float u
bool ExportGifGraphic(SvStream &rStream, const Graphic &rGraphic, FilterConfigItem *pConfigItem)
Definition: egif.cxx:543
#define ERRCODE_IO_PENDING
#define ERRCODE_NONE
bool ExportTiffGraphicImport(SvStream &rStream, const Graphic &rGraphic, const FilterConfigItem *pFilterConfigItem)
Definition: etiff.cxx:580
sal_Int16 nVersion
bool ExportEpsGraphic(SvStream &rStream, const Graphic &rGraphic, FilterConfigItem *pFilterConfigItem)
DocumentType eType
VCL_DLLPUBLIC bool ImportGIF(SvStream &rStm, Graphic &rGraphic)
Definition: gifread.cxx:969
bool IsGIFAnimated(SvStream &rStm, Size &rLogicSize)
Definition: gifread.cxx:956
GraphicType
Definition: graph.hxx:35
static OUString ImpGetExtension(std::u16string_view rPath)
static Graphic ImpGetScaledGraphic(const Graphic &rGraphic, FilterConfigItem &rConfigItem)
static bool supportNativeWebp()
static std::mutex & getListMutex()
static std::vector< GraphicFilter * > gaFilterHdlList
IMPL_LINK(GraphicFilter, FilterCallback, ConvertData &, rData, bool)
constexpr OUStringLiteral SVG_SHORTNAME
#define GRFILTER_FORMAT_DONTKNOW
#define IMP_SVG
constexpr OUStringLiteral MET_SHORTNAME
#define IMP_BMP
#define EXP_SVMETAFILE
#define EXP_BMP
#define IMP_TIFF
#define IMP_PICT
#define EXP_SVGZ
#define IMP_PNG
constexpr OUStringLiteral PCT_SHORTNAME
#define ERRCODE_GRFILTER_OPENERROR
#define IMP_PCD
#define IMP_JPEG
constexpr OUStringLiteral GIF_SHORTNAME
#define IMP_XBM
#define EXP_EMZ
#define IMP_GIF
#define EXP_WMZ
#define IMP_WEBP
constexpr OUStringLiteral WEBP_SHORTNAME
#define EXP_SVG
constexpr OUStringLiteral TIF_SHORTNAME
#define IMP_PSD
constexpr OUStringLiteral WMF_SHORTNAME
#define IMP_WMF
#define IMP_XPM
#define EXP_GIF
constexpr OUStringLiteral BMP_SHORTNAME
#define IMP_SVMETAFILE
#define IMP_DXF
#define ERRCODE_GRFILTER_TOOBIG
#define IMP_EMF
#define IMP_MET
#define IMP_TGA
#define IMP_RAS
#define IMP_WMZ
#define ERRCODE_GRFILTER_FORMATERROR
#define EXP_TIFF
#define IMP_EMZ
#define ERRCODE_GRFILTER_FILTERERROR
#define IMP_SVGZ
#define ERRCODE_GRFILTER_IOERROR
#define IMP_PCX
GraphicFilterImportFlags
@ UseExistingBitmap
Read pixel data into an existing bitmap.
@ OnlyCreateBitmap
Only create a bitmap, do not read pixel data.
#define EXP_EMF
#define EXP_PNG
constexpr OUStringLiteral JPG_SHORTNAME
#define ERRCODE_GRFILTER_VERSIONERROR
#define IMP_PBM
#define IMP_PDF
constexpr OUStringLiteral EMF_SHORTNAME
#define IMP_EPS
constexpr OUStringLiteral PNG_SHORTNAME
constexpr OUStringLiteral SVM_SHORTNAME
#define EXP_EPS
#define EXP_JPEG
#define EXP_WEBP
#define EXP_WMF
#define IMP_MOV
GtkMediaStream * m_pStream
bool ImportDxfGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: idxf.cxx:28
bool ImportEpsGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: ieps.cxx:575
Sequence< PropertyValue > aArguments
bool ImportMetGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: ios2met.cxx:2860
bool ImportPbmGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: ipbm.cxx:534
bool ImportPcdGraphic(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *pConfigItem)
Definition: ipcd.cxx:346
bool ImportPcxGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: ipcx.cxx:402
bool ImportPictGraphic(SvStream &rIStm, Graphic &rGraphic)
Definition: ipict.cxx:2024
bool ImportPsdGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: ipsd.cxx:769
bool ImportRasGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: iras.cxx:398
bool ImportTgaGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: itga.cxx:783
bool ImportTiffGraphicImport(SvStream &rTIFF, Graphic &rGraphic)
Definition: itiff.cxx:110
bool ExportJPEG(SvStream &rOutputStream, const Graphic &rGraphic, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData, bool *pExportWasGrey)
Definition: jpeg.cxx:53
VCL_DLLPUBLIC bool ImportJPEG(SvStream &rInputStream, Graphic &rGraphic, GraphicFilterImportFlags nImportFlags, BitmapScopedWriteAccess *ppAccess)
Definition: jpeg.cxx:26
#define SAL_INFO_IF(condition, area, stream)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_INFO(area, stream)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
int i
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
long Long
UNOTOOLS_DLLPUBLIC bool IsDocument(OUString const &url)
UNOTOOLS_DLLPUBLIC bool Kill(OUString const &url)
bool ImportPDF(SvStream &rStream, Graphic &rGraphic)
Imports a PDF stream into rGraphic.
Definition: pdfread.cxx:143
bool ImportPNG(SvStream &rInputStream, Graphic &rGraphic, GraphicFilterImportFlags nImportFlags, BitmapScopedWriteAccess *pAccess, AlphaScopedWriteAccess *pAlphaAccess)
bool peekGraphicFormat(SvStream &rStream, OUString &rFormatExtension, bool bTest)
HashMap_OWString_Interface aMap
bool ImportWebpGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: reader.cxx:298
sal_uIntPtr sal_uLong
#define STREAM_SEEK_TO_END
#define STREAM_SEEK_TO_BEGIN
const Reference< XComponentContext > & m_rContext
unsigned char sal_uInt8
signed char sal_Int8
VectorGraphicDataType
bool ConvertGraphicToWMF(const Graphic &rGraphic, SvStream &rTargetStream, FilterConfigItem const *pConfigItem, bool bPlaceable)
Definition: wmf.cxx:85
bool ConvertGDIMetaFileToEMF(const GDIMetaFile &rMTF, SvStream &rTargetStream)
Definition: wmf.cxx:111
bool ExportWebpGraphic(SvStream &rStream, const Graphic &rGraphic, FilterConfigItem *pFilterConfigItem)
Definition: writer.cxx:193
VCL_DLLPUBLIC bool ImportXBM(SvStream &rStm, Graphic &rGraphic)
Definition: xbmread.cxx:371
VCL_DLLPUBLIC bool ImportXPM(SvStream &rStm, Graphic &rGraphic)
Definition: xpmread.cxx:670
#define ZCODEC_DEFAULT_COMPRESSION