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