android: Update app-specific/MIME type icons
[LibreOffice.git] / vcl / source / filter / graphicfilter2.cxx
blobfa5c25e30c938ad70cf77b9f5187c9dde811dc12
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <string.h>
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"
31 namespace
33 enum class MetafileType : sal_uInt16
35 Memory = 0x0001,
36 Disk = 0x0002,
38 enum class MetafileVersion : sal_uInt16
40 Version100 = 0x0100,
41 Version300 = 0x0300,
45 GraphicDescriptor::GraphicDescriptor( const INetURLObject& rPath ) :
46 pFileStm( ::utl::UcbStreamHelper::CreateStream( rPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ).release() ),
47 aPathExt( rPath.GetFileExtension().toAsciiLowerCase() ),
48 bOwnStream( true )
50 ImpConstruct();
53 GraphicDescriptor::GraphicDescriptor( SvStream& rInStream, const OUString* pPath) :
54 pFileStm ( &rInStream ),
55 bOwnStream ( false )
57 ImpConstruct();
59 if ( pPath )
61 INetURLObject aURL( *pPath );
62 aPathExt = aURL.GetFileExtension().toAsciiLowerCase();
66 GraphicDescriptor::~GraphicDescriptor()
68 if ( bOwnStream )
69 delete pFileStm;
72 bool GraphicDescriptor::Detect( bool bExtendedInfo )
74 bool bRet = false;
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 );
107 return bRet;
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();
124 if ( bRet )
125 aMetadata = aDetector.getMetadata();
126 return bRet;
129 bool GraphicDescriptor::ImpDetectGIF( SvStream& rStm, bool bExtendedInfo )
131 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
132 bool bRet = aDetector.detect() && aDetector.checkGIF();
133 if ( bRet )
134 aMetadata = aDetector.getMetadata();
135 return bRet;
138 // returns the next jpeg marker, a return value of 0 represents an error
139 static sal_uInt8 ImpDetectJPG_GetNextMarker( SvStream& rStm )
141 sal_uInt8 nByte;
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 );
154 if (!rStm.good())
155 return 0;
157 while( nByte == 0xff );
159 while( nByte == 0 ); // 0xff00 represents 0xff and not a marker,
160 // the marker detection has to be restarted.
161 return nByte;
164 bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm, bool bExtendedInfo )
166 sal_uInt32 nTemp32 = 0;
167 bool bRet = false;
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;
178 bRet = true;
180 if ( bExtendedInfo )
182 rStm.SeekRel( -2 );
184 ErrCode nError( rStm.GetError() );
186 bool bScanFailure = false;
187 bool bScanFinished = false;
188 MapMode aMap;
190 while (!bScanFailure && !bScanFinished && rStm.good())
192 sal_uInt8 nMarker = ImpDetectJPG_GetNextMarker( rStm );
193 switch( nMarker )
195 // fixed size marker, not having a two byte length parameter
196 case 0xd0 : // RST0
197 case 0xd1 :
198 case 0xd2 :
199 case 0xd3 :
200 case 0xd4 :
201 case 0xd5 :
202 case 0xd6 :
203 case 0xd7 : // RST7
204 case 0x01 : // TEM
205 break;
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
209 bScanFailure = true;
210 break;
212 case 0xd9 : // EOI
213 bScanFinished = true;
214 break;
216 // per default we assume marker segments containing a length parameter
217 default :
219 sal_uInt16 nLength = 0;
220 rStm.ReadUInt16( nLength );
222 if ( nLength < 2 )
223 bScanFailure = true;
224 else
226 sal_uInt32 nNextMarkerPos = rStm.Tell() + nLength - 2;
227 switch( nMarker )
229 case 0xe0 : // APP0 Marker
231 if ( nLength == 16 )
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 )
249 .ReadUChar( nUnits )
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 ) );
266 break;
268 // Start of Frame Markers
269 case 0xc0 : // SOF0
270 case 0xc1 : // SOF1
271 case 0xc2 : // SOF2
272 case 0xc3 : // SOF3
273 case 0xc5 : // SOF5
274 case 0xc6 : // SOF6
275 case 0xc7 : // SOF7
276 case 0xc9 : // SOF9
277 case 0xca : // SOF10
278 case 0xcb : // SOF11
279 case 0xcd : // SOF13
280 case 0xce : // SOF14
281 case 0xcf : // SOF15
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
310 // conversion again.
311 aMetadata.maLogSize = OutputDevice::LogicToLogic(
312 aMetadata.maPixSize, aMap, MapMode(MapUnit::Map100thMM));
314 bScanFinished = true;
316 break;
318 rStm.Seek( nNextMarkerPos );
321 break;
324 rStm.SetError( nError );
327 rStm.Seek( nStmPos );
328 return bRet;
331 bool GraphicDescriptor::ImpDetectPCD( SvStream& rStm, bool )
333 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /*bExtendedInfo*/ );
334 bool bRet = aDetector.detect() && aDetector.checkPCD();
335 if ( bRet )
336 aMetadata = aDetector.getMetadata();
337 return bRet;
340 bool GraphicDescriptor::ImpDetectPCX( SvStream& rStm )
342 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, true /*bExtendedInfo*/ );
343 bool bRet = aDetector.detect() && aDetector.checkPCX();
344 if ( bRet )
345 aMetadata = aDetector.getMetadata();
346 return bRet;
349 bool GraphicDescriptor::ImpDetectPNG( SvStream& rStm, bool bExtendedInfo )
351 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
352 bool bRet = aDetector.detect() && aDetector.checkPNG();
353 if ( bRet )
354 aMetadata = aDetector.getMetadata();
355 return bRet;
358 bool GraphicDescriptor::ImpDetectTIF( SvStream& rStm, bool bExtendedInfo )
360 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
361 bool bRet = aDetector.detect() && aDetector.checkTIF();
362 if ( bRet )
363 aMetadata = aDetector.getMetadata();
364 return bRet;
367 bool GraphicDescriptor::ImpDetectXBM( SvStream& rStm, bool )
369 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /* bExtendedInfo */ );
370 bool bRet = aDetector.detect() && aDetector.checkXBM();
371 if ( bRet )
372 aMetadata = aDetector.getMetadata();
373 return bRet;
376 bool GraphicDescriptor::ImpDetectXPM( SvStream& rStm, bool )
378 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /* bExtendedInfo */ );
379 bool bRet = aDetector.detect() && aDetector.checkXPM();
380 if ( bRet )
381 aMetadata = aDetector.getMetadata();
382 return bRet;
385 bool GraphicDescriptor::ImpDetectPBM( SvStream& rStm, bool )
387 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /* bExtendedInfo */ );
388 bool bRet = aDetector.detect() && aDetector.checkPBM();
389 if ( bRet )
390 aMetadata = aDetector.getMetadata();
391 return bRet;
394 bool GraphicDescriptor::ImpDetectPGM( SvStream& rStm, bool )
396 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /* bExtendedInfo */ );
397 bool bRet = aDetector.detect() && aDetector.checkPGM();
398 if ( bRet )
399 aMetadata = aDetector.getMetadata();
400 return bRet;
403 bool GraphicDescriptor::ImpDetectPPM( SvStream& rStm, bool )
405 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /* bExtendedInfo */ );
406 bool bRet = aDetector.detect() && aDetector.checkPPM();
407 if ( bRet )
408 aMetadata = aDetector.getMetadata();
409 return bRet;
412 bool GraphicDescriptor::ImpDetectRAS( SvStream& rStm, bool )
414 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /* bExtendedInfo */ );
415 bool bRet = aDetector.detect() && aDetector.checkRAS();
416 if ( bRet )
417 aMetadata = aDetector.getMetadata();
418 return bRet;
421 bool GraphicDescriptor::ImpDetectTGA( SvStream& rStm, bool )
423 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /* bExtendedInfo */ );
424 bool bRet = aDetector.detect() && aDetector.checkTGA();
425 if ( bRet )
426 aMetadata = aDetector.getMetadata();
427 return bRet;
430 bool GraphicDescriptor::ImpDetectPSD( SvStream& rStm, bool bExtendedInfo )
432 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
433 bool bRet = aDetector.detect() && aDetector.checkPSD();
434 if ( bRet )
435 aMetadata = aDetector.getMetadata();
436 return bRet;
439 bool GraphicDescriptor::ImpDetectEPS( SvStream& rStm, bool )
441 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /*bExtendedInfo*/ );
442 bool bRet = aDetector.detect() && aDetector.checkEPS();
443 if ( bRet )
444 aMetadata = aDetector.getMetadata();
445 return bRet;
448 bool GraphicDescriptor::ImpDetectDXF( SvStream& rStm, bool )
450 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /*bExtendedInfo*/ );
451 bool bRet = aDetector.detect() && aDetector.checkDXF();
452 if ( bRet )
453 aMetadata = aDetector.getMetadata();
454 return bRet;
457 bool GraphicDescriptor::ImpDetectMET( SvStream& rStm, bool )
459 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /*bExtendedInfo*/ );
460 bool bRet = aDetector.detect() && aDetector.checkMET();
461 if ( bRet )
462 aMetadata = aDetector.getMetadata();
463 return bRet;
466 bool GraphicDescriptor::ImpDetectPCT( SvStream& rStm, bool )
468 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /*bExtendedInfo*/ );
469 bool bRet = aDetector.detect() && aDetector.checkPCT();
470 if ( bRet )
471 aMetadata = aDetector.getMetadata();
472 return bRet;
475 bool GraphicDescriptor::ImpDetectSVM( SvStream& rStm, bool bExtendedInfo )
477 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
478 bool bRet = aDetector.detect() && aDetector.checkSVM();
479 if ( bRet )
480 aMetadata = aDetector.getMetadata();
481 return bRet;
484 bool GraphicDescriptor::ImpDetectWMF(SvStream& rStm, bool /*bExtendedInfo*/)
486 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /*bExtendedInfo*/ );
487 bool bRet = aDetector.detect() && aDetector.checkWMF();
488 if ( bRet )
489 aMetadata = aDetector.getMetadata();
490 return bRet;
493 bool GraphicDescriptor::ImpDetectEMF(SvStream& rStm, bool bExtendedInfo)
495 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
496 bool bRet = aDetector.detect() && aDetector.checkEMF();
497 if ( bRet )
498 aMetadata = aDetector.getMetadata();
499 return bRet;
502 bool GraphicDescriptor::ImpDetectSVG( SvStream& rStm, bool /*bExtendedInfo*/ )
504 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /*bExtendedInfo*/ );
505 bool bRet = aDetector.detect() && aDetector.checkSVG();
506 if ( bRet )
507 aMetadata = aDetector.getMetadata();
508 return bRet;
511 bool GraphicDescriptor::ImpDetectWEBP( SvStream& rStm, bool bExtendedInfo )
513 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
514 bool bRet = aDetector.detect() && aDetector.checkWEBP();
515 if ( bRet )
516 aMetadata = aDetector.getMetadata();
517 return bRet;
520 OUString GraphicDescriptor::GetImportFormatShortName( GraphicFileFormat nFormat )
522 return vcl::getImportFormatShortName( nFormat );
525 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */