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>
30 GraphicDescriptor::GraphicDescriptor( const INetURLObject
& rPath
) :
31 pFileStm( ::utl::UcbStreamHelper::CreateStream( rPath
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), StreamMode::READ
).release() ),
32 aPathExt( rPath
.GetFileExtension().toAsciiLowerCase() ),
37 GraphicDescriptor::GraphicDescriptor( SvStream
& rInStream
, const OUString
* pPath
) :
38 pFileStm ( &rInStream
),
43 INetURLObject
aURL( *pPath
);
44 aPathExt
= aURL
.GetFileExtension().toAsciiLowerCase();
48 GraphicDescriptor::~GraphicDescriptor()
54 bool GraphicDescriptor::Detect( bool bExtendedInfo
)
57 if ( pFileStm
&& !pFileStm
->GetError() )
59 SvStream
& rStm
= *pFileStm
;
60 SvStreamEndian nOldFormat
= rStm
.GetEndian();
62 if ( ImpDetectGIF( rStm
, bExtendedInfo
) ) bRet
= true;
63 else if ( ImpDetectJPG( rStm
, bExtendedInfo
) ) bRet
= true;
64 else if ( ImpDetectBMP( rStm
, bExtendedInfo
) ) bRet
= true;
65 else if ( ImpDetectPNG( rStm
, bExtendedInfo
) ) bRet
= true;
66 else if ( ImpDetectTIF( rStm
, bExtendedInfo
) ) bRet
= true;
67 else if ( ImpDetectPCX( rStm
) ) bRet
= true;
68 else if ( ImpDetectDXF( rStm
, bExtendedInfo
) ) bRet
= true;
69 else if ( ImpDetectMET( rStm
, bExtendedInfo
) ) bRet
= true;
70 else if ( ImpDetectSVM( rStm
, bExtendedInfo
) ) bRet
= true;
71 else if ( ImpDetectWMF( rStm
, bExtendedInfo
) ) bRet
= true;
72 else if ( ImpDetectEMF( rStm
, bExtendedInfo
) ) bRet
= true;
73 else if ( ImpDetectSVG( rStm
, bExtendedInfo
) ) bRet
= true;
74 else if ( ImpDetectPCT( rStm
, bExtendedInfo
) ) bRet
= true;
75 else if ( ImpDetectXBM( rStm
, bExtendedInfo
) ) bRet
= true;
76 else if ( ImpDetectXPM( rStm
, bExtendedInfo
) ) bRet
= true;
77 else if ( ImpDetectPBM( rStm
, bExtendedInfo
) ) bRet
= true;
78 else if ( ImpDetectPGM( rStm
, bExtendedInfo
) ) bRet
= true;
79 else if ( ImpDetectPPM( rStm
, bExtendedInfo
) ) bRet
= true;
80 else if ( ImpDetectRAS( rStm
, bExtendedInfo
) ) bRet
= true;
81 else if ( ImpDetectTGA( rStm
, bExtendedInfo
) ) bRet
= true;
82 else if ( ImpDetectPSD( rStm
, bExtendedInfo
) ) bRet
= true;
83 else if ( ImpDetectEPS( rStm
, bExtendedInfo
) ) bRet
= true;
84 else if ( ImpDetectPCD( rStm
, bExtendedInfo
) ) bRet
= true;
85 else if ( ImpDetectWEBP( rStm
, bExtendedInfo
) ) bRet
= true;
87 rStm
.SetEndian( nOldFormat
);
92 bool GraphicDescriptor::ImpDetectBMP( SvStream
& rStm
, bool bExtendedInfo
)
94 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
95 bool bRet
= aDetector
.detect() && aDetector
.checkBMP();
97 aMetadata
= aDetector
.getMetadata();
101 bool GraphicDescriptor::ImpDetectGIF( SvStream
& rStm
, bool bExtendedInfo
)
103 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
104 bool bRet
= aDetector
.detect() && aDetector
.checkGIF();
106 aMetadata
= aDetector
.getMetadata();
110 // returns the next jpeg marker, a return value of 0 represents an error
111 static sal_uInt8
ImpDetectJPG_GetNextMarker( SvStream
& rStm
)
118 rStm
.ReadUChar( nByte
);
119 if (!rStm
.good()) // as 0 is not allowed as marker,
120 return 0; // we can use it as errorcode
122 while ( nByte
!= 0xff );
125 rStm
.ReadUChar( nByte
);
129 while( nByte
== 0xff );
131 while( nByte
== 0 ); // 0xff00 represents 0xff and not a marker,
132 // the marker detection has to be restarted.
136 bool GraphicDescriptor::ImpDetectJPG( SvStream
& rStm
, bool bExtendedInfo
)
138 sal_uInt32 nTemp32
= 0;
141 sal_uInt64 nStmPos
= rStm
.Tell();
143 rStm
.SetEndian( SvStreamEndian::BIG
);
144 rStm
.ReadUInt32( nTemp32
);
146 // compare upper 24 bits
147 if( 0xffd8ff00 == ( nTemp32
& 0xffffff00 ) )
149 aMetadata
.mnFormat
= GraphicFileFormat::JPG
;
156 ErrCode
nError( rStm
.GetError() );
158 bool bScanFailure
= false;
159 bool bScanFinished
= false;
162 while (!bScanFailure
&& !bScanFinished
&& rStm
.good())
164 sal_uInt8 nMarker
= ImpDetectJPG_GetNextMarker( rStm
);
167 // fixed size marker, not having a two byte length parameter
179 case 0xd8 : // SOI (has already been checked, there should not be a second one)
180 case 0x00 : // marker is invalid, we should stop now
185 bScanFinished
= true;
188 // per default we assume marker segments containing a length parameter
191 sal_uInt16 nLength
= 0;
192 rStm
.ReadUInt16( nLength
);
198 sal_uInt64 nNextMarkerPos
= rStm
.Tell() + nLength
- 2;
201 case 0xe0 : // APP0 Marker
205 sal_Int32 nIdentifier
= 0;
206 rStm
.ReadInt32( nIdentifier
);
207 if ( nIdentifier
== 0x4a464946 ) // JFIF Identifier
209 sal_uInt8 nStringTerminator
= 0;
210 sal_uInt8 nMajorRevision
= 0;
211 sal_uInt8 nMinorRevision
= 0;
212 sal_uInt8 nUnits
= 0;
213 sal_uInt16 nHorizontalResolution
= 0;
214 sal_uInt16 nVerticalResolution
= 0;
215 sal_uInt8 nHorzThumbnailPixelCount
= 0;
216 sal_uInt8 nVertThumbnailPixelCount
= 0;
218 rStm
.ReadUChar( nStringTerminator
)
219 .ReadUChar( nMajorRevision
)
220 .ReadUChar( nMinorRevision
)
222 .ReadUInt16( nHorizontalResolution
)
223 .ReadUInt16( nVerticalResolution
)
224 .ReadUChar( nHorzThumbnailPixelCount
)
225 .ReadUChar( nVertThumbnailPixelCount
);
227 // setting the logical size
228 if ( nUnits
&& nHorizontalResolution
&& nVerticalResolution
)
230 aMap
.SetMapUnit( nUnits
== 1 ? MapUnit::MapInch
: MapUnit::MapCM
);
231 aMap
.SetScaleX( Fraction( 1, nHorizontalResolution
) );
232 aMap
.SetScaleY( Fraction( 1, nVerticalResolution
) );
233 aMetadata
.maLogSize
= OutputDevice::LogicToLogic( aMetadata
.maPixSize
, aMap
, MapMode( MapUnit::Map100thMM
) );
240 // Start of Frame Markers
255 sal_uInt8 nSamplePrecision
= 0;
256 sal_uInt16 nNumberOfLines
= 0;
257 sal_uInt16 nSamplesPerLine
= 0;
258 sal_uInt8 nNumberOfImageComponents
= 0;
259 sal_uInt8 nComponentsIdentifier
= 0;
260 sal_uInt8 nSamplingFactor
= 0;
261 sal_uInt8 nQuantizationTableDestinationSelector
= 0;
262 rStm
.ReadUChar( nSamplePrecision
)
263 .ReadUInt16( nNumberOfLines
)
264 .ReadUInt16( nSamplesPerLine
)
265 .ReadUChar( nNumberOfImageComponents
)
266 .ReadUChar( nComponentsIdentifier
)
267 .ReadUChar( nSamplingFactor
)
268 .ReadUChar( nQuantizationTableDestinationSelector
);
269 aMetadata
.mnNumberOfImageComponents
= nNumberOfImageComponents
;
271 // nSamplingFactor (lower nibble: vertical,
272 // upper nibble: horizontal) is unused
274 aMetadata
.maPixSize
.setHeight( nNumberOfLines
);
275 aMetadata
.maPixSize
.setWidth( nSamplesPerLine
);
276 aMetadata
.mnBitsPerPixel
= ( nNumberOfImageComponents
== 3 ? 24 : nNumberOfImageComponents
== 1 ? 8 : 0 );
277 aMetadata
.mnPlanes
= 1;
279 if (aMap
.GetMapUnit() != MapUnit::MapPixel
)
280 // We already know the DPI, but the
281 // pixel size arrived later, so do the
283 aMetadata
.maLogSize
= OutputDevice::LogicToLogic(
284 aMetadata
.maPixSize
, aMap
, MapMode(MapUnit::Map100thMM
));
286 bScanFinished
= true;
290 rStm
.Seek( nNextMarkerPos
);
296 rStm
.SetError( nError
);
299 rStm
.Seek( nStmPos
);
303 bool GraphicDescriptor::ImpDetectPCD( SvStream
& rStm
, bool )
305 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
306 bool bRet
= aDetector
.detect() && aDetector
.checkPCD();
308 aMetadata
= aDetector
.getMetadata();
312 bool GraphicDescriptor::ImpDetectPCX( SvStream
& rStm
)
314 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, true /*bExtendedInfo*/ );
315 bool bRet
= aDetector
.detect() && aDetector
.checkPCX();
317 aMetadata
= aDetector
.getMetadata();
321 bool GraphicDescriptor::ImpDetectPNG( SvStream
& rStm
, bool bExtendedInfo
)
323 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
324 bool bRet
= aDetector
.detect() && aDetector
.checkPNG();
326 aMetadata
= aDetector
.getMetadata();
330 bool GraphicDescriptor::ImpDetectTIF( SvStream
& rStm
, bool bExtendedInfo
)
332 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
333 bool bRet
= aDetector
.detect() && aDetector
.checkTIF();
335 aMetadata
= aDetector
.getMetadata();
339 bool GraphicDescriptor::ImpDetectXBM( SvStream
& rStm
, bool )
341 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
342 bool bRet
= aDetector
.detect() && aDetector
.checkXBM();
344 aMetadata
= aDetector
.getMetadata();
348 bool GraphicDescriptor::ImpDetectXPM( SvStream
& rStm
, bool )
350 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
351 bool bRet
= aDetector
.detect() && aDetector
.checkXPM();
353 aMetadata
= aDetector
.getMetadata();
357 bool GraphicDescriptor::ImpDetectPBM( SvStream
& rStm
, bool )
359 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
360 bool bRet
= aDetector
.detect() && aDetector
.checkPBM();
362 aMetadata
= aDetector
.getMetadata();
366 bool GraphicDescriptor::ImpDetectPGM( SvStream
& rStm
, bool )
368 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
369 bool bRet
= aDetector
.detect() && aDetector
.checkPGM();
371 aMetadata
= aDetector
.getMetadata();
375 bool GraphicDescriptor::ImpDetectPPM( SvStream
& rStm
, bool )
377 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
378 bool bRet
= aDetector
.detect() && aDetector
.checkPPM();
380 aMetadata
= aDetector
.getMetadata();
384 bool GraphicDescriptor::ImpDetectRAS( SvStream
& rStm
, bool )
386 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
387 bool bRet
= aDetector
.detect() && aDetector
.checkRAS();
389 aMetadata
= aDetector
.getMetadata();
393 bool GraphicDescriptor::ImpDetectTGA( SvStream
& rStm
, bool )
395 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /* bExtendedInfo */ );
396 bool bRet
= aDetector
.detect() && aDetector
.checkTGA();
398 aMetadata
= aDetector
.getMetadata();
402 bool GraphicDescriptor::ImpDetectPSD( SvStream
& rStm
, bool bExtendedInfo
)
404 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
405 bool bRet
= aDetector
.detect() && aDetector
.checkPSD();
407 aMetadata
= aDetector
.getMetadata();
411 bool GraphicDescriptor::ImpDetectEPS( SvStream
& rStm
, bool )
413 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
414 bool bRet
= aDetector
.detect() && aDetector
.checkEPS();
416 aMetadata
= aDetector
.getMetadata();
420 bool GraphicDescriptor::ImpDetectDXF( SvStream
& rStm
, bool )
422 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
423 bool bRet
= aDetector
.detect() && aDetector
.checkDXF();
425 aMetadata
= aDetector
.getMetadata();
429 bool GraphicDescriptor::ImpDetectMET( SvStream
& rStm
, bool )
431 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
432 bool bRet
= aDetector
.detect() && aDetector
.checkMET();
434 aMetadata
= aDetector
.getMetadata();
438 bool GraphicDescriptor::ImpDetectPCT( SvStream
& rStm
, bool )
440 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
441 bool bRet
= aDetector
.detect() && aDetector
.checkPCT();
443 aMetadata
= aDetector
.getMetadata();
447 bool GraphicDescriptor::ImpDetectSVM( SvStream
& rStm
, bool bExtendedInfo
)
449 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
450 bool bRet
= aDetector
.detect() && aDetector
.checkSVM();
452 aMetadata
= aDetector
.getMetadata();
456 bool GraphicDescriptor::ImpDetectWMF(SvStream
& rStm
, bool /*bExtendedInfo*/)
458 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
459 bool bRet
= aDetector
.detect() && aDetector
.checkWMF();
461 aMetadata
= aDetector
.getMetadata();
465 bool GraphicDescriptor::ImpDetectEMF(SvStream
& rStm
, bool bExtendedInfo
)
467 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
468 bool bRet
= aDetector
.detect() && aDetector
.checkEMF();
470 aMetadata
= aDetector
.getMetadata();
474 bool GraphicDescriptor::ImpDetectSVG( SvStream
& rStm
, bool /*bExtendedInfo*/ )
476 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, false /*bExtendedInfo*/ );
477 bool bRet
= aDetector
.detect() && aDetector
.checkSVG();
479 aMetadata
= aDetector
.getMetadata();
483 bool GraphicDescriptor::ImpDetectWEBP( SvStream
& rStm
, bool bExtendedInfo
)
485 vcl::GraphicFormatDetector
aDetector( rStm
, aPathExt
, bExtendedInfo
);
486 bool bRet
= aDetector
.detect() && aDetector
.checkWEBP();
488 aMetadata
= aDetector
.getMetadata();
492 OUString
GraphicDescriptor::GetImportFormatShortName( GraphicFileFormat nFormat
)
494 return vcl::getImportFormatShortName( nFormat
);
497 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */