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