LibreOffice Module vcl (master) 1
graphicfilter2.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 <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>
30
31namespace
32{
33enum class MetafileType : sal_uInt16
34{
35 Memory = 0x0001,
36 Disk = 0x0002,
37};
38enum class MetafileVersion : sal_uInt16
39{
40 Version100 = 0x0100,
41 Version300 = 0x0300,
42};
43}
44
46 pFileStm( ::utl::UcbStreamHelper::CreateStream( rPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ).release() ),
47 aPathExt( rPath.GetFileExtension().toAsciiLowerCase() ),
48 bOwnStream( true )
49{
51}
52
53GraphicDescriptor::GraphicDescriptor( SvStream& rInStream, const OUString* pPath) :
54 pFileStm ( &rInStream ),
55 bOwnStream ( false )
56{
58
59 if ( pPath )
60 {
61 INetURLObject aURL( *pPath );
62 aPathExt = aURL.GetFileExtension().toAsciiLowerCase();
63 }
64}
65
67{
68 if ( bOwnStream )
69 delete pFileStm;
70}
71
72bool GraphicDescriptor::Detect( bool bExtendedInfo )
73{
74 bool bRet = false;
75 if ( pFileStm && !pFileStm->GetError() )
76 {
77 SvStream& rStm = *pFileStm;
78 SvStreamEndian nOldFormat = rStm.GetEndian();
79
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;
104
105 rStm.SetEndian( nOldFormat );
106 }
107 return bRet;
108}
109
111{
117 aMetadata.mbIsAlpha = false;
118}
119
120bool GraphicDescriptor::ImpDetectBMP( SvStream& rStm, bool bExtendedInfo )
121{
122 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
123 bool bRet = aDetector.detect() && aDetector.checkBMP();
124 if ( bRet )
125 aMetadata = aDetector.getMetadata();
126 return bRet;
127}
128
129bool GraphicDescriptor::ImpDetectGIF( SvStream& rStm, bool bExtendedInfo )
130{
131 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
132 bool bRet = aDetector.detect() && aDetector.checkGIF();
133 if ( bRet )
134 aMetadata = aDetector.getMetadata();
135 return bRet;
136}
137
138// returns the next jpeg marker, a return value of 0 represents an error
140{
141 sal_uInt8 nByte;
142 do
143 {
144 do
145 {
146 rStm.ReadUChar( nByte );
147 if (!rStm.good()) // as 0 is not allowed as marker,
148 return 0; // we can use it as errorcode
149 }
150 while ( nByte != 0xff );
151 do
152 {
153 rStm.ReadUChar( nByte );
154 if (!rStm.good())
155 return 0;
156 }
157 while( nByte == 0xff );
158 }
159 while( nByte == 0 ); // 0xff00 represents 0xff and not a marker,
160 // the marker detection has to be restarted.
161 return nByte;
162}
163
164bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm, bool bExtendedInfo )
165{
166 sal_uInt32 nTemp32 = 0;
167 bool bRet = false;
168
169 sal_Int32 nStmPos = rStm.Tell();
170
171 rStm.SetEndian( SvStreamEndian::BIG );
172 rStm.ReadUInt32( nTemp32 );
173
174 // compare upper 24 bits
175 if( 0xffd8ff00 == ( nTemp32 & 0xffffff00 ) )
176 {
178 bRet = true;
179
180 if ( bExtendedInfo )
181 {
182 rStm.SeekRel( -2 );
183
184 ErrCode nError( rStm.GetError() );
185
186 bool bScanFailure = false;
187 bool bScanFinished = false;
189
190 while (!bScanFailure && !bScanFinished && rStm.good())
191 {
192 sal_uInt8 nMarker = ImpDetectJPG_GetNextMarker( rStm );
193 switch( nMarker )
194 {
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;
206
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;
211
212 case 0xd9 : // EOI
213 bScanFinished = true;
214 break;
215
216 // per default we assume marker segments containing a length parameter
217 default :
218 {
219 sal_uInt16 nLength = 0;
220 rStm.ReadUInt16( nLength );
221
222 if ( nLength < 2 )
223 bScanFailure = true;
224 else
225 {
226 sal_uInt32 nNextMarkerPos = rStm.Tell() + nLength - 2;
227 switch( nMarker )
228 {
229 case 0xe0 : // APP0 Marker
230 {
231 if ( nLength == 16 )
232 {
233 sal_Int32 nIdentifier = 0;
234 rStm.ReadInt32( nIdentifier );
235 if ( nIdentifier == 0x4a464946 ) // JFIF Identifier
236 {
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;
245
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 );
254
255 // setting the logical size
256 if ( nUnits && nHorizontalResolution && nVerticalResolution )
257 {
258 aMap.SetMapUnit( nUnits == 1 ? MapUnit::MapInch : MapUnit::MapCM );
259 aMap.SetScaleX( Fraction( 1, nHorizontalResolution ) );
260 aMap.SetScaleY( Fraction( 1, nVerticalResolution ) );
262 }
263 }
264 }
265 }
266 break;
267
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
282 {
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;
298
299 // nSamplingFactor (lower nibble: vertical,
300 // upper nibble: horizontal) is unused
301
302 aMetadata.maPixSize.setHeight( nNumberOfLines );
303 aMetadata.maPixSize.setWidth( nSamplesPerLine );
304 aMetadata.mnBitsPerPixel = ( nNumberOfImageComponents == 3 ? 24 : nNumberOfImageComponents == 1 ? 8 : 0 );
306
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.
312 aMetadata.maPixSize, aMap, MapMode(MapUnit::Map100thMM));
313
314 bScanFinished = true;
315 }
316 break;
317 }
318 rStm.Seek( nNextMarkerPos );
319 }
320 }
321 break;
322 }
323 }
324 rStm.SetError( nError );
325 }
326 }
327 rStm.Seek( nStmPos );
328 return bRet;
329}
330
332{
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;
338}
339
341{
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;
347}
348
349bool GraphicDescriptor::ImpDetectPNG( SvStream& rStm, bool bExtendedInfo )
350{
351 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
352 bool bRet = aDetector.detect() && aDetector.checkPNG();
353 if ( bRet )
354 aMetadata = aDetector.getMetadata();
355 return bRet;
356}
357
358bool GraphicDescriptor::ImpDetectTIF( SvStream& rStm, bool bExtendedInfo )
359{
360 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
361 bool bRet = aDetector.detect() && aDetector.checkTIF();
362 if ( bRet )
363 aMetadata = aDetector.getMetadata();
364 return bRet;
365}
366
368{
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;
374}
375
377{
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;
383}
384
386{
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;
392}
393
395{
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;
401}
402
404{
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;
410}
411
413{
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;
419}
420
422{
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;
428}
429
430bool GraphicDescriptor::ImpDetectPSD( SvStream& rStm, bool bExtendedInfo )
431{
432 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
433 bool bRet = aDetector.detect() && aDetector.checkPSD();
434 if ( bRet )
435 aMetadata = aDetector.getMetadata();
436 return bRet;
437}
438
440{
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;
446}
447
449{
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;
455}
456
458{
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;
464}
465
467{
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;
473}
474
475bool GraphicDescriptor::ImpDetectSVM( SvStream& rStm, bool bExtendedInfo )
476{
477 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
478 bool bRet = aDetector.detect() && aDetector.checkSVM();
479 if ( bRet )
480 aMetadata = aDetector.getMetadata();
481 return bRet;
482}
483
484bool GraphicDescriptor::ImpDetectWMF(SvStream& rStm, bool /*bExtendedInfo*/)
485{
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;
491}
492
493bool GraphicDescriptor::ImpDetectEMF(SvStream& rStm, bool bExtendedInfo)
494{
495 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
496 bool bRet = aDetector.detect() && aDetector.checkEMF();
497 if ( bRet )
498 aMetadata = aDetector.getMetadata();
499 return bRet;
500}
501
502bool GraphicDescriptor::ImpDetectSVG( SvStream& rStm, bool /*bExtendedInfo*/ )
503{
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;
509}
510
511bool GraphicDescriptor::ImpDetectWEBP( SvStream& rStm, bool bExtendedInfo )
512{
513 vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
514 bool bRet = aDetector.detect() && aDetector.checkWEBP();
515 if ( bRet )
516 aMetadata = aDetector.getMetadata();
517 return bRet;
518}
519
521{
522 return vcl::getImportFormatShortName( nFormat );
523}
524
525/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
GraphicFileFormat
bool ImpDetectDXF(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectSVM(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectWMF(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectPNG(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectTIF(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectPGM(SvStream &rStm, bool bExtendedInfo)
GraphicDescriptor(const GraphicDescriptor &)=delete
static OUString GetImportFormatShortName(GraphicFileFormat nFormat)
bool Detect(bool bExtendedInfo=false)
starts the detection
bool ImpDetectMET(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectRAS(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectPCD(SvStream &rStm, bool bExtendedInfo)
GraphicMetadata aMetadata
bool ImpDetectEPS(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectPPM(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectPSD(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectWEBP(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectXPM(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectPBM(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectXBM(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectBMP(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectJPG(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectSVG(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectGIF(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectPCX(SvStream &rStm)
bool ImpDetectEMF(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectTGA(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectPCT(SvStream &rStm, bool bExtendedInfo)
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1605
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
sal_uInt64 Tell() const
void SetEndian(SvStreamEndian SvStreamEndian)
bool good() const
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
SvStreamEndian GetEndian() const
void SetError(ErrCode nErrorCode)
sal_uInt64 Seek(sal_uInt64 nPos)
SvStream & ReadInt32(sal_Int32 &rInt32)
sal_uInt64 SeekRel(sal_Int64 nPos)
ErrCode GetError() const
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
SvStream & ReadUChar(unsigned char &rChar)
const GraphicMetadata & getMetadata()
URL aURL
static sal_uInt8 ImpDetectJPG_GetNextMarker(SvStream &rStm)
NONE
uno::Reference< io::XStream > CreateStream(uno::Reference< embed::XStorage > const &xStorage, OUString const &rFilename)
READ
static OUString getImportFormatShortName(GraphicFileFormat nFormat)
@ Memory
HashMap_OWString_Interface aMap
StreamMode
SvStreamEndian
GraphicFileFormat mnFormat
sal_uInt16 mnBitsPerPixel
sal_uInt8 mnNumberOfImageComponents
unsigned char sal_uInt8
sal_Int32 nLength