Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / vcl / source / filter / graphicfilter2.cxx
blob352e4de56c9695b85ad23f35e2b1707d3163434d
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 .
21 #include <string.h>
22 #include <stdio.h>
23 #include <tools/stream.hxx>
24 #include <vcl/outdev.hxx>
25 #include <vcl/graphicfilter.hxx>
26 #include <unotools/ucbstreamhelper.hxx>
28 #define DATA_SIZE 640
30 sal_uInt8* ImplSearchEntry( sal_uInt8* , sal_uInt8* , sal_uLong , sal_uLong );
32 GraphicDescriptor::GraphicDescriptor( const INetURLObject& rPath ) :
33 pFileStm( ::utl::UcbStreamHelper::CreateStream( rPath.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ ) ),
34 aPathExt( rPath.GetFileExtension().toAsciiLowerCase() ),
35 bOwnStream( sal_True )
37 ImpConstruct();
40 GraphicDescriptor::GraphicDescriptor( SvStream& rInStream, const OUString* pPath) :
41 pFileStm ( &rInStream ),
42 bOwnStream ( sal_False )
44 ImpConstruct();
46 if ( pPath )
48 INetURLObject aURL( *pPath );
49 aPathExt = aURL.GetFileExtension().toAsciiLowerCase();
53 GraphicDescriptor::~GraphicDescriptor()
55 if ( bOwnStream )
56 delete pFileStm;
59 sal_Bool GraphicDescriptor::Detect( sal_Bool bExtendedInfo )
61 sal_Bool bRet = sal_False;
62 if ( pFileStm && !pFileStm->GetError() )
64 SvStream& rStm = *pFileStm;
65 sal_uInt16 nOldFormat = rStm.GetNumberFormatInt();
67 if ( ImpDetectGIF( rStm, bExtendedInfo ) ) bRet = sal_True;
68 else if ( ImpDetectJPG( rStm, bExtendedInfo ) ) bRet = sal_True;
69 else if ( ImpDetectBMP( rStm, bExtendedInfo ) ) bRet = sal_True;
70 else if ( ImpDetectPNG( rStm, bExtendedInfo ) ) bRet = sal_True;
71 else if ( ImpDetectTIF( rStm, bExtendedInfo ) ) bRet = sal_True;
72 else if ( ImpDetectPCX( rStm, bExtendedInfo ) ) bRet = sal_True;
73 else if ( ImpDetectDXF( rStm, bExtendedInfo ) ) bRet = sal_True;
74 else if ( ImpDetectMET( rStm, bExtendedInfo ) ) bRet = sal_True;
75 else if ( ImpDetectSGF( rStm, bExtendedInfo ) ) bRet = sal_True;
76 else if ( ImpDetectSGV( rStm, bExtendedInfo ) ) bRet = sal_True;
77 else if ( ImpDetectSVM( rStm, bExtendedInfo ) ) bRet = sal_True;
78 else if ( ImpDetectWMF( rStm, bExtendedInfo ) ) bRet = sal_True;
79 else if ( ImpDetectEMF( rStm, bExtendedInfo ) ) bRet = sal_True;
80 else if ( ImpDetectSVG( rStm, bExtendedInfo ) ) bRet = sal_True;
81 else if ( ImpDetectPCT( rStm, bExtendedInfo ) ) bRet = sal_True;
82 else if ( ImpDetectXBM( rStm, bExtendedInfo ) ) bRet = sal_True;
83 else if ( ImpDetectXPM( rStm, bExtendedInfo ) ) bRet = sal_True;
84 else if ( ImpDetectPBM( rStm, bExtendedInfo ) ) bRet = sal_True;
85 else if ( ImpDetectPGM( rStm, bExtendedInfo ) ) bRet = sal_True;
86 else if ( ImpDetectPPM( rStm, bExtendedInfo ) ) bRet = sal_True;
87 else if ( ImpDetectRAS( rStm, bExtendedInfo ) ) bRet = sal_True;
88 else if ( ImpDetectTGA( rStm, bExtendedInfo ) ) bRet = sal_True;
89 else if ( ImpDetectPSD( rStm, bExtendedInfo ) ) bRet = sal_True;
90 else if ( ImpDetectEPS( rStm, bExtendedInfo ) ) bRet = sal_True;
91 else if ( ImpDetectPCD( rStm, bExtendedInfo ) ) bRet = sal_True;
93 rStm.SetNumberFormatInt( nOldFormat );
95 return bRet;
98 void GraphicDescriptor::ImpConstruct()
100 nFormat = GFF_NOT;
101 nBitsPerPixel = 0;
102 nPlanes = 0;
103 bCompressed = sal_False;
106 sal_Bool GraphicDescriptor::ImpDetectBMP( SvStream& rStm, sal_Bool bExtendedInfo )
108 sal_uInt16 nTemp16 = 0;
109 sal_Bool bRet = sal_False;
110 sal_Int32 nStmPos = rStm.Tell();
112 rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
113 rStm >> nTemp16;
115 // OS/2-BitmapArray
116 if ( nTemp16 == 0x4142 )
118 rStm.SeekRel( 0x0c );
119 rStm >> nTemp16;
122 // Bitmap
123 if ( nTemp16 == 0x4d42 )
125 nFormat = GFF_BMP;
126 bRet = sal_True;
128 if ( bExtendedInfo )
130 sal_uInt32 nTemp32;
131 sal_uInt32 nCompression;
133 // up to first info
134 rStm.SeekRel( 0x10 );
136 // Pixel width
137 rStm >> nTemp32;
138 aPixSize.Width() = nTemp32;
140 // Pixel height
141 rStm >> nTemp32;
142 aPixSize.Height() = nTemp32;
144 // Planes
145 rStm >> nTemp16;
146 nPlanes = nTemp16;
148 // BitCount
149 rStm >> nTemp16;
150 nBitsPerPixel = nTemp16;
152 // Compression
153 rStm >> nTemp32;
154 bCompressed = ( ( nCompression = nTemp32 ) > 0 );
156 // logical width
157 rStm.SeekRel( 4 );
158 rStm >> nTemp32;
159 if ( nTemp32 )
160 aLogSize.Width() = ( aPixSize.Width() * 100000 ) / nTemp32;
162 // logical height
163 rStm >> nTemp32;
164 if ( nTemp32 )
165 aLogSize.Height() = ( aPixSize.Height() * 100000 ) / nTemp32;
167 // further validation, check for rational values
168 if ( ( nBitsPerPixel > 24 ) || ( nCompression > 3 ) )
170 nFormat = GFF_NOT;
171 bRet = sal_False;
175 rStm.Seek( nStmPos );
176 return bRet;
179 sal_Bool GraphicDescriptor::ImpDetectGIF( SvStream& rStm, sal_Bool bExtendedInfo )
181 sal_uInt32 n32 = 0;
182 sal_uInt16 n16 = 0;
183 sal_Bool bRet = sal_False;
184 sal_uInt8 cByte = 0;
186 sal_Int32 nStmPos = rStm.Tell();
187 rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
188 rStm >> n32;
190 if ( n32 == 0x38464947 )
192 rStm >> n16;
193 if ( ( n16 == 0x6137 ) || ( n16 == 0x6139 ) )
195 nFormat = GFF_GIF;
196 bRet = sal_True;
198 if ( bExtendedInfo )
200 sal_uInt16 nTemp16 = 0;
202 // Pixel width
203 rStm >> nTemp16;
204 aPixSize.Width() = nTemp16;
206 // Pixel height
207 rStm >> nTemp16;
208 aPixSize.Height() = nTemp16;
210 // Bits/Pixel
211 rStm >> cByte;
212 nBitsPerPixel = ( ( cByte & 112 ) >> 4 ) + 1;
216 rStm.Seek( nStmPos );
217 return bRet;
220 // returns the next jpeg marker, a return value of 0 represents an error
221 sal_uInt8 ImpDetectJPG_GetNextMarker( SvStream& rStm )
223 sal_uInt8 nByte;
228 rStm >> nByte;
229 if ( rStm.IsEof() || rStm.GetError() ) // as 0 is not allowed as marker,
230 return 0; // we can use it as errorcode
232 while ( nByte != 0xff );
235 rStm >> nByte;
236 if ( rStm.IsEof() || rStm.GetError() )
237 return 0;
239 while( nByte == 0xff );
241 while( nByte == 0 ); // 0xff00 represents 0xff and not a marker,
242 // the marker detection has to be restartet.
243 return nByte;
246 sal_Bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm, sal_Bool bExtendedInfo )
248 sal_uInt32 nTemp32 = 0;
249 sal_Bool bRet = sal_False;
251 sal_Int32 nStmPos = rStm.Tell();
253 rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
254 rStm >> nTemp32;
256 // compare upper 24 bits
257 if( 0xffd8ff00 == ( nTemp32 & 0xffffff00 ) )
259 nFormat = GFF_JPG;
260 bRet = sal_True;
262 if ( bExtendedInfo )
264 rStm.SeekRel( -2 );
266 sal_uInt32 nError( rStm.GetError() );
268 bool bScanFailure = false;
269 bool bScanFinished = false;
271 while( !bScanFailure && !bScanFinished && !rStm.IsEof() && !rStm.GetError() )
273 sal_uInt8 nMarker = ImpDetectJPG_GetNextMarker( rStm );
274 switch( nMarker )
276 // fixed size marker, not having a two byte length parameter
277 case 0xd0 : // RST0
278 case 0xd1 :
279 case 0xd2 :
280 case 0xd3 :
281 case 0xd4 :
282 case 0xd5 :
283 case 0xd6 :
284 case 0xd7 : // RST7
285 case 0x01 : // TEM
286 break;
288 case 0xd8 : // SOI (has already been checked, there should not be a second one)
289 case 0x00 : // marker is invalid, we should stop now
290 bScanFailure = true;
291 break;
293 case 0xd9 : // EOI
294 bScanFinished = true;
295 break;
297 // per default we assume marker segments conaining a length parameter
298 default :
300 sal_uInt16 nLength = 0;
301 rStm >> nLength;
303 if ( nLength < 2 )
304 bScanFailure = true;
305 else
307 sal_uInt32 nNextMarkerPos = rStm.Tell() + nLength - 2;
308 switch( nMarker )
310 case 0xe0 : // APP0 Marker
312 if ( nLength == 16 )
314 sal_Int32 nIdentifier = 0;
315 rStm >> nIdentifier;
316 if ( nIdentifier == 0x4a464946 ) // JFIF Identifier
318 sal_uInt8 nStringTerminator = 0;
319 sal_uInt8 nMajorRevision = 0;
320 sal_uInt8 nMinorRevision = 0;
321 sal_uInt8 nUnits = 0;
322 sal_uInt16 nHorizontalResolution = 0;
323 sal_uInt16 nVerticalResolution = 0;
324 sal_uInt8 nHorzThumbnailPixelCount = 0;
325 sal_uInt8 nVertThumbnailPixelCount = 0;
327 rStm >> nStringTerminator
328 >> nMajorRevision
329 >> nMinorRevision
330 >> nUnits
331 >> nHorizontalResolution
332 >> nVerticalResolution
333 >> nHorzThumbnailPixelCount
334 >> nVertThumbnailPixelCount;
336 // setting the logical size
337 if ( nUnits && nHorizontalResolution && nVerticalResolution )
339 MapMode aMap;
340 aMap.SetMapUnit( nUnits == 1 ? MAP_INCH : MAP_CM );
341 aMap.SetScaleX( Fraction( 1, nHorizontalResolution ) );
342 aMap.SetScaleY( Fraction( 1, nVerticalResolution ) );
343 aLogSize = OutputDevice::LogicToLogic( aPixSize, aMap, MapMode( MAP_100TH_MM ) );
348 break;
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
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 nHorizontalSamplingFactor = 0;
371 sal_uInt8 nQuantizationTableDestinationSelector = 0;
372 rStm >> nSamplePrecision
373 >> nNumberOfLines
374 >> nSamplesPerLine
375 >> nNumberOfImageComponents
376 >> nComponentsIdentifier
377 >> nHorizontalSamplingFactor
378 >> nQuantizationTableDestinationSelector;
379 nHorizontalSamplingFactor >>= 4;
381 aPixSize.Height() = nNumberOfLines;
382 aPixSize.Width() = nSamplesPerLine;
383 nBitsPerPixel = ( nNumberOfImageComponents == 3 ? 24 : nNumberOfImageComponents == 1 ? 8 : 0 );
384 nPlanes = 1;
386 bScanFinished = true;
388 break;
390 rStm.Seek( nNextMarkerPos );
393 break;
396 rStm.SetError( nError );
399 rStm.Seek( nStmPos );
400 return bRet;
403 sal_Bool GraphicDescriptor::ImpDetectPCD( SvStream& rStm, sal_Bool )
405 sal_Bool bRet = sal_False;
407 sal_Int32 nStmPos = rStm.Tell();
408 rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
410 sal_uInt32 nTemp32 = 0;
411 sal_uInt16 nTemp16 = 0;
412 sal_uInt8 cByte = 0;
414 rStm.SeekRel( 2048 );
415 rStm >> nTemp32;
416 rStm >> nTemp16;
417 rStm >> cByte;
419 if ( ( nTemp32 == 0x5f444350 ) &&
420 ( nTemp16 == 0x5049 ) &&
421 ( cByte == 0x49 ) )
423 nFormat = GFF_PCD;
424 bRet = sal_True;
426 rStm.Seek( nStmPos );
427 return bRet;
430 sal_Bool GraphicDescriptor::ImpDetectPCX( SvStream& rStm, sal_Bool bExtendedInfo )
432 // ! Because 0x0a can be interpreted as LF too ...
433 // we cant be sure that this special sign represent a PCX file only.
434 // Every Ascii file is possible here :-(
435 // We must detect the whole header.
436 bExtendedInfo = sal_True;
438 sal_Bool bRet = sal_False;
439 sal_uInt8 cByte = 0;
441 sal_Int32 nStmPos = rStm.Tell();
442 rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
443 rStm >> cByte;
445 if ( cByte == 0x0a )
447 nFormat = GFF_PCX;
448 bRet = sal_True;
450 if ( bExtendedInfo )
452 sal_uInt16 nTemp16;
453 sal_uInt16 nXmin;
454 sal_uInt16 nXmax;
455 sal_uInt16 nYmin;
456 sal_uInt16 nYmax;
457 sal_uInt16 nDPIx;
458 sal_uInt16 nDPIy;
461 rStm.SeekRel( 1 );
463 // compression
464 rStm >> cByte;
465 bCompressed = ( cByte > 0 );
467 bRet = (cByte==0 || cByte ==1);
468 if (bRet)
470 // Bits/Pixel
471 rStm >> cByte;
472 nBitsPerPixel = cByte;
474 // image dimensions
475 rStm >> nTemp16;
476 nXmin = nTemp16;
477 rStm >> nTemp16;
478 nYmin = nTemp16;
479 rStm >> nTemp16;
480 nXmax = nTemp16;
481 rStm >> nTemp16;
482 nYmax = nTemp16;
484 aPixSize.Width() = nXmax - nXmin + 1;
485 aPixSize.Height() = nYmax - nYmin + 1;
487 // resolution
488 rStm >> nTemp16;
489 nDPIx = nTemp16;
490 rStm >> nTemp16;
491 nDPIy = nTemp16;
493 // set logical size
494 MapMode aMap( MAP_INCH, Point(),
495 Fraction( 1, nDPIx ), Fraction( 1, nDPIy ) );
496 aLogSize = OutputDevice::LogicToLogic( aPixSize, aMap,
497 MapMode( MAP_100TH_MM ) );
499 // number of color planes
500 cByte = 5; // Illegal value in case of EOF.
501 rStm.SeekRel( 49 );
502 rStm >> cByte;
503 nPlanes = cByte;
505 bRet = (nPlanes<=4);
510 rStm.Seek( nStmPos );
511 return bRet;
514 sal_Bool GraphicDescriptor::ImpDetectPNG( SvStream& rStm, sal_Bool bExtendedInfo )
516 sal_uInt32 nTemp32 = 0;
517 sal_Bool bRet = sal_False;
519 sal_Int32 nStmPos = rStm.Tell();
520 rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
521 rStm >> nTemp32;
523 if ( nTemp32 == 0x89504e47 )
525 rStm >> nTemp32;
526 if ( nTemp32 == 0x0d0a1a0a )
528 nFormat = GFF_PNG;
529 bRet = sal_True;
531 if ( bExtendedInfo )
533 sal_uInt8 cByte = 0;
535 // IHDR-Chunk
536 rStm.SeekRel( 8 );
538 // width
539 rStm >> nTemp32;
540 aPixSize.Width() = nTemp32;
542 // height
543 rStm >> nTemp32;
544 aPixSize.Height() = nTemp32;
546 // Bits/Pixel
547 rStm >> cByte;
548 nBitsPerPixel = cByte;
550 // Planes always 1;
551 // compression always
552 nPlanes = 1;
553 bCompressed = sal_True;
555 sal_uInt32 nLen32 = 0;
556 nTemp32 = 0;
558 rStm.SeekRel( 8 );
560 // read up to the pHYs-Chunk or the start of the image
561 rStm >> nLen32;
562 rStm >> nTemp32;
563 while( ( nTemp32 != 0x70485973 ) && ( nTemp32 != 0x49444154 )
564 && !rStm.IsEof() && !rStm.GetError() )
566 rStm.SeekRel( 4 + nLen32 );
567 rStm >> nLen32;
568 rStm >> nTemp32;
571 if ( nTemp32 == 0x70485973
572 && !rStm.IsEof() && !rStm.GetError() )
574 sal_uLong nXRes;
575 sal_uLong nYRes;
577 // horizontal resolution
578 nTemp32 = 0;
579 rStm >> nTemp32;
580 nXRes = nTemp32;
582 // vertical resolution
583 nTemp32 = 0;
584 rStm >> nTemp32;
585 nYRes = nTemp32;
587 // unit
588 cByte = 0;
589 rStm >> cByte;
591 if ( cByte )
593 if ( nXRes )
594 aLogSize.Width() = ( aPixSize.Width() * 100000 ) /
595 nTemp32;
597 if ( nYRes )
598 aLogSize.Height() = ( aPixSize.Height() * 100000 ) /
599 nTemp32;
605 rStm.Seek( nStmPos );
606 return bRet;
609 sal_Bool GraphicDescriptor::ImpDetectTIF( SvStream& rStm, sal_Bool bExtendedInfo )
611 bool bDetectOk = false;
612 sal_Bool bRet = sal_False;
613 sal_uInt8 cByte1 = 0;
614 sal_uInt8 cByte2 = 1;
616 sal_Int32 nStmPos = rStm.Tell();
617 rStm >> cByte1;
618 rStm >> cByte2;
619 if ( cByte1 == cByte2 )
621 if ( cByte1 == 0x49 )
623 rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
624 bDetectOk = true;
626 else if ( cByte1 == 0x4d )
628 rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
629 bDetectOk = true;
632 if ( bDetectOk )
634 sal_uInt16 nTemp16 = 0;
636 rStm >> nTemp16;
637 if ( nTemp16 == 0x2a )
639 nFormat = GFF_TIF;
640 bRet = sal_True;
642 if ( bExtendedInfo )
644 sal_uLong nCount;
645 sal_uLong nMax = DATA_SIZE - 48;
646 sal_uInt32 nTemp32 = 0;
647 bool bOk = false;
649 // Offset of the first IFD
650 rStm >> nTemp32;
651 rStm.SeekRel( ( nCount = ( nTemp32 + 2 ) ) - 0x08 );
653 if ( nCount < nMax )
655 // read tags till we find Tag256 ( Width )
656 // do not read more bytes than DATA_SIZE
657 rStm >> nTemp16;
658 while ( nTemp16 != 256 )
660 bOk = nCount < nMax;
661 if ( !bOk )
663 break;
665 rStm.SeekRel( 10 );
666 rStm >> nTemp16;
667 nCount += 12;
670 if ( bOk )
672 // width
673 rStm >> nTemp16;
674 rStm.SeekRel( 4 );
675 if ( nTemp16 == 3 )
677 rStm >> nTemp16;
678 aPixSize.Width() = nTemp16;
679 rStm.SeekRel( 2 );
681 else
683 rStm >> nTemp32;
684 aPixSize.Width() = nTemp32;
686 nCount += 12;
688 // height
689 rStm.SeekRel( 2 );
690 rStm >> nTemp16;
691 rStm.SeekRel( 4 );
692 if ( nTemp16 == 3 )
694 rStm >> nTemp16;
695 aPixSize.Height() = nTemp16;
696 rStm.SeekRel( 2 );
698 else
700 rStm >> nTemp32;
701 aPixSize.Height() = nTemp32;
703 nCount += 12;
705 // Bits/Pixel
706 rStm >> nTemp16;
707 if ( nTemp16 == 258 )
709 rStm.SeekRel( 6 );
710 rStm >> nTemp16;
711 nBitsPerPixel = nTemp16;
712 rStm.SeekRel( 2 );
713 nCount += 12;
715 else
716 rStm.SeekRel( -2 );
718 // compression
719 rStm >> nTemp16;
720 if ( nTemp16 == 259 )
722 rStm.SeekRel( 6 );
723 rStm >> nTemp16;
724 bCompressed = ( nTemp16 > 1 );
725 rStm.SeekRel( 2 );
726 nCount += 12;
728 else
729 rStm.SeekRel( -2 );
736 rStm.Seek( nStmPos );
737 return bRet;
740 sal_Bool GraphicDescriptor::ImpDetectXBM( SvStream&, sal_Bool )
742 sal_Bool bRet = aPathExt.startsWith( "xbm" );
743 if (bRet)
744 nFormat = GFF_XBM;
746 return bRet;
749 sal_Bool GraphicDescriptor::ImpDetectXPM( SvStream&, sal_Bool )
751 sal_Bool bRet = aPathExt.startsWith( "xpm" );
752 if (bRet)
753 nFormat = GFF_XPM;
755 return bRet;
758 sal_Bool GraphicDescriptor::ImpDetectPBM( SvStream& rStm, sal_Bool )
760 sal_Bool bRet = sal_False;
762 // check file extension first, as this trumps the 2 ID bytes
763 if ( aPathExt.startsWith( "pbm" ) )
764 bRet = sal_True;
765 else
767 sal_Int32 nStmPos = rStm.Tell();
768 sal_uInt8 nFirst = 0, nSecond = 0;
769 rStm >> nFirst >> nSecond;
770 if ( nFirst == 'P' && ( ( nSecond == '1' ) || ( nSecond == '4' ) ) )
771 bRet = sal_True;
772 rStm.Seek( nStmPos );
775 if ( bRet )
776 nFormat = GFF_PBM;
778 return bRet;
781 sal_Bool GraphicDescriptor::ImpDetectPGM( SvStream& rStm, sal_Bool )
783 sal_Bool bRet = sal_False;
785 if ( aPathExt.startsWith( "pgm" ) )
786 bRet = sal_True;
787 else
789 sal_uInt8 nFirst = 0, nSecond = 0;
790 sal_Int32 nStmPos = rStm.Tell();
791 rStm >> nFirst >> nSecond;
792 if ( nFirst == 'P' && ( ( nSecond == '2' ) || ( nSecond == '5' ) ) )
793 bRet = sal_True;
794 rStm.Seek( nStmPos );
797 if ( bRet )
798 nFormat = GFF_PGM;
800 return bRet;
803 sal_Bool GraphicDescriptor::ImpDetectPPM( SvStream& rStm, sal_Bool )
805 sal_Bool bRet = sal_False;
807 if ( aPathExt.startsWith( "ppm" ) )
808 bRet = sal_True;
809 else
811 sal_uInt8 nFirst = 0, nSecond = 0;
812 sal_Int32 nStmPos = rStm.Tell();
813 rStm >> nFirst >> nSecond;
814 if ( nFirst == 'P' && ( ( nSecond == '3' ) || ( nSecond == '6' ) ) )
815 bRet = sal_True;
816 rStm.Seek( nStmPos );
819 if ( bRet )
820 nFormat = GFF_PPM;
822 return bRet;
825 sal_Bool GraphicDescriptor::ImpDetectRAS( SvStream& rStm, sal_Bool )
827 sal_uInt32 nMagicNumber = 0;
828 sal_Bool bRet = sal_False;
829 sal_Int32 nStmPos = rStm.Tell();
830 rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
831 rStm >> nMagicNumber;
832 if ( nMagicNumber == 0x59a66a95 )
834 nFormat = GFF_RAS;
835 bRet = sal_True;
837 rStm.Seek( nStmPos );
838 return bRet;
841 sal_Bool GraphicDescriptor::ImpDetectTGA( SvStream&, sal_Bool )
843 sal_Bool bRet = aPathExt.startsWith( "tga" );
844 if (bRet)
845 nFormat = GFF_TGA;
847 return bRet;
850 sal_Bool GraphicDescriptor::ImpDetectPSD( SvStream& rStm, sal_Bool bExtendedInfo )
852 sal_Bool bRet = sal_False;
854 sal_uInt32 nMagicNumber = 0;
855 sal_Int32 nStmPos = rStm.Tell();
856 rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
857 rStm >> nMagicNumber;
858 if ( nMagicNumber == 0x38425053 )
860 sal_uInt16 nVersion = 0;
861 rStm >> nVersion;
862 if ( nVersion == 1 )
864 bRet = sal_True;
865 if ( bExtendedInfo )
867 sal_uInt16 nChannels = 0;
868 sal_uInt32 nRows = 0;
869 sal_uInt32 nColumns = 0;
870 sal_uInt16 nDepth = 0;
871 sal_uInt16 nMode = 0;
872 rStm.SeekRel( 6 ); // Pad
873 rStm >> nChannels >> nRows >> nColumns >> nDepth >> nMode;
874 if ( ( nDepth == 1 ) || ( nDepth == 8 ) || ( nDepth == 16 ) )
876 nBitsPerPixel = ( nDepth == 16 ) ? 8 : nDepth;
877 switch ( nChannels )
879 case 4 :
880 case 3 :
881 nBitsPerPixel = 24;
882 case 2 :
883 case 1 :
884 aPixSize.Width() = nColumns;
885 aPixSize.Height() = nRows;
886 break;
887 default:
888 bRet = sal_False;
891 else
892 bRet = sal_False;
897 if ( bRet )
898 nFormat = GFF_PSD;
899 rStm.Seek( nStmPos );
900 return bRet;
903 sal_Bool GraphicDescriptor::ImpDetectEPS( SvStream& rStm, sal_Bool )
905 // check the EPS preview and the file extension
906 sal_uInt32 nFirstLong = 0;
907 sal_uInt8 nFirstBytes[20];
908 sal_Bool bRet = sal_False;
909 memset(nFirstBytes, 0, sizeof (nFirstBytes));
911 sal_Int32 nStmPos = rStm.Tell();
912 rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
913 rStm >> nFirstLong;
914 rStm.SeekRel( -4 );
915 rStm.Read( &nFirstBytes, 20 );
917 if ( ( nFirstLong == 0xC5D0D3C6 ) || aPathExt.startsWith( "eps" ) ||
918 ( ImplSearchEntry( nFirstBytes, (sal_uInt8*)"%!PS-Adobe", 10, 10 )
919 && ImplSearchEntry( &nFirstBytes[15], (sal_uInt8*)"EPS", 3, 3 ) ) )
921 nFormat = GFF_EPS;
922 bRet = sal_True;
924 rStm.Seek( nStmPos );
925 return bRet;
928 sal_Bool GraphicDescriptor::ImpDetectDXF( SvStream&, sal_Bool )
930 sal_Bool bRet = aPathExt.startsWith( "dxf" );
931 if (bRet)
932 nFormat = GFF_DXF;
934 return bRet;
937 sal_Bool GraphicDescriptor::ImpDetectMET( SvStream&, sal_Bool )
939 sal_Bool bRet = aPathExt.startsWith( "met" );
940 if (bRet)
941 nFormat = GFF_MET;
943 return bRet;
946 extern bool isPCT(SvStream& rStream, sal_uLong nStreamPos, sal_uLong nStreamLen);
948 sal_Bool GraphicDescriptor::ImpDetectPCT( SvStream& rStm, sal_Bool )
950 sal_Bool bRet = aPathExt.startsWith( "pct" );
951 if (bRet)
952 nFormat = GFF_PCT;
953 else
955 sal_Size nStreamPos = rStm.Tell();
956 sal_Size nStreamLen = rStm.remainingSize();
957 if (isPCT(rStm, nStreamPos, nStreamLen))
959 bRet = sal_True;
960 nFormat = GFF_PCT;
962 rStm.Seek(nStreamPos);
965 return bRet;
968 sal_Bool GraphicDescriptor::ImpDetectSGF( SvStream& rStm, sal_Bool )
970 sal_Bool bRet = sal_False;
971 if( aPathExt.startsWith( "sgf" ) )
972 bRet = sal_True;
973 else
975 sal_Int32 nStmPos = rStm.Tell();
977 sal_uInt8 nFirst = 0, nSecond = 0;
979 rStm >> nFirst >> nSecond;
981 if( nFirst == 'J' && nSecond == 'J' )
982 bRet = sal_True;
984 rStm.Seek( nStmPos );
987 if( bRet )
988 nFormat = GFF_SGF;
990 return bRet;
993 sal_Bool GraphicDescriptor::ImpDetectSGV( SvStream&, sal_Bool )
995 sal_Bool bRet = aPathExt.startsWith( "sgv" );
996 if (bRet)
997 nFormat = GFF_SGV;
999 return bRet;
1002 sal_Bool GraphicDescriptor::ImpDetectSVM( SvStream& rStm, sal_Bool bExtendedInfo )
1004 sal_uInt32 n32 = 0;
1005 sal_Bool bRet = sal_False;
1006 sal_uInt8 cByte = 0;
1008 sal_Int32 nStmPos = rStm.Tell();
1009 rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1010 rStm >> n32;
1011 if ( n32 == 0x44475653 )
1013 cByte = 0;
1014 rStm >> cByte;
1015 if ( cByte == 0x49 )
1017 nFormat = GFF_SVM;
1018 bRet = sal_True;
1020 if ( bExtendedInfo )
1022 sal_uInt32 nTemp32;
1023 sal_uInt16 nTemp16;
1025 rStm.SeekRel( 0x04 );
1027 // width
1028 nTemp32 = 0;
1029 rStm >> nTemp32;
1030 aLogSize.Width() = nTemp32;
1032 // height
1033 nTemp32 = 0;
1034 rStm >> nTemp32;
1035 aLogSize.Height() = nTemp32;
1037 // read MapUnit and determine PrefSize
1038 nTemp16 = 0;
1039 rStm >> nTemp16;
1040 aLogSize = OutputDevice::LogicToLogic( aLogSize,
1041 MapMode( (MapUnit) nTemp16 ),
1042 MapMode( MAP_100TH_MM ) );
1046 else
1048 rStm.SeekRel( -4L );
1049 n32 = 0;
1050 rStm >> n32;
1052 if( n32 == 0x4D4C4356 )
1054 sal_uInt16 nTmp16 = 0;
1056 rStm >> nTmp16;
1058 if( nTmp16 == 0x4654 )
1060 nFormat = GFF_SVM;
1061 bRet = sal_True;
1063 if( bExtendedInfo )
1065 MapMode aMapMode;
1067 rStm.SeekRel( 0x06 );
1068 rStm >> aMapMode;
1069 rStm >> aLogSize;
1070 aLogSize = OutputDevice::LogicToLogic( aLogSize, aMapMode, MapMode( MAP_100TH_MM ) );
1075 rStm.Seek( nStmPos );
1076 return bRet;
1079 sal_Bool GraphicDescriptor::ImpDetectWMF( SvStream&, sal_Bool )
1081 sal_Bool bRet = aPathExt.startsWith( "wmf" );
1082 if (bRet)
1083 nFormat = GFF_WMF;
1085 return bRet;
1088 sal_Bool GraphicDescriptor::ImpDetectEMF( SvStream&, sal_Bool )
1090 sal_Bool bRet = aPathExt.startsWith( "emf" );
1091 if (bRet)
1092 nFormat = GFF_EMF;
1094 return bRet;
1097 sal_Bool GraphicDescriptor::ImpDetectSVG( SvStream& /*rStm*/, sal_Bool /*bExtendedInfo*/ )
1099 sal_Bool bRet = aPathExt.startsWith( "svg" );
1100 if (bRet)
1101 nFormat = GFF_SVG;
1103 return bRet;
1106 OUString GraphicDescriptor::GetImportFormatShortName( sal_uInt16 nFormat )
1108 const char *pKeyName = 0;
1110 switch( nFormat )
1112 case( GFF_BMP ) : pKeyName = "bmp"; break;
1113 case( GFF_GIF ) : pKeyName = "gif"; break;
1114 case( GFF_JPG ) : pKeyName = "jpg"; break;
1115 case( GFF_PCD ) : pKeyName = "pcd"; break;
1116 case( GFF_PCX ) : pKeyName = "pcx"; break;
1117 case( GFF_PNG ) : pKeyName = "png"; break;
1118 case( GFF_XBM ) : pKeyName = "xbm"; break;
1119 case( GFF_XPM ) : pKeyName = "xpm"; break;
1120 case( GFF_PBM ) : pKeyName = "pbm"; break;
1121 case( GFF_PGM ) : pKeyName = "pgm"; break;
1122 case( GFF_PPM ) : pKeyName = "ppm"; break;
1123 case( GFF_RAS ) : pKeyName = "ras"; break;
1124 case( GFF_TGA ) : pKeyName = "tga"; break;
1125 case( GFF_PSD ) : pKeyName = "psd"; break;
1126 case( GFF_EPS ) : pKeyName = "eps"; break;
1127 case( GFF_TIF ) : pKeyName = "tif"; break;
1128 case( GFF_DXF ) : pKeyName = "dxf"; break;
1129 case( GFF_MET ) : pKeyName = "met"; break;
1130 case( GFF_PCT ) : pKeyName = "pct"; break;
1131 case( GFF_SGF ) : pKeyName = "sgf"; break;
1132 case( GFF_SGV ) : pKeyName = "sgv"; break;
1133 case( GFF_SVM ) : pKeyName = "svm"; break;
1134 case( GFF_WMF ) : pKeyName = "wmf"; break;
1135 case( GFF_EMF ) : pKeyName = "emf"; break;
1136 case( GFF_SVG ) : pKeyName = "svg"; break;
1139 return OUString::createFromAscii(pKeyName);
1142 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */