1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <tools/stream.hxx>
22 #include <tools/fract.hxx>
23 #include <tools/urlobj.hxx>
24 #include <tools/zcodec.hxx>
25 #include <vcl/outdev.hxx>
26 #include <vcl/graphicfilter.hxx>
27 #include <unotools/ucbstreamhelper.hxx>
28 #include <graphic/GraphicFormatDetector.hxx>
29 #include "graphicfilter_internal.hxx"
33 enum class MetafileType
: sal_uInt16
38 enum class MetafileVersion
: sal_uInt16
45 GraphicDescriptor::GraphicDescriptor( const INetURLObject
& rPath
) :
46 pFileStm( ::utl::UcbStreamHelper::CreateStream( rPath
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), StreamMode::READ
).release() ),
47 aPathExt( rPath
.GetFileExtension().toAsciiLowerCase() ),
53 GraphicDescriptor::GraphicDescriptor( SvStream
& rInStream
, const OUString
* pPath
) :
54 pFileStm ( &rInStream
),
61 INetURLObject
aURL( *pPath
);
62 aPathExt
= aURL
.GetFileExtension().toAsciiLowerCase();
66 GraphicDescriptor::~GraphicDescriptor()
72 bool GraphicDescriptor::Detect( bool bExtendedInfo
)
75 if ( pFileStm
&& !pFileStm
->GetError() )
77 SvStream
& rStm
= *pFileStm
;
78 SvStreamEndian nOldFormat
= rStm
.GetEndian();
80 if ( ImpDetectGIF( rStm
, bExtendedInfo
) ) bRet
= true;
81 else if ( ImpDetectJPG( rStm
, bExtendedInfo
) ) bRet
= true;
82 else if ( ImpDetectBMP( rStm
, bExtendedInfo
) ) bRet
= true;
83 else if ( ImpDetectPNG( rStm
, bExtendedInfo
) ) bRet
= true;
84 else if ( ImpDetectTIF( rStm
, bExtendedInfo
) ) bRet
= true;
85 else if ( ImpDetectPCX( rStm
) ) bRet
= true;
86 else if ( ImpDetectDXF( rStm
, bExtendedInfo
) ) bRet
= true;
87 else if ( ImpDetectMET( rStm
, bExtendedInfo
) ) bRet
= true;
88 else if ( ImpDetectSVM( rStm
, bExtendedInfo
) ) bRet
= true;
89 else if ( ImpDetectWMF( rStm
, bExtendedInfo
) ) bRet
= true;
90 else if ( ImpDetectEMF( rStm
, bExtendedInfo
) ) bRet
= true;
91 else if ( ImpDetectSVG( rStm
, bExtendedInfo
) ) bRet
= true;
92 else if ( ImpDetectPCT( rStm
, bExtendedInfo
) ) bRet
= true;
93 else if ( ImpDetectXBM( rStm
, bExtendedInfo
) ) bRet
= true;
94 else if ( ImpDetectXPM( rStm
, bExtendedInfo
) ) bRet
= true;
95 else if ( ImpDetectPBM( rStm
, bExtendedInfo
) ) bRet
= true;
96 else if ( ImpDetectPGM( rStm
, bExtendedInfo
) ) bRet
= true;
97 else if ( ImpDetectPPM( rStm
, bExtendedInfo
) ) bRet
= true;
98 else if ( ImpDetectRAS( rStm
, bExtendedInfo
) ) bRet
= true;
99 else if ( ImpDetectTGA( rStm
, bExtendedInfo
) ) bRet
= true;
100 else if ( ImpDetectPSD( rStm
, bExtendedInfo
) ) bRet
= true;
101 else if ( ImpDetectEPS( rStm
, bExtendedInfo
) ) bRet
= true;
102 else if ( ImpDetectPCD( rStm
, bExtendedInfo
) ) bRet
= true;
103 else if ( ImpDetectWEBP( rStm
, bExtendedInfo
) ) bRet
= true;
105 rStm
.SetEndian( nOldFormat
);
110 void GraphicDescriptor::ImpConstruct()
112 aMetadata
.mnFormat
= GraphicFileFormat::NOT
;
113 aMetadata
.mnBitsPerPixel
= 0;
114 aMetadata
.mnPlanes
= 0;
115 aMetadata
.mnNumberOfImageComponents
= 0;
116 aMetadata
.mbIsTransparent
= false;
117 aMetadata
.mbIsAlpha
= false;
120 bool GraphicDescriptor::ImpDetectBMP( SvStream
& rStm
, bool bExtendedInfo
)
122 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
123 bool bRet
= aDetector
.detect() && aDetector
.checkBMP();
125 aMetadata
= aDetector
.getMetadata();
129 bool GraphicDescriptor::ImpDetectGIF( SvStream
& rStm
, bool bExtendedInfo
)
131 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
132 bool bRet
= aDetector
.detect() && aDetector
.checkGIF();
134 aMetadata
= aDetector
.getMetadata();
138 // returns the next jpeg marker, a return value of 0 represents an error
139 static sal_uInt8
ImpDetectJPG_GetNextMarker( SvStream
& rStm
)
146 rStm
.ReadUChar( nByte
);
147 if (!rStm
.good()) // as 0 is not allowed as marker,
148 return 0; // we can use it as errorcode
150 while ( nByte
!= 0xff );
153 rStm
.ReadUChar( nByte
);
157 while( nByte
== 0xff );
159 while( nByte
== 0 ); // 0xff00 represents 0xff and not a marker,
160 // the marker detection has to be restarted.
164 bool GraphicDescriptor::ImpDetectJPG( SvStream
& rStm
, bool bExtendedInfo
)
166 sal_uInt32 nTemp32
= 0;
169 sal_Int32 nStmPos
= rStm
.Tell();
171 rStm
.SetEndian( SvStreamEndian::BIG
);
172 rStm
.ReadUInt32( nTemp32
);
174 // compare upper 24 bits
175 if( 0xffd8ff00 == ( nTemp32
& 0xffffff00 ) )
177 aMetadata
.mnFormat
= GraphicFileFormat::JPG
;
184 ErrCode
nError( rStm
.GetError() );
186 bool bScanFailure
= false;
187 bool bScanFinished
= false;
190 while (!bScanFailure
&& !bScanFinished
&& rStm
.good())
192 sal_uInt8 nMarker
= ImpDetectJPG_GetNextMarker( rStm
);
195 // fixed size marker, not having a two byte length parameter
207 case 0xd8 : // SOI (has already been checked, there should not be a second one)
208 case 0x00 : // marker is invalid, we should stop now
213 bScanFinished
= true;
216 // per default we assume marker segments containing a length parameter
219 sal_uInt16 nLength
= 0;
220 rStm
.ReadUInt16( nLength
);
226 sal_uInt32 nNextMarkerPos
= rStm
.Tell() + nLength
- 2;
229 case 0xe0 : // APP0 Marker
233 sal_Int32 nIdentifier
= 0;
234 rStm
.ReadInt32( nIdentifier
);
235 if ( nIdentifier
== 0x4a464946 ) // JFIF Identifier
237 sal_uInt8 nStringTerminator
= 0;
238 sal_uInt8 nMajorRevision
= 0;
239 sal_uInt8 nMinorRevision
= 0;
240 sal_uInt8 nUnits
= 0;
241 sal_uInt16 nHorizontalResolution
= 0;
242 sal_uInt16 nVerticalResolution
= 0;
243 sal_uInt8 nHorzThumbnailPixelCount
= 0;
244 sal_uInt8 nVertThumbnailPixelCount
= 0;
246 rStm
.ReadUChar( nStringTerminator
)
247 .ReadUChar( nMajorRevision
)
248 .ReadUChar( nMinorRevision
)
250 .ReadUInt16( nHorizontalResolution
)
251 .ReadUInt16( nVerticalResolution
)
252 .ReadUChar( nHorzThumbnailPixelCount
)
253 .ReadUChar( nVertThumbnailPixelCount
);
255 // setting the logical size
256 if ( nUnits
&& nHorizontalResolution
&& nVerticalResolution
)
258 aMap
.SetMapUnit( nUnits
== 1 ? MapUnit::MapInch
: MapUnit::MapCM
);
259 aMap
.SetScaleX( Fraction( 1, nHorizontalResolution
) );
260 aMap
.SetScaleY( Fraction( 1, nVerticalResolution
) );
261 aMetadata
.maLogSize
= OutputDevice::LogicToLogic( aMetadata
.maPixSize
, aMap
, MapMode( MapUnit::Map100thMM
) );
268 // Start of Frame Markers
283 sal_uInt8 nSamplePrecision
= 0;
284 sal_uInt16 nNumberOfLines
= 0;
285 sal_uInt16 nSamplesPerLine
= 0;
286 sal_uInt8 nNumberOfImageComponents
= 0;
287 sal_uInt8 nComponentsIdentifier
= 0;
288 sal_uInt8 nSamplingFactor
= 0;
289 sal_uInt8 nQuantizationTableDestinationSelector
= 0;
290 rStm
.ReadUChar( nSamplePrecision
)
291 .ReadUInt16( nNumberOfLines
)
292 .ReadUInt16( nSamplesPerLine
)
293 .ReadUChar( nNumberOfImageComponents
)
294 .ReadUChar( nComponentsIdentifier
)
295 .ReadUChar( nSamplingFactor
)
296 .ReadUChar( nQuantizationTableDestinationSelector
);
297 aMetadata
.mnNumberOfImageComponents
= nNumberOfImageComponents
;
299 // nSamplingFactor (lower nibble: vertical,
300 // upper nibble: horizontal) is unused
302 aMetadata
.maPixSize
.setHeight( nNumberOfLines
);
303 aMetadata
.maPixSize
.setWidth( nSamplesPerLine
);
304 aMetadata
.mnBitsPerPixel
= ( nNumberOfImageComponents
== 3 ? 24 : nNumberOfImageComponents
== 1 ? 8 : 0 );
305 aMetadata
.mnPlanes
= 1;
307 if (aMap
.GetMapUnit() != MapUnit::MapPixel
)
308 // We already know the DPI, but the
309 // pixel size arrived later, so do the
311 aMetadata
.maLogSize
= OutputDevice::LogicToLogic(
312 aMetadata
.maPixSize
, aMap
, MapMode(MapUnit::Map100thMM
));
314 bScanFinished
= true;
318 rStm
.Seek( nNextMarkerPos
);
324 rStm
.SetError( nError
);
327 rStm
.Seek( nStmPos
);
331 bool GraphicDescriptor::ImpDetectPCD( SvStream
& rStm
, bool )
333 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
334 bool bRet
= aDetector
.detect() && aDetector
.checkPCD();
336 aMetadata
= aDetector
.getMetadata();
340 bool GraphicDescriptor::ImpDetectPCX( SvStream
& rStm
)
342 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, true /*bExtendedInfo*/ );
343 bool bRet
= aDetector
.detect() && aDetector
.checkPCX();
345 aMetadata
= aDetector
.getMetadata();
349 bool GraphicDescriptor::ImpDetectPNG( SvStream
& rStm
, bool bExtendedInfo
)
351 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
352 bool bRet
= aDetector
.detect() && aDetector
.checkPNG();
354 aMetadata
= aDetector
.getMetadata();
358 bool GraphicDescriptor::ImpDetectTIF( SvStream
& rStm
, bool bExtendedInfo
)
360 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
361 bool bRet
= aDetector
.detect() && aDetector
.checkTIF();
363 aMetadata
= aDetector
.getMetadata();
367 bool GraphicDescriptor::ImpDetectXBM( SvStream
& rStm
, bool )
369 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
370 bool bRet
= aDetector
.detect() && aDetector
.checkXBM();
372 aMetadata
= aDetector
.getMetadata();
376 bool GraphicDescriptor::ImpDetectXPM( SvStream
& rStm
, bool )
378 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
379 bool bRet
= aDetector
.detect() && aDetector
.checkXPM();
381 aMetadata
= aDetector
.getMetadata();
385 bool GraphicDescriptor::ImpDetectPBM( SvStream
& rStm
, bool )
387 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
388 bool bRet
= aDetector
.detect() && aDetector
.checkPBM();
390 aMetadata
= aDetector
.getMetadata();
394 bool GraphicDescriptor::ImpDetectPGM( SvStream
& rStm
, bool )
396 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
397 bool bRet
= aDetector
.detect() && aDetector
.checkPGM();
399 aMetadata
= aDetector
.getMetadata();
403 bool GraphicDescriptor::ImpDetectPPM( SvStream
& rStm
, bool )
405 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
406 bool bRet
= aDetector
.detect() && aDetector
.checkPPM();
408 aMetadata
= aDetector
.getMetadata();
412 bool GraphicDescriptor::ImpDetectRAS( SvStream
& rStm
, bool )
414 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
415 bool bRet
= aDetector
.detect() && aDetector
.checkRAS();
417 aMetadata
= aDetector
.getMetadata();
421 bool GraphicDescriptor::ImpDetectTGA( SvStream
& rStm
, bool )
423 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
424 bool bRet
= aDetector
.detect() && aDetector
.checkTGA();
426 aMetadata
= aDetector
.getMetadata();
430 bool GraphicDescriptor::ImpDetectPSD( SvStream
& rStm
, bool bExtendedInfo
)
432 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
433 bool bRet
= aDetector
.detect() && aDetector
.checkPSD();
435 aMetadata
= aDetector
.getMetadata();
439 bool GraphicDescriptor::ImpDetectEPS( SvStream
& rStm
, bool )
441 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
442 bool bRet
= aDetector
.detect() && aDetector
.checkEPS();
444 aMetadata
= aDetector
.getMetadata();
448 bool GraphicDescriptor::ImpDetectDXF( SvStream
& rStm
, bool )
450 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
451 bool bRet
= aDetector
.detect() && aDetector
.checkDXF();
453 aMetadata
= aDetector
.getMetadata();
457 bool GraphicDescriptor::ImpDetectMET( SvStream
& rStm
, bool )
459 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
460 bool bRet
= aDetector
.detect() && aDetector
.checkMET();
462 aMetadata
= aDetector
.getMetadata();
466 bool GraphicDescriptor::ImpDetectPCT( SvStream
& rStm
, bool )
468 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
469 bool bRet
= aDetector
.detect() && aDetector
.checkPCT();
471 aMetadata
= aDetector
.getMetadata();
475 bool GraphicDescriptor::ImpDetectSVM( SvStream
& rStm
, bool bExtendedInfo
)
477 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
478 bool bRet
= aDetector
.detect() && aDetector
.checkSVM();
480 aMetadata
= aDetector
.getMetadata();
484 bool GraphicDescriptor::ImpDetectWMF(SvStream
& rStm
, bool /*bExtendedInfo*/)
486 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
487 bool bRet
= aDetector
.detect() && aDetector
.checkWMF();
489 aMetadata
= aDetector
.getMetadata();
493 bool GraphicDescriptor::ImpDetectEMF(SvStream
& rStm
, bool bExtendedInfo
)
495 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
496 bool bRet
= aDetector
.detect() && aDetector
.checkEMF();
498 aMetadata
= aDetector
.getMetadata();
502 bool GraphicDescriptor::ImpDetectSVG( SvStream
& rStm
, bool /*bExtendedInfo*/ )
504 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
505 bool bRet
= aDetector
.detect() && aDetector
.checkSVG();
507 aMetadata
= aDetector
.getMetadata();
511 bool GraphicDescriptor::ImpDetectWEBP( SvStream
& rStm
, bool bExtendedInfo
)
513 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
514 bool bRet
= aDetector
.detect() && aDetector
.checkWEBP();
516 aMetadata
= aDetector
.getMetadata();
520 OUString
GraphicDescriptor::GetImportFormatShortName( GraphicFileFormat nFormat
)
522 return vcl::getImportFormatShortName( nFormat
);
525 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */