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 <TypeSerializer.hxx>
25 #include <vcl/outdev.hxx>
26 #include <vcl/graphicfilter.hxx>
29 
30 #define DATA_SIZE 640
31 
33  pFileStm( ::utl::UcbStreamHelper::CreateStream( rPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ).release() ),
34  aPathExt( rPath.GetFileExtension().toAsciiLowerCase() ),
35  bOwnStream( true )
36 {
37  ImpConstruct();
38 }
39 
40 GraphicDescriptor::GraphicDescriptor( SvStream& rInStream, const OUString* pPath) :
41  pFileStm ( &rInStream ),
42  bOwnStream ( false )
43 {
44  ImpConstruct();
45 
46  if ( pPath )
47  {
48  INetURLObject aURL( *pPath );
49  aPathExt = aURL.GetFileExtension().toAsciiLowerCase();
50  }
51 }
52 
54 {
55  if ( bOwnStream )
56  delete pFileStm;
57 }
58 
59 bool GraphicDescriptor::Detect( bool bExtendedInfo )
60 {
61  bool bRet = false;
62  if ( pFileStm && !pFileStm->GetError() )
63  {
64  SvStream& rStm = *pFileStm;
65  SvStreamEndian nOldFormat = rStm.GetEndian();
66 
67  if ( ImpDetectGIF( rStm, bExtendedInfo ) ) bRet = true;
68  else if ( ImpDetectJPG( rStm, bExtendedInfo ) ) bRet = true;
69  else if ( ImpDetectBMP( rStm, bExtendedInfo ) ) bRet = true;
70  else if ( ImpDetectPNG( rStm, bExtendedInfo ) ) bRet = true;
71  else if ( ImpDetectTIF( rStm, bExtendedInfo ) ) bRet = true;
72  else if ( ImpDetectPCX( rStm ) ) bRet = true;
73  else if ( ImpDetectDXF( rStm, bExtendedInfo ) ) bRet = true;
74  else if ( ImpDetectMET( rStm, bExtendedInfo ) ) bRet = true;
75  else if ( ImpDetectSVM( rStm, bExtendedInfo ) ) bRet = true;
76  else if ( ImpDetectWMF( rStm, bExtendedInfo ) ) bRet = true;
77  else if ( ImpDetectEMF( rStm, bExtendedInfo ) ) bRet = true;
78  else if ( ImpDetectSVG( rStm, bExtendedInfo ) ) bRet = true;
79  else if ( ImpDetectPCT( rStm, bExtendedInfo ) ) bRet = true;
80  else if ( ImpDetectXBM( rStm, bExtendedInfo ) ) bRet = true;
81  else if ( ImpDetectXPM( rStm, bExtendedInfo ) ) bRet = true;
82  else if ( ImpDetectPBM( rStm, bExtendedInfo ) ) bRet = true;
83  else if ( ImpDetectPGM( rStm, bExtendedInfo ) ) bRet = true;
84  else if ( ImpDetectPPM( rStm, bExtendedInfo ) ) bRet = true;
85  else if ( ImpDetectRAS( rStm, bExtendedInfo ) ) bRet = true;
86  else if ( ImpDetectTGA( rStm, bExtendedInfo ) ) bRet = true;
87  else if ( ImpDetectPSD( rStm, bExtendedInfo ) ) bRet = true;
88  else if ( ImpDetectEPS( rStm, bExtendedInfo ) ) bRet = true;
89  else if ( ImpDetectPCD( rStm, bExtendedInfo ) ) bRet = true;
90 
91  rStm.SetEndian( nOldFormat );
92  }
93  return bRet;
94 }
95 
97 {
99  nBitsPerPixel = 0;
100  nPlanes = 0;
102  bIsTransparent = false;
103  bIsAlpha = false;
104 }
105 
106 bool GraphicDescriptor::ImpDetectBMP( SvStream& rStm, bool bExtendedInfo )
107 {
108  sal_uInt16 nTemp16 = 0;
109  bool bRet = false;
110  sal_Int32 nStmPos = rStm.Tell();
111 
112  rStm.SetEndian( SvStreamEndian::LITTLE );
113  rStm.ReadUInt16( nTemp16 );
114 
115  // OS/2-BitmapArray
116  if ( nTemp16 == 0x4142 )
117  {
118  rStm.SeekRel( 0x0c );
119  rStm.ReadUInt16( nTemp16 );
120  }
121 
122  // Bitmap
123  if ( nTemp16 == 0x4d42 )
124  {
126  bRet = true;
127 
128  if ( bExtendedInfo )
129  {
130  sal_uInt32 nTemp32;
131  sal_uInt32 nCompression;
132 
133  // up to first info
134  rStm.SeekRel( 0x10 );
135 
136  // Pixel width
137  rStm.ReadUInt32( nTemp32 );
138  aPixSize.setWidth( nTemp32 );
139 
140  // Pixel height
141  rStm.ReadUInt32( nTemp32 );
142  aPixSize.setHeight( nTemp32 );
143 
144  // Planes
145  rStm.ReadUInt16( nTemp16 );
146  nPlanes = nTemp16;
147 
148  // BitCount
149  rStm.ReadUInt16( nTemp16 );
150  nBitsPerPixel = nTemp16;
151 
152  // Compression
153  rStm.ReadUInt32( nTemp32 );
154  nCompression = nTemp32;
155 
156  // logical width
157  rStm.SeekRel( 4 );
158  rStm.ReadUInt32( nTemp32 );
159  if ( nTemp32 )
160  aLogSize.setWidth( ( aPixSize.Width() * 100000 ) / nTemp32 );
161 
162  // logical height
163  rStm.ReadUInt32( nTemp32 );
164  if ( nTemp32 )
165  aLogSize.setHeight( ( aPixSize.Height() * 100000 ) / nTemp32 );
166 
167  // further validation, check for rational values
168  if ( ( nBitsPerPixel > 24 ) || ( nCompression > 3 ) )
169  {
171  bRet = false;
172  }
173  }
174  }
175  rStm.Seek( nStmPos );
176  return bRet;
177 }
178 
179 bool GraphicDescriptor::ImpDetectGIF( SvStream& rStm, bool bExtendedInfo )
180 {
181  sal_uInt32 n32 = 0;
182  sal_uInt16 n16 = 0;
183  bool bRet = false;
184  sal_uInt8 cByte = 0;
185 
186  sal_Int32 nStmPos = rStm.Tell();
187  rStm.SetEndian( SvStreamEndian::LITTLE );
188  rStm.ReadUInt32( n32 );
189 
190  if ( n32 == 0x38464947 )
191  {
192  rStm.ReadUInt16( n16 );
193  if ( ( n16 == 0x6137 ) || ( n16 == 0x6139 ) )
194  {
196  bRet = true;
197 
198  if ( bExtendedInfo )
199  {
200  sal_uInt16 nTemp16 = 0;
201 
202  // Pixel width
203  rStm.ReadUInt16( nTemp16 );
204  aPixSize.setWidth( nTemp16 );
205 
206  // Pixel height
207  rStm.ReadUInt16( nTemp16 );
208  aPixSize.setHeight( nTemp16 );
209 
210  // Bits/Pixel
211  rStm.ReadUChar( cByte );
212  nBitsPerPixel = ( ( cByte & 112 ) >> 4 ) + 1;
213  }
214  }
215  }
216  rStm.Seek( nStmPos );
217  return bRet;
218 }
219 
220 // returns the next jpeg marker, a return value of 0 represents an error
222 {
223  sal_uInt8 nByte;
224  do
225  {
226  do
227  {
228  rStm.ReadUChar( nByte );
229  if (!rStm.good()) // as 0 is not allowed as marker,
230  return 0; // we can use it as errorcode
231  }
232  while ( nByte != 0xff );
233  do
234  {
235  rStm.ReadUChar( nByte );
236  if (!rStm.good())
237  return 0;
238  }
239  while( nByte == 0xff );
240  }
241  while( nByte == 0 ); // 0xff00 represents 0xff and not a marker,
242  // the marker detection has to be restarted.
243  return nByte;
244 }
245 
246 bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm, bool bExtendedInfo )
247 {
248  sal_uInt32 nTemp32 = 0;
249  bool bRet = false;
250 
251  sal_Int32 nStmPos = rStm.Tell();
252 
253  rStm.SetEndian( SvStreamEndian::BIG );
254  rStm.ReadUInt32( nTemp32 );
255 
256  // compare upper 24 bits
257  if( 0xffd8ff00 == ( nTemp32 & 0xffffff00 ) )
258  {
260  bRet = true;
261 
262  if ( bExtendedInfo )
263  {
264  rStm.SeekRel( -2 );
265 
266  ErrCode nError( rStm.GetError() );
267 
268  bool bScanFailure = false;
269  bool bScanFinished = false;
270  MapMode aMap;
271 
272  while (!bScanFailure && !bScanFinished && rStm.good())
273  {
274  sal_uInt8 nMarker = ImpDetectJPG_GetNextMarker( rStm );
275  switch( nMarker )
276  {
277  // fixed size marker, not having a two byte length parameter
278  case 0xd0 : // RST0
279  case 0xd1 :
280  case 0xd2 :
281  case 0xd3 :
282  case 0xd4 :
283  case 0xd5 :
284  case 0xd6 :
285  case 0xd7 : // RST7
286  case 0x01 : // TEM
287  break;
288 
289  case 0xd8 : // SOI (has already been checked, there should not be a second one)
290  case 0x00 : // marker is invalid, we should stop now
291  bScanFailure = true;
292  break;
293 
294  case 0xd9 : // EOI
295  bScanFinished = true;
296  break;
297 
298  // per default we assume marker segments containing a length parameter
299  default :
300  {
301  sal_uInt16 nLength = 0;
302  rStm.ReadUInt16( nLength );
303 
304  if ( nLength < 2 )
305  bScanFailure = true;
306  else
307  {
308  sal_uInt32 nNextMarkerPos = rStm.Tell() + nLength - 2;
309  switch( nMarker )
310  {
311  case 0xe0 : // APP0 Marker
312  {
313  if ( nLength == 16 )
314  {
315  sal_Int32 nIdentifier = 0;
316  rStm.ReadInt32( nIdentifier );
317  if ( nIdentifier == 0x4a464946 ) // JFIF Identifier
318  {
319  sal_uInt8 nStringTerminator = 0;
320  sal_uInt8 nMajorRevision = 0;
321  sal_uInt8 nMinorRevision = 0;
322  sal_uInt8 nUnits = 0;
323  sal_uInt16 nHorizontalResolution = 0;
324  sal_uInt16 nVerticalResolution = 0;
325  sal_uInt8 nHorzThumbnailPixelCount = 0;
326  sal_uInt8 nVertThumbnailPixelCount = 0;
327 
328  rStm.ReadUChar( nStringTerminator )
329  .ReadUChar( nMajorRevision )
330  .ReadUChar( nMinorRevision )
331  .ReadUChar( nUnits )
332  .ReadUInt16( nHorizontalResolution )
333  .ReadUInt16( nVerticalResolution )
334  .ReadUChar( nHorzThumbnailPixelCount )
335  .ReadUChar( nVertThumbnailPixelCount );
336 
337  // setting the logical size
338  if ( nUnits && nHorizontalResolution && nVerticalResolution )
339  {
340  aMap.SetMapUnit( nUnits == 1 ? MapUnit::MapInch : MapUnit::MapCM );
341  aMap.SetScaleX( Fraction( 1, nHorizontalResolution ) );
342  aMap.SetScaleY( Fraction( 1, nVerticalResolution ) );
343  aLogSize = OutputDevice::LogicToLogic( aPixSize, aMap, MapMode( MapUnit::Map100thMM ) );
344  }
345  }
346  }
347  }
348  break;
349 
350  // Start of Frame Markers
351  case 0xc0 : // SOF0
352  case 0xc1 : // SOF1
353  case 0xc2 : // SOF2
354  case 0xc3 : // SOF3
355  case 0xc5 : // SOF5
356  case 0xc6 : // SOF6
357  case 0xc7 : // SOF7
358  case 0xc9 : // SOF9
359  case 0xca : // SOF10
360  case 0xcb : // SOF11
361  case 0xcd : // SOF13
362  case 0xce : // SOF14
363  case 0xcf : // SOF15
364  {
365  sal_uInt8 nSamplePrecision = 0;
366  sal_uInt16 nNumberOfLines = 0;
367  sal_uInt16 nSamplesPerLine = 0;
368  sal_uInt8 nNumberOfImageComponents = 0;
369  sal_uInt8 nComponentsIdentifier = 0;
370  sal_uInt8 nSamplingFactor = 0;
371  sal_uInt8 nQuantizationTableDestinationSelector = 0;
372  rStm.ReadUChar( nSamplePrecision )
373  .ReadUInt16( nNumberOfLines )
374  .ReadUInt16( nSamplesPerLine )
375  .ReadUChar( nNumberOfImageComponents )
376  .ReadUChar( nComponentsIdentifier )
377  .ReadUChar( nSamplingFactor )
378  .ReadUChar( nQuantizationTableDestinationSelector );
379  mnNumberOfImageComponents = nNumberOfImageComponents;
380 
381  // nSamplingFactor (lower nibble: vertical,
382  // upper nibble: horizontal) is unused
383 
384  aPixSize.setHeight( nNumberOfLines );
385  aPixSize.setWidth( nSamplesPerLine );
386  nBitsPerPixel = ( nNumberOfImageComponents == 3 ? 24 : nNumberOfImageComponents == 1 ? 8 : 0 );
387  nPlanes = 1;
388 
389  if (aMap.GetMapUnit() != MapUnit::MapPixel)
390  // We already know the DPI, but the
391  // pixel size arrived later, so do the
392  // conversion again.
394  aPixSize, aMap, MapMode(MapUnit::Map100thMM));
395 
396  bScanFinished = true;
397  }
398  break;
399  }
400  rStm.Seek( nNextMarkerPos );
401  }
402  }
403  break;
404  }
405  }
406  rStm.SetError( nError );
407  }
408  }
409  rStm.Seek( nStmPos );
410  return bRet;
411 }
412 
414 {
415  bool bRet = false;
416 
417  sal_Int32 nStmPos = rStm.Tell();
418  rStm.SetEndian( SvStreamEndian::LITTLE );
419 
420  sal_uInt32 nTemp32 = 0;
421  sal_uInt16 nTemp16 = 0;
422  sal_uInt8 cByte = 0;
423 
424  rStm.SeekRel( 2048 );
425  rStm.ReadUInt32( nTemp32 );
426  rStm.ReadUInt16( nTemp16 );
427  rStm.ReadUChar( cByte );
428 
429  if ( ( nTemp32 == 0x5f444350 ) &&
430  ( nTemp16 == 0x5049 ) &&
431  ( cByte == 0x49 ) )
432  {
434  bRet = true;
435  }
436  rStm.Seek( nStmPos );
437  return bRet;
438 }
439 
441 {
442  // ! Because 0x0a can be interpreted as LF too ...
443  // we can't be sure that this special sign represent a PCX file only.
444  // Every Ascii file is possible here :-(
445  // We must detect the whole header.
446 
447  bool bRet = false;
448  sal_uInt8 cByte = 0;
449 
450  sal_Int32 nStmPos = rStm.Tell();
451  rStm.SetEndian( SvStreamEndian::LITTLE );
452  rStm.ReadUChar( cByte );
453 
454  if ( cByte == 0x0a )
455  {
457 
458  sal_uInt16 nTemp16;
459  sal_uInt16 nXmin;
460  sal_uInt16 nXmax;
461  sal_uInt16 nYmin;
462  sal_uInt16 nYmax;
463  sal_uInt16 nDPIx;
464  sal_uInt16 nDPIy;
465 
466  rStm.SeekRel( 1 );
467 
468  // compression
469  rStm.ReadUChar( cByte );
470 
471  bRet = (cByte==0 || cByte ==1);
472  if (bRet)
473  {
474  // Bits/Pixel
475  rStm.ReadUChar( cByte );
476  nBitsPerPixel = cByte;
477 
478  // image dimensions
479  rStm.ReadUInt16( nTemp16 );
480  nXmin = nTemp16;
481  rStm.ReadUInt16( nTemp16 );
482  nYmin = nTemp16;
483  rStm.ReadUInt16( nTemp16 );
484  nXmax = nTemp16;
485  rStm.ReadUInt16( nTemp16 );
486  nYmax = nTemp16;
487 
488  aPixSize.setWidth( nXmax - nXmin + 1 );
489  aPixSize.setHeight( nYmax - nYmin + 1 );
490 
491  // resolution
492  rStm.ReadUInt16( nTemp16 );
493  nDPIx = nTemp16;
494  rStm.ReadUInt16( nTemp16 );
495  nDPIy = nTemp16;
496 
497  // set logical size
498  MapMode aMap( MapUnit::MapInch, Point(),
499  Fraction( 1, nDPIx ), Fraction( 1, nDPIy ) );
501  MapMode( MapUnit::Map100thMM ) );
502 
503  // number of color planes
504  cByte = 5; // Illegal value in case of EOF.
505  rStm.SeekRel( 49 );
506  rStm.ReadUChar( cByte );
507  nPlanes = cByte;
508 
509  bRet = (nPlanes<=4);
510  }
511  }
512 
513  rStm.Seek( nStmPos );
514  return bRet;
515 }
516 
517 bool GraphicDescriptor::ImpDetectPNG( SvStream& rStm, bool bExtendedInfo )
518 {
519  sal_uInt32 nTemp32 = 0;
520  bool bRet = false;
521 
522  sal_Int32 nStmPos = rStm.Tell();
523  rStm.SetEndian( SvStreamEndian::BIG );
524  rStm.ReadUInt32( nTemp32 );
525 
526  if ( nTemp32 == 0x89504e47 )
527  {
528  rStm.ReadUInt32( nTemp32 );
529  if ( nTemp32 == 0x0d0a1a0a )
530  {
532  bRet = true;
533 
534  if ( bExtendedInfo )
535  {
536  sal_uInt8 cByte = 0;
537 
538  // IHDR-Chunk
539  rStm.SeekRel( 8 );
540 
541  // width
542  rStm.ReadUInt32( nTemp32 );
543  aPixSize.setWidth( nTemp32 );
544 
545  // height
546  rStm.ReadUInt32( nTemp32 );
547  aPixSize.setHeight( nTemp32 );
548 
549  // Bits/Pixel
550  rStm.ReadUChar( cByte );
551  nBitsPerPixel = cByte;
552 
553  // Colour type - check whether it supports alpha values
554  sal_uInt8 cColType = 0;
555  rStm.ReadUChar( cColType );
556  bIsAlpha = bIsTransparent = ( cColType == 4 || cColType == 6 );
557 
558  // Planes always 1;
559  // compression always
560  nPlanes = 1;
561 
562  sal_uInt32 nLen32 = 0;
563  nTemp32 = 0;
564 
565  rStm.SeekRel( 7 );
566 
567  // read up to the start of the image
568  rStm.ReadUInt32( nLen32 );
569  rStm.ReadUInt32( nTemp32 );
570  while( ( nTemp32 != 0x49444154 ) && rStm.good() )
571  {
572  if ( nTemp32 == 0x70485973 ) // physical pixel dimensions
573  {
574  sal_uLong nXRes;
575  sal_uLong nYRes;
576 
577  // horizontal resolution
578  nTemp32 = 0;
579  rStm.ReadUInt32( nTemp32 );
580  nXRes = nTemp32;
581 
582  // vertical resolution
583  nTemp32 = 0;
584  rStm.ReadUInt32( nTemp32 );
585  nYRes = nTemp32;
586 
587  // unit
588  cByte = 0;
589  rStm.ReadUChar( cByte );
590 
591  if ( cByte )
592  {
593  if ( nXRes )
594  aLogSize.setWidth( (aPixSize.Width() * 100000) / nXRes );
595 
596  if ( nYRes )
597  aLogSize.setHeight( (aPixSize.Height() * 100000) / nYRes );
598  }
599 
600  nLen32 -= 9;
601  }
602  else if ( nTemp32 == 0x74524e53 ) // transparency
603  {
604  bIsTransparent = true;
605  bIsAlpha = ( cColType != 0 && cColType != 2 );
606  }
607 
608  // skip forward to next chunk
609  rStm.SeekRel( 4 + nLen32 );
610  rStm.ReadUInt32( nLen32 );
611  rStm.ReadUInt32( nTemp32 );
612  }
613  }
614  }
615  }
616  rStm.Seek( nStmPos );
617  return bRet;
618 }
619 
620 bool GraphicDescriptor::ImpDetectTIF( SvStream& rStm, bool bExtendedInfo )
621 {
622  bool bRet = false;
623  sal_uInt8 cByte1 = 0;
624  sal_uInt8 cByte2 = 1;
625 
626  sal_Int32 nStmPos = rStm.Tell();
627  rStm.ReadUChar( cByte1 );
628  rStm.ReadUChar( cByte2 );
629  if ( cByte1 == cByte2 )
630  {
631  bool bDetectOk = false;
632 
633  if ( cByte1 == 0x49 )
634  {
635  rStm.SetEndian( SvStreamEndian::LITTLE );
636  bDetectOk = true;
637  }
638  else if ( cByte1 == 0x4d )
639  {
640  rStm.SetEndian( SvStreamEndian::BIG );
641  bDetectOk = true;
642  }
643 
644  if ( bDetectOk )
645  {
646  sal_uInt16 nTemp16 = 0;
647 
648  rStm.ReadUInt16( nTemp16 );
649  if ( nTemp16 == 0x2a )
650  {
652  bRet = true;
653 
654  if ( bExtendedInfo )
655  {
656  sal_uLong nCount;
657  sal_uLong nMax = DATA_SIZE - 48;
658  sal_uInt32 nTemp32 = 0;
659 
660  // Offset of the first IFD
661  rStm.ReadUInt32( nTemp32 );
662  nCount = nTemp32 + 2;
663  rStm.SeekRel( nCount - 0x08 );
664 
665  if ( nCount < nMax )
666  {
667  bool bOk = false;
668 
669  // read tags till we find Tag256 ( Width )
670  // do not read more bytes than DATA_SIZE
671  rStm.ReadUInt16( nTemp16 );
672  while ( nTemp16 != 256 )
673  {
674  bOk = nCount < nMax;
675  if ( !bOk )
676  {
677  break;
678  }
679  rStm.SeekRel( 10 );
680  rStm.ReadUInt16( nTemp16 );
681  nCount += 12;
682  }
683 
684  if ( bOk )
685  {
686  // width
687  rStm.ReadUInt16( nTemp16 );
688  rStm.SeekRel( 4 );
689  if ( nTemp16 == 3 )
690  {
691  rStm.ReadUInt16( nTemp16 );
692  aPixSize.setWidth( nTemp16 );
693  rStm.SeekRel( 2 );
694  }
695  else
696  {
697  rStm.ReadUInt32( nTemp32 );
698  aPixSize.setWidth( nTemp32 );
699  }
700 
701  // height
702  rStm.SeekRel( 2 );
703  rStm.ReadUInt16( nTemp16 );
704  rStm.SeekRel( 4 );
705  if ( nTemp16 == 3 )
706  {
707  rStm.ReadUInt16( nTemp16 );
708  aPixSize.setHeight( nTemp16 );
709  rStm.SeekRel( 2 );
710  }
711  else
712  {
713  rStm.ReadUInt32( nTemp32 );
714  aPixSize.setHeight( nTemp32 );
715  }
716 
717  // Bits/Pixel
718  rStm.ReadUInt16( nTemp16 );
719  if ( nTemp16 == 258 )
720  {
721  rStm.SeekRel( 6 );
722  rStm.ReadUInt16( nTemp16 );
723  nBitsPerPixel = nTemp16;
724  rStm.SeekRel( 2 );
725  }
726  else
727  rStm.SeekRel( -2 );
728 
729  // compression
730  rStm.ReadUInt16( nTemp16 );
731  if ( nTemp16 == 259 )
732  {
733  rStm.SeekRel( 6 );
734  rStm.ReadUInt16( nTemp16 ); // compression
735  rStm.SeekRel( 2 );
736  }
737  else
738  rStm.SeekRel( -2 );
739  }
740  }
741  }
742  }
743  }
744  }
745  rStm.Seek( nStmPos );
746  return bRet;
747 }
748 
750 {
751  bool bRet = aPathExt.startsWith( "xbm" );
752  if (bRet)
754 
755  return bRet;
756 }
757 
759 {
760  bool bRet = aPathExt.startsWith( "xpm" );
761  if (bRet)
763 
764  return bRet;
765 }
766 
768 {
769  bool bRet = false;
770 
771  // check file extension first, as this trumps the 2 ID bytes
772  if ( aPathExt.startsWith( "pbm" ) )
773  bRet = true;
774  else
775  {
776  sal_Int32 nStmPos = rStm.Tell();
777  sal_uInt8 nFirst = 0, nSecond = 0;
778  rStm.ReadUChar( nFirst ).ReadUChar( nSecond );
779  if ( nFirst == 'P' && ( ( nSecond == '1' ) || ( nSecond == '4' ) ) )
780  bRet = true;
781  rStm.Seek( nStmPos );
782  }
783 
784  if ( bRet )
786 
787  return bRet;
788 }
789 
791 {
792  bool bRet = false;
793 
794  if ( aPathExt.startsWith( "pgm" ) )
795  bRet = true;
796  else
797  {
798  sal_uInt8 nFirst = 0, nSecond = 0;
799  sal_Int32 nStmPos = rStm.Tell();
800  rStm.ReadUChar( nFirst ).ReadUChar( nSecond );
801  if ( nFirst == 'P' && ( ( nSecond == '2' ) || ( nSecond == '5' ) ) )
802  bRet = true;
803  rStm.Seek( nStmPos );
804  }
805 
806  if ( bRet )
808 
809  return bRet;
810 }
811 
813 {
814  bool bRet = false;
815 
816  if ( aPathExt.startsWith( "ppm" ) )
817  bRet = true;
818  else
819  {
820  sal_uInt8 nFirst = 0, nSecond = 0;
821  sal_Int32 nStmPos = rStm.Tell();
822  rStm.ReadUChar( nFirst ).ReadUChar( nSecond );
823  if ( nFirst == 'P' && ( ( nSecond == '3' ) || ( nSecond == '6' ) ) )
824  bRet = true;
825  rStm.Seek( nStmPos );
826  }
827 
828  if ( bRet )
830 
831  return bRet;
832 }
833 
835 {
836  sal_uInt32 nMagicNumber = 0;
837  bool bRet = false;
838  sal_Int32 nStmPos = rStm.Tell();
839  rStm.SetEndian( SvStreamEndian::BIG );
840  rStm.ReadUInt32( nMagicNumber );
841  if ( nMagicNumber == 0x59a66a95 )
842  {
844  bRet = true;
845  }
846  rStm.Seek( nStmPos );
847  return bRet;
848 }
849 
851 {
852  bool bRet = aPathExt.startsWith( "tga" );
853  if (bRet)
855 
856  return bRet;
857 }
858 
859 bool GraphicDescriptor::ImpDetectPSD( SvStream& rStm, bool bExtendedInfo )
860 {
861  bool bRet = false;
862 
863  sal_uInt32 nMagicNumber = 0;
864  sal_Int32 nStmPos = rStm.Tell();
865  rStm.SetEndian( SvStreamEndian::BIG );
866  rStm.ReadUInt32( nMagicNumber );
867  if ( nMagicNumber == 0x38425053 )
868  {
869  sal_uInt16 nVersion = 0;
870  rStm.ReadUInt16( nVersion );
871  if ( nVersion == 1 )
872  {
873  bRet = true;
874  if ( bExtendedInfo )
875  {
876  sal_uInt16 nChannels = 0;
877  sal_uInt32 nRows = 0;
878  sal_uInt32 nColumns = 0;
879  sal_uInt16 nDepth = 0;
880  sal_uInt16 nMode = 0;
881  rStm.SeekRel( 6 ); // Pad
882  rStm.ReadUInt16( nChannels ).ReadUInt32( nRows ).ReadUInt32( nColumns ).ReadUInt16( nDepth ).ReadUInt16( nMode );
883  if ( ( nDepth == 1 ) || ( nDepth == 8 ) || ( nDepth == 16 ) )
884  {
885  nBitsPerPixel = ( nDepth == 16 ) ? 8 : nDepth;
886  switch ( nChannels )
887  {
888  case 4 :
889  case 3 :
890  nBitsPerPixel = 24;
891  [[fallthrough]];
892  case 2 :
893  case 1 :
894  aPixSize.setWidth( nColumns );
895  aPixSize.setHeight( nRows );
896  break;
897  default:
898  bRet = false;
899  }
900  }
901  else
902  bRet = false;
903  }
904  }
905  }
906 
907  if ( bRet )
909  rStm.Seek( nStmPos );
910  return bRet;
911 }
912 
914 {
915  // check the EPS preview and the file extension
916  sal_uInt32 nFirstLong = 0;
917  sal_uInt8 nFirstBytes[20] = {};
918  bool bRet = false;
919 
920  sal_Int32 nStmPos = rStm.Tell();
921  rStm.SetEndian( SvStreamEndian::BIG );
922  rStm.ReadUInt32( nFirstLong );
923  rStm.SeekRel( -4 );
924  rStm.ReadBytes( &nFirstBytes, 20 );
925 
926  if ( ( nFirstLong == 0xC5D0D3C6 ) || aPathExt.startsWith( "eps" ) ||
927  ( ImplSearchEntry( nFirstBytes, reinterpret_cast<sal_uInt8 const *>("%!PS-Adobe"), 10, 10 )
928  && ImplSearchEntry( &nFirstBytes[15], reinterpret_cast<sal_uInt8 const *>("EPS"), 3, 3 ) ) )
929  {
931  bRet = true;
932  }
933  rStm.Seek( nStmPos );
934  return bRet;
935 }
936 
938 {
939  bool bRet = aPathExt.startsWith( "dxf" );
940  if (bRet)
942 
943  return bRet;
944 }
945 
947 {
948  bool bRet = aPathExt.startsWith( "met" );
949  if (bRet)
951 
952  return bRet;
953 }
954 
956 {
957  bool bRet = aPathExt.startsWith( "pct" );
958  if (bRet)
960  else
961  {
962  sal_uInt64 const nStreamPos = rStm.Tell();
963  sal_uInt64 const nStreamLen = rStm.remainingSize();
964  if (isPCT(rStm, nStreamPos, nStreamLen))
965  {
966  bRet = true;
968  }
969  rStm.Seek(nStreamPos);
970  }
971 
972  return bRet;
973 }
974 
975 bool GraphicDescriptor::ImpDetectSVM( SvStream& rStm, bool bExtendedInfo )
976 {
977  sal_uInt32 n32 = 0;
978  bool bRet = false;
979  sal_uInt8 cByte = 0;
980 
981  sal_Int32 nStmPos = rStm.Tell();
982  rStm.SetEndian( SvStreamEndian::LITTLE );
983  rStm.ReadUInt32( n32 );
984  if ( n32 == 0x44475653 )
985  {
986  cByte = 0;
987  rStm.ReadUChar( cByte );
988  if ( cByte == 0x49 )
989  {
991  bRet = true;
992 
993  if ( bExtendedInfo )
994  {
995  sal_uInt32 nTemp32;
996  sal_uInt16 nTemp16;
997 
998  rStm.SeekRel( 0x04 );
999 
1000  // width
1001  nTemp32 = 0;
1002  rStm.ReadUInt32( nTemp32 );
1003  aLogSize.setWidth( nTemp32 );
1004 
1005  // height
1006  nTemp32 = 0;
1007  rStm.ReadUInt32( nTemp32 );
1008  aLogSize.setHeight( nTemp32 );
1009 
1010  // read MapUnit and determine PrefSize
1011  nTemp16 = 0;
1012  rStm.ReadUInt16( nTemp16 );
1014  MapMode( static_cast<MapUnit>(nTemp16) ),
1015  MapMode( MapUnit::Map100thMM ) );
1016  }
1017  }
1018  }
1019  else
1020  {
1021  rStm.SeekRel( -4 );
1022  n32 = 0;
1023  rStm.ReadUInt32( n32 );
1024 
1025  if( n32 == 0x4D4C4356 )
1026  {
1027  sal_uInt16 nTmp16 = 0;
1028 
1029  rStm.ReadUInt16( nTmp16 );
1030 
1031  if( nTmp16 == 0x4654 )
1032  {
1034  bRet = true;
1035 
1036  if( bExtendedInfo )
1037  {
1038  MapMode aMapMode;
1039 
1040  rStm.SeekRel( 0x06 );
1041  ReadMapMode( rStm, aMapMode );
1042  TypeSerializer aSerializer(rStm);
1043  aSerializer.readSize(aLogSize);
1044  aLogSize = OutputDevice::LogicToLogic( aLogSize, aMapMode, MapMode( MapUnit::Map100thMM ) );
1045  }
1046  }
1047  }
1048  }
1049  rStm.Seek( nStmPos );
1050  return bRet;
1051 }
1052 
1054 {
1055  bool bRet = aPathExt.startsWith( "wmf" );
1056  if (bRet)
1058 
1059  return bRet;
1060 }
1061 
1062 bool GraphicDescriptor::ImpDetectEMF( SvStream& rStm, bool bExtendedInfo )
1063 {
1064  sal_uInt32 nRecordType = 0;
1065  bool bRet = false;
1066 
1067  sal_Int32 nStmPos = rStm.Tell();
1068  rStm.SetEndian( SvStreamEndian::LITTLE );
1069  rStm.ReadUInt32( nRecordType );
1070 
1071  if ( nRecordType == 0x00000001 )
1072  {
1073  sal_uInt32 nHeaderSize = 0;
1074  sal_Int32 nBoundLeft = 0, nBoundTop = 0, nBoundRight = 0, nBoundBottom = 0;
1075  sal_Int32 nFrameLeft = 0, nFrameTop = 0, nFrameRight = 0, nFrameBottom = 0;
1076  sal_uInt32 nSignature = 0;
1077 
1078  rStm.ReadUInt32( nHeaderSize );
1079  rStm.ReadInt32( nBoundLeft );
1080  rStm.ReadInt32( nBoundTop );
1081  rStm.ReadInt32( nBoundRight );
1082  rStm.ReadInt32( nBoundBottom );
1083  rStm.ReadInt32( nFrameLeft );
1084  rStm.ReadInt32( nFrameTop );
1085  rStm.ReadInt32( nFrameRight );
1086  rStm.ReadInt32( nFrameBottom );
1087  rStm.ReadUInt32( nSignature );
1088 
1089  if ( nSignature == 0x464d4520 )
1090  {
1092  bRet = true;
1093 
1094  if ( bExtendedInfo )
1095  {
1096  // size in pixels
1097  aPixSize.setWidth( nBoundRight - nBoundLeft + 1 );
1098  aPixSize.setHeight( nBoundBottom - nBoundTop + 1 );
1099 
1100  // size in 0.01mm units
1101  aLogSize.setWidth( nFrameRight - nFrameLeft + 1 );
1102  aLogSize.setHeight( nFrameBottom - nFrameTop + 1 );
1103  }
1104  }
1105  }
1106 
1107  rStm.Seek( nStmPos );
1108  return bRet;
1109 }
1110 
1111 bool GraphicDescriptor::ImpDetectSVG( SvStream& /*rStm*/, bool /*bExtendedInfo*/ )
1112 {
1113  bool bRet = aPathExt.startsWith( "svg" );
1114  if (bRet)
1116 
1117  return bRet;
1118 }
1119 
1121 {
1122  const char *pKeyName = nullptr;
1123 
1124  switch( nFormat )
1125  {
1126  case GraphicFileFormat::BMP : pKeyName = "bmp"; break;
1127  case GraphicFileFormat::GIF : pKeyName = "gif"; break;
1128  case GraphicFileFormat::JPG : pKeyName = "jpg"; break;
1129  case GraphicFileFormat::PCD : pKeyName = "pcd"; break;
1130  case GraphicFileFormat::PCX : pKeyName = "pcx"; break;
1131  case GraphicFileFormat::PNG : pKeyName = "png"; break;
1132  case GraphicFileFormat::XBM : pKeyName = "xbm"; break;
1133  case GraphicFileFormat::XPM : pKeyName = "xpm"; break;
1134  case GraphicFileFormat::PBM : pKeyName = "pbm"; break;
1135  case GraphicFileFormat::PGM : pKeyName = "pgm"; break;
1136  case GraphicFileFormat::PPM : pKeyName = "ppm"; break;
1137  case GraphicFileFormat::RAS : pKeyName = "ras"; break;
1138  case GraphicFileFormat::TGA : pKeyName = "tga"; break;
1139  case GraphicFileFormat::PSD : pKeyName = "psd"; break;
1140  case GraphicFileFormat::EPS : pKeyName = "eps"; break;
1141  case GraphicFileFormat::TIF : pKeyName = "tif"; break;
1142  case GraphicFileFormat::DXF : pKeyName = "dxf"; break;
1143  case GraphicFileFormat::MET : pKeyName = "met"; break;
1144  case GraphicFileFormat::PCT : pKeyName = "pct"; break;
1145  case GraphicFileFormat::SVM : pKeyName = "svm"; break;
1146  case GraphicFileFormat::WMF : pKeyName = "wmf"; break;
1147  case GraphicFileFormat::EMF : pKeyName = "emf"; break;
1148  case GraphicFileFormat::SVG : pKeyName = "svg"; break;
1149  default: assert(false);
1150  }
1151 
1152  return OUString::createFromAscii(pKeyName);
1153 }
1154 
1155 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
GraphicDescriptor(const GraphicDescriptor &)=delete
bool ImpDetectPCX(SvStream &rStm)
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1674
long Height() const
sal_uIntPtr sal_uLong
bool ImpDetectEMF(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectBMP(SvStream &rStm, bool bExtendedInfo)
bool isPCT(SvStream &rStream, sal_uLong nStreamPos, sal_uLong nStreamLen)
sal_uInt64 Seek(sal_uInt64 nPos)
bool ImpDetectMET(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectPSD(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectGIF(SvStream &rStm, bool bExtendedInfo)
sal_uInt64 SeekRel(sal_Int64 nPos)
bool ImpDetectPBM(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectPGM(SvStream &rStm, bool bExtendedInfo)
static sal_uInt8 ImpDetectJPG_GetNextMarker(SvStream &rStm)
bool ImpDetectPCD(SvStream &rStm, bool bExtendedInfo)
ErrCode GetError() const
sal_uInt8 mnNumberOfImageComponents
sal_uInt8 * ImplSearchEntry(sal_uInt8 *pSource, sal_uInt8 const *pDest, sal_uLong nComp, sal_uLong nSize)
bool ImpDetectTGA(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectPPM(SvStream &rStm, bool bExtendedInfo)
sal_uInt64 remainingSize()
void readSize(Size &rSize)
bool ImpDetectEPS(SvStream &rStm, bool bExtendedInfo)
void SetMapUnit(MapUnit eUnit)
Definition: mapmod.cxx:97
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
bool ImpDetectDXF(SvStream &rStm, bool bExtendedInfo)
NONE
static OUString GetImportFormatShortName(GraphicFileFormat nFormat)
void SetScaleX(const Fraction &rScaleX)
Definition: mapmod.cxx:108
bool ImpDetectPCT(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectXBM(SvStream &rStm, bool bExtendedInfo)
StreamMode
#define DATA_SIZE
void SetScaleY(const Fraction &rScaleY)
Definition: mapmod.cxx:115
void SetError(ErrCode nErrorCode)
SvStream & ReadUChar(unsigned char &rChar)
MapUnit GetMapUnit() const
Definition: mapmod.cxx:168
bool ImpDetectWMF(SvStream &rStm, bool bExtendedInfo)
GraphicFileFormat
SvStream & ReadInt32(sal_Int32 &rInt32)
uno::Reference< io::XStream > CreateStream(uno::Reference< embed::XStorage > const &xStorage, OUString const &rFilename)
std::size_t ReadBytes(void *pData, std::size_t nSize)
SvStreamEndian GetEndian() const
bool ImpDetectSVM(SvStream &rStm, bool bExtendedInfo)
unsigned char sal_uInt8
GraphicFileFormat nFormat
bool ImpDetectJPG(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectRAS(SvStream &rStm, bool bExtendedInfo)
void SetEndian(SvStreamEndian SvStreamEndian)
OUString GetFileExtension() const
sal_uInt64 Tell() const
bool ImpDetectXPM(SvStream &rStm, bool bExtendedInfo)
bool good() const
bool ImpDetectTIF(SvStream &rStm, bool bExtendedInfo)
SvStreamEndian
SvStream & ReadMapMode(SvStream &rIStm, MapMode &rMapMode)
Definition: mapmod.cxx:136
bool ImpDetectSVG(SvStream &rStm, bool bExtendedInfo)
bool ImpDetectPNG(SvStream &rStm, bool bExtendedInfo)
sal_Int32 const nLength
bool Detect(bool bExtendedInfo=false)
starts the detection
sal_uInt16 nBitsPerPixel
void setWidth(long nWidth)
READ
void setHeight(long nHeight)