Line data Source code
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 :
21 : #include <string.h>
22 : #include <stdio.h>
23 : #include <tools/stream.hxx>
24 : #include <vcl/outdev.hxx>
25 : #include <svtools/filter.hxx>
26 : #include "FilterConfigCache.hxx"
27 : #include <unotools/ucbstreamhelper.hxx>
28 :
29 : #define DATA_SIZE 640
30 :
31 : sal_uInt8* ImplSearchEntry( sal_uInt8* , sal_uInt8* , sal_uLong , sal_uLong );
32 :
33 0 : GraphicDescriptor::GraphicDescriptor( const INetURLObject& rPath ) :
34 0 : pFileStm( ::utl::UcbStreamHelper::CreateStream( rPath.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ ) ),
35 : aPathExt( rPath.GetFileExtension().toAsciiLowerCase() ),
36 0 : bOwnStream( sal_True )
37 : {
38 0 : ImpConstruct();
39 0 : }
40 :
41 0 : GraphicDescriptor::GraphicDescriptor( SvStream& rInStream, const String* pPath) :
42 : pFileStm ( &rInStream ),
43 0 : bOwnStream ( sal_False )
44 : {
45 0 : ImpConstruct();
46 :
47 0 : if ( pPath )
48 : {
49 0 : INetURLObject aURL( *pPath );
50 0 : aPathExt = aURL.GetFileExtension().toAsciiLowerCase();
51 : }
52 0 : }
53 :
54 0 : GraphicDescriptor::~GraphicDescriptor()
55 : {
56 0 : if ( bOwnStream )
57 0 : delete pFileStm;
58 0 : }
59 :
60 0 : sal_Bool GraphicDescriptor::Detect( sal_Bool bExtendedInfo )
61 : {
62 0 : sal_Bool bRet = sal_False;
63 0 : if ( pFileStm && !pFileStm->GetError() )
64 : {
65 0 : SvStream& rStm = *pFileStm;
66 0 : sal_uInt16 nOldFormat = rStm.GetNumberFormatInt();
67 :
68 0 : if ( ImpDetectGIF( rStm, bExtendedInfo ) ) bRet = sal_True;
69 0 : else if ( ImpDetectJPG( rStm, bExtendedInfo ) ) bRet = sal_True;
70 0 : else if ( ImpDetectBMP( rStm, bExtendedInfo ) ) bRet = sal_True;
71 0 : else if ( ImpDetectPNG( rStm, bExtendedInfo ) ) bRet = sal_True;
72 0 : else if ( ImpDetectTIF( rStm, bExtendedInfo ) ) bRet = sal_True;
73 0 : else if ( ImpDetectPCX( rStm, bExtendedInfo ) ) bRet = sal_True;
74 0 : else if ( ImpDetectDXF( rStm, bExtendedInfo ) ) bRet = sal_True;
75 0 : else if ( ImpDetectMET( rStm, bExtendedInfo ) ) bRet = sal_True;
76 0 : else if ( ImpDetectSGF( rStm, bExtendedInfo ) ) bRet = sal_True;
77 0 : else if ( ImpDetectSGV( rStm, bExtendedInfo ) ) bRet = sal_True;
78 0 : else if ( ImpDetectSVM( rStm, bExtendedInfo ) ) bRet = sal_True;
79 0 : else if ( ImpDetectWMF( rStm, bExtendedInfo ) ) bRet = sal_True;
80 0 : else if ( ImpDetectEMF( rStm, bExtendedInfo ) ) bRet = sal_True;
81 0 : else if ( ImpDetectSVG( rStm, bExtendedInfo ) ) bRet = sal_True;
82 0 : else if ( ImpDetectPCT( rStm, bExtendedInfo ) ) bRet = sal_True;
83 0 : else if ( ImpDetectXBM( rStm, bExtendedInfo ) ) bRet = sal_True;
84 0 : else if ( ImpDetectXPM( rStm, bExtendedInfo ) ) bRet = sal_True;
85 0 : else if ( ImpDetectPBM( rStm, bExtendedInfo ) ) bRet = sal_True;
86 0 : else if ( ImpDetectPGM( rStm, bExtendedInfo ) ) bRet = sal_True;
87 0 : else if ( ImpDetectPPM( rStm, bExtendedInfo ) ) bRet = sal_True;
88 0 : else if ( ImpDetectRAS( rStm, bExtendedInfo ) ) bRet = sal_True;
89 0 : else if ( ImpDetectTGA( rStm, bExtendedInfo ) ) bRet = sal_True;
90 0 : else if ( ImpDetectPSD( rStm, bExtendedInfo ) ) bRet = sal_True;
91 0 : else if ( ImpDetectEPS( rStm, bExtendedInfo ) ) bRet = sal_True;
92 0 : else if ( ImpDetectPCD( rStm, bExtendedInfo ) ) bRet = sal_True;
93 :
94 0 : rStm.SetNumberFormatInt( nOldFormat );
95 : }
96 0 : return bRet;
97 : }
98 :
99 0 : void GraphicDescriptor::ImpConstruct()
100 : {
101 0 : nFormat = GFF_NOT;
102 0 : nBitsPerPixel = 0;
103 0 : nPlanes = 0;
104 0 : bCompressed = sal_False;
105 0 : }
106 :
107 0 : sal_Bool GraphicDescriptor::ImpDetectBMP( SvStream& rStm, sal_Bool bExtendedInfo )
108 : {
109 : sal_uInt16 nTemp16;
110 0 : sal_Bool bRet = sal_False;
111 0 : sal_Int32 nStmPos = rStm.Tell();
112 :
113 0 : rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
114 0 : rStm >> nTemp16;
115 :
116 : // OS/2-BitmapArray
117 0 : if ( nTemp16 == 0x4142 )
118 : {
119 0 : rStm.SeekRel( 0x0c );
120 0 : rStm >> nTemp16;
121 : }
122 :
123 : // Bitmap
124 0 : if ( nTemp16 == 0x4d42 )
125 : {
126 0 : nFormat = GFF_BMP;
127 0 : bRet = sal_True;
128 :
129 0 : if ( bExtendedInfo )
130 : {
131 : sal_uInt32 nTemp32;
132 : sal_uInt32 nCompression;
133 :
134 : // bis zur ersten Information
135 0 : rStm.SeekRel( 0x10 );
136 :
137 : // PixelBreite auslesen
138 0 : rStm >> nTemp32;
139 0 : aPixSize.Width() = nTemp32;
140 :
141 : // PixelHoehe auslesen
142 0 : rStm >> nTemp32;
143 0 : aPixSize.Height() = nTemp32;
144 :
145 : // Planes auslesen
146 0 : rStm >> nTemp16;
147 0 : nPlanes = nTemp16;
148 :
149 : // BitCount auslesen
150 0 : rStm >> nTemp16;
151 0 : nBitsPerPixel = nTemp16;
152 :
153 : // Compression auslesen
154 0 : rStm >> nTemp32;
155 0 : bCompressed = ( ( nCompression = nTemp32 ) > 0 );
156 :
157 : // logische Breite
158 0 : rStm.SeekRel( 4 );
159 0 : rStm >> nTemp32;
160 0 : if ( nTemp32 )
161 0 : aLogSize.Width() = ( aPixSize.Width() * 100000 ) / nTemp32;
162 :
163 : // logische Hoehe
164 0 : rStm >> nTemp32;
165 0 : if ( nTemp32 )
166 0 : aLogSize.Height() = ( aPixSize.Height() * 100000 ) / nTemp32;
167 :
168 : // Wir wollen noch etwas feiner differenzieren und
169 : // auf sinnvolle Werte ueberpruefen ( Bug-Id #29001 )
170 0 : if ( ( nBitsPerPixel > 24 ) || ( nCompression > 3 ) )
171 : {
172 0 : nFormat = GFF_NOT;
173 0 : bRet = sal_False;
174 : }
175 : }
176 : }
177 0 : rStm.Seek( nStmPos );
178 0 : return bRet;
179 : }
180 :
181 0 : sal_Bool GraphicDescriptor::ImpDetectGIF( SvStream& rStm, sal_Bool bExtendedInfo )
182 : {
183 : sal_uInt32 n32;
184 : sal_uInt16 n16;
185 0 : sal_Bool bRet = sal_False;
186 : sal_uInt8 cByte;
187 :
188 0 : sal_Int32 nStmPos = rStm.Tell();
189 0 : rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
190 0 : rStm >> n32;
191 :
192 0 : if ( n32 == 0x38464947 )
193 : {
194 0 : rStm >> n16;
195 0 : if ( ( n16 == 0x6137 ) || ( n16 == 0x6139 ) )
196 : {
197 0 : nFormat = GFF_GIF;
198 0 : bRet = sal_True;
199 :
200 0 : if ( bExtendedInfo )
201 : {
202 : sal_uInt16 nTemp16;
203 :
204 : // PixelBreite auslesen
205 0 : rStm >> nTemp16;
206 0 : aPixSize.Width() = nTemp16;
207 :
208 : // PixelHoehe auslesen
209 0 : rStm >> nTemp16;
210 0 : aPixSize.Height() = nTemp16;
211 :
212 : // Bits/Pixel auslesen
213 0 : rStm >> cByte;
214 0 : nBitsPerPixel = ( ( cByte & 112 ) >> 4 ) + 1;
215 : }
216 : }
217 : }
218 0 : rStm.Seek( nStmPos );
219 0 : return bRet;
220 : }
221 :
222 : // returns the next jpeg marker, a return value of 0 represents an error
223 0 : sal_uInt8 ImpDetectJPG_GetNextMarker( SvStream& rStm )
224 : {
225 : sal_uInt8 nByte;
226 0 : do
227 : {
228 0 : do
229 : {
230 0 : rStm >> nByte;
231 0 : if ( rStm.IsEof() || rStm.GetError() ) // as 0 is not allowed as marker,
232 0 : return 0; // we can use it as errorcode
233 : }
234 : while ( nByte != 0xff );
235 0 : do
236 : {
237 0 : rStm >> nByte;
238 0 : if ( rStm.IsEof() || rStm.GetError() )
239 0 : return 0;
240 : }
241 : while( nByte == 0xff );
242 : }
243 : while( nByte == 0 ); // 0xff00 represents 0xff and not a marker,
244 : // the marker detection has to be restartet.
245 0 : return nByte;
246 : }
247 :
248 0 : sal_Bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm, sal_Bool bExtendedInfo )
249 : {
250 : sal_uInt32 nTemp32;
251 0 : sal_Bool bRet = sal_False;
252 :
253 0 : sal_Int32 nStmPos = rStm.Tell();
254 :
255 0 : rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
256 0 : rStm >> nTemp32;
257 :
258 : // compare upper 24 bits
259 0 : if( 0xffd8ff00 == ( nTemp32 & 0xffffff00 ) )
260 : {
261 0 : nFormat = GFF_JPG;
262 0 : bRet = sal_True;
263 :
264 0 : if ( bExtendedInfo )
265 : {
266 0 : rStm.SeekRel( -2 );
267 :
268 0 : sal_uInt32 nError( rStm.GetError() );
269 :
270 0 : sal_Bool bScanFailure = sal_False;
271 0 : sal_Bool bScanFinished = sal_False;
272 :
273 0 : while( !bScanFailure && !bScanFinished && !rStm.IsEof() && !rStm.GetError() )
274 : {
275 0 : sal_uInt8 nMarker = ImpDetectJPG_GetNextMarker( rStm );
276 0 : switch( nMarker )
277 : {
278 : // fixed size marker, not having a two byte length parameter
279 : case 0xd0 : // RST0
280 : case 0xd1 :
281 : case 0xd2 :
282 : case 0xd3 :
283 : case 0xd4 :
284 : case 0xd5 :
285 : case 0xd6 :
286 : case 0xd7 : // RST7
287 : case 0x01 : // TEM
288 0 : break;
289 :
290 : case 0xd8 : // SOI (has already been checked, there should not be a second one)
291 : case 0x00 : // marker is invalid, we should stop now
292 0 : bScanFailure = sal_True;
293 0 : break;
294 :
295 : case 0xd9 : // EOI
296 0 : bScanFinished = sal_True;
297 0 : break;
298 :
299 : // per default we assume marker segments conaining a length parameter
300 : default :
301 : {
302 : sal_uInt16 nLength;
303 0 : rStm >> nLength;
304 :
305 0 : if ( nLength < 2 )
306 0 : bScanFailure = sal_True;
307 : else
308 : {
309 0 : sal_uInt32 nNextMarkerPos = rStm.Tell() + nLength - 2;
310 0 : switch( nMarker )
311 : {
312 : case 0xe0 : // APP0 Marker
313 : {
314 0 : if ( nLength == 16 )
315 : {
316 : sal_Int32 nIdentifier;
317 0 : rStm >> nIdentifier;
318 0 : if ( nIdentifier == 0x4a464946 ) // JFIF Identifier
319 : {
320 : sal_uInt8 nStringTerminator;
321 : sal_uInt8 nMajorRevision;
322 : sal_uInt8 nMinorRevision;
323 : sal_uInt8 nUnits;
324 : sal_uInt16 nHorizontalResolution;
325 : sal_uInt16 nVerticalResolution;
326 : sal_uInt8 nHorzThumbnailPixelCount;
327 : sal_uInt8 nVertThumbnailPixelCount;
328 :
329 0 : rStm >> nStringTerminator
330 0 : >> nMajorRevision
331 0 : >> nMinorRevision
332 0 : >> nUnits
333 0 : >> nHorizontalResolution
334 0 : >> nVerticalResolution
335 0 : >> nHorzThumbnailPixelCount
336 0 : >> nVertThumbnailPixelCount;
337 :
338 : // setting the logical size
339 0 : if ( nUnits && nHorizontalResolution && nVerticalResolution )
340 : {
341 0 : MapMode aMap;
342 0 : aMap.SetMapUnit( nUnits == 1 ? MAP_INCH : MAP_CM );
343 0 : aMap.SetScaleX( Fraction( 1, nHorizontalResolution ) );
344 0 : aMap.SetScaleY( Fraction( 1, nVerticalResolution ) );
345 0 : aLogSize = OutputDevice::LogicToLogic( aPixSize, aMap, MapMode( MAP_100TH_MM ) );
346 : }
347 : }
348 : }
349 : }
350 0 : break;
351 :
352 : // Start of Frame Markers
353 : case 0xc0 : // SOF0
354 : case 0xc1 : // SOF1
355 : case 0xc2 : // SOF2
356 : case 0xc3 : // SOF3
357 : case 0xc5 : // SOF5
358 : case 0xc6 : // SOF6
359 : case 0xc7 : // SOF7
360 : case 0xc9 : // SOF9
361 : case 0xca : // SOF10
362 : case 0xcb : // SOF11
363 : case 0xcd : // SOF13
364 : case 0xce : // SOF14
365 : case 0xcf : // SOF15
366 : {
367 : sal_uInt8 nSamplePrecision;
368 : sal_uInt16 nNumberOfLines;
369 : sal_uInt16 nSamplesPerLine;
370 : sal_uInt8 nNumberOfImageComponents;
371 : sal_uInt8 nComponentsIdentifier;
372 : sal_uInt8 nHorizontalSamplingFactor;
373 : sal_uInt8 nQuantizationTableDestinationSelector;
374 0 : rStm >> nSamplePrecision
375 0 : >> nNumberOfLines
376 0 : >> nSamplesPerLine
377 0 : >> nNumberOfImageComponents
378 0 : >> nComponentsIdentifier
379 0 : >> nHorizontalSamplingFactor
380 0 : >> nQuantizationTableDestinationSelector;
381 0 : nHorizontalSamplingFactor >>= 4;
382 :
383 0 : aPixSize.Height() = nNumberOfLines;
384 0 : aPixSize.Width() = nSamplesPerLine;
385 0 : nBitsPerPixel = ( nNumberOfImageComponents == 3 ? 24 : nNumberOfImageComponents == 1 ? 8 : 0 );
386 0 : nPlanes = 1;
387 :
388 0 : bScanFinished = sal_True;
389 : }
390 0 : break;
391 : }
392 0 : rStm.Seek( nNextMarkerPos );
393 : }
394 : }
395 0 : break;
396 : }
397 : }
398 0 : rStm.SetError( nError );
399 : }
400 : }
401 0 : rStm.Seek( nStmPos );
402 0 : return bRet;
403 : }
404 :
405 0 : sal_Bool GraphicDescriptor::ImpDetectPCD( SvStream& rStm, sal_Bool )
406 : {
407 0 : sal_Bool bRet = sal_False;
408 :
409 0 : sal_Int32 nStmPos = rStm.Tell();
410 0 : rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
411 :
412 : sal_uInt32 nTemp32;
413 : sal_uInt16 nTemp16;
414 : sal_uInt8 cByte;
415 :
416 0 : rStm.SeekRel( 2048 );
417 0 : rStm >> nTemp32;
418 0 : rStm >> nTemp16;
419 0 : rStm >> cByte;
420 :
421 0 : if ( ( nTemp32 == 0x5f444350 ) &&
422 : ( nTemp16 == 0x5049 ) &&
423 : ( cByte == 0x49 ) )
424 : {
425 0 : nFormat = GFF_PCD;
426 0 : bRet = sal_True;
427 : }
428 0 : rStm.Seek( nStmPos );
429 0 : return bRet;
430 : }
431 :
432 0 : sal_Bool GraphicDescriptor::ImpDetectPCX( SvStream& rStm, sal_Bool bExtendedInfo )
433 : {
434 : // ! Because 0x0a can be interpreted as LF too ...
435 : // we cant be shure that this special sign represent a PCX file only.
436 : // Every Ascii file is possible here :-(
437 : // We must detect the whole header.
438 0 : bExtendedInfo = sal_True;
439 :
440 0 : sal_Bool bRet = sal_False;
441 : sal_uInt8 cByte;
442 :
443 0 : sal_Int32 nStmPos = rStm.Tell();
444 0 : rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
445 0 : rStm >> cByte;
446 :
447 0 : if ( cByte == 0x0a )
448 : {
449 0 : nFormat = GFF_PCX;
450 0 : bRet = sal_True;
451 :
452 0 : if ( bExtendedInfo )
453 : {
454 : sal_uInt16 nTemp16;
455 : sal_uInt16 nXmin;
456 : sal_uInt16 nXmax;
457 : sal_uInt16 nYmin;
458 : sal_uInt16 nYmax;
459 : sal_uInt16 nDPIx;
460 : sal_uInt16 nDPIy;
461 :
462 :
463 0 : rStm.SeekRel( 1 );
464 :
465 : // Kompression lesen
466 0 : rStm >> cByte;
467 0 : bCompressed = ( cByte > 0 );
468 :
469 0 : bRet = (cByte==0 || cByte ==1);
470 :
471 : // Bits/Pixel lesen
472 0 : rStm >> cByte;
473 0 : nBitsPerPixel = cByte;
474 :
475 : // Bildabmessungen
476 0 : rStm >> nTemp16;
477 0 : nXmin = nTemp16;
478 0 : rStm >> nTemp16;
479 0 : nYmin = nTemp16;
480 0 : rStm >> nTemp16;
481 0 : nXmax = nTemp16;
482 0 : rStm >> nTemp16;
483 0 : nYmax = nTemp16;
484 :
485 0 : aPixSize.Width() = nXmax - nXmin + 1;
486 0 : aPixSize.Height() = nYmax - nYmin + 1;
487 :
488 : // Aufloesung
489 0 : rStm >> nTemp16;
490 0 : nDPIx = nTemp16;
491 0 : rStm >> nTemp16;
492 0 : nDPIy = nTemp16;
493 :
494 : // logische Groesse setzen
495 : MapMode aMap( MAP_INCH, Point(),
496 0 : Fraction( 1, nDPIx ), Fraction( 1, nDPIy ) );
497 : aLogSize = OutputDevice::LogicToLogic( aPixSize, aMap,
498 0 : MapMode( MAP_100TH_MM ) );
499 :
500 :
501 : // Anzahl Farbebenen
502 0 : rStm.SeekRel( 49 );
503 0 : rStm >> cByte;
504 0 : nPlanes = cByte;
505 :
506 0 : bRet = (nPlanes<=4);
507 : }
508 : }
509 :
510 0 : rStm.Seek( nStmPos );
511 0 : return bRet;
512 : }
513 :
514 0 : sal_Bool GraphicDescriptor::ImpDetectPNG( SvStream& rStm, sal_Bool bExtendedInfo )
515 : {
516 : sal_uInt32 nTemp32;
517 0 : sal_Bool bRet = sal_False;
518 :
519 0 : sal_Int32 nStmPos = rStm.Tell();
520 0 : rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
521 0 : rStm >> nTemp32;
522 :
523 0 : if ( nTemp32 == 0x89504e47 )
524 : {
525 0 : rStm >> nTemp32;
526 0 : if ( nTemp32 == 0x0d0a1a0a )
527 : {
528 0 : nFormat = GFF_PNG;
529 0 : bRet = sal_True;
530 :
531 0 : if ( bExtendedInfo )
532 : {
533 : sal_uInt8 cByte;
534 :
535 : // IHDR-Chunk
536 0 : rStm.SeekRel( 8 );
537 :
538 : // Breite einlesen
539 0 : rStm >> nTemp32;
540 0 : aPixSize.Width() = nTemp32;
541 :
542 : // Hoehe einlesen
543 0 : rStm >> nTemp32;
544 0 : aPixSize.Height() = nTemp32;
545 :
546 : // Bits/Pixel einlesen
547 0 : rStm >> cByte;
548 0 : nBitsPerPixel = cByte;
549 :
550 : // Planes immer 1;
551 : // Kompression immer
552 0 : nPlanes = 1;
553 0 : bCompressed = sal_True;
554 :
555 : sal_uInt32 nLen32;
556 :
557 0 : rStm.SeekRel( 8 );
558 :
559 : // so lange ueberlesen, bis wir den pHYs-Chunk haben oder
560 : // den Anfang der Bilddaten
561 0 : rStm >> nLen32;
562 0 : rStm >> nTemp32;
563 0 : while( ( nTemp32 != 0x70485973 ) && ( nTemp32 != 0x49444154 ) )
564 : {
565 0 : rStm.SeekRel( 4 + nLen32 );
566 0 : rStm >> nLen32;
567 0 : rStm >> nTemp32;
568 : }
569 :
570 0 : if ( nTemp32 == 0x70485973 )
571 : {
572 : sal_uLong nXRes;
573 : sal_uLong nYRes;
574 :
575 : // horizontale Aufloesung
576 0 : rStm >> nTemp32;
577 0 : nXRes = nTemp32;
578 :
579 : // vertikale Aufloesung
580 0 : rStm >> nTemp32;
581 0 : nYRes = nTemp32;
582 :
583 : // Unit einlesen
584 0 : rStm >> cByte;
585 :
586 0 : if ( cByte )
587 : {
588 0 : if ( nXRes )
589 0 : aLogSize.Width() = ( aPixSize.Width() * 100000 ) /
590 0 : nTemp32;
591 :
592 0 : if ( nYRes )
593 0 : aLogSize.Height() = ( aPixSize.Height() * 100000 ) /
594 0 : nTemp32;
595 : }
596 : }
597 : }
598 : }
599 : }
600 0 : rStm.Seek( nStmPos );
601 0 : return bRet;
602 : }
603 :
604 0 : sal_Bool GraphicDescriptor::ImpDetectTIF( SvStream& rStm, sal_Bool bExtendedInfo )
605 : {
606 0 : sal_Bool bDetectOk = sal_False;
607 0 : sal_Bool bRet = sal_False;
608 : sal_uInt8 cByte1;
609 : sal_uInt8 cByte2;
610 :
611 0 : sal_Int32 nStmPos = rStm.Tell();
612 0 : rStm >> cByte1;
613 0 : rStm >> cByte2;
614 0 : if ( cByte1 == cByte2 )
615 : {
616 0 : if ( cByte1 == 0x49 )
617 : {
618 0 : rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
619 0 : bDetectOk = sal_True;
620 : }
621 0 : else if ( cByte1 == 0x4d )
622 : {
623 0 : rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
624 0 : bDetectOk = sal_True;
625 : }
626 :
627 0 : if ( bDetectOk )
628 : {
629 : sal_uInt16 nTemp16;
630 :
631 0 : rStm >> nTemp16;
632 0 : if ( nTemp16 == 0x2a )
633 : {
634 0 : nFormat = GFF_TIF;
635 0 : bRet = sal_True;
636 :
637 0 : if ( bExtendedInfo )
638 : {
639 : sal_uLong nCount;
640 0 : sal_uLong nMax = DATA_SIZE - 48;
641 : sal_uInt32 nTemp32;
642 0 : sal_Bool bOk = sal_False;
643 :
644 : // Offset des ersten IFD einlesen
645 0 : rStm >> nTemp32;
646 0 : rStm.SeekRel( ( nCount = ( nTemp32 + 2 ) ) - 0x08 );
647 :
648 0 : if ( nCount < nMax )
649 : {
650 : // Tag's lesen, bis wir auf Tag256 ( Width ) treffen
651 : // nicht mehr Bytes als DATA_SIZE lesen
652 0 : rStm >> nTemp16;
653 0 : while ( nTemp16 != 256 )
654 : {
655 0 : bOk = nCount < nMax;
656 0 : if ( !bOk )
657 : {
658 0 : break;
659 : }
660 0 : rStm.SeekRel( 10 );
661 0 : rStm >> nTemp16;
662 0 : nCount += 12;
663 : }
664 :
665 0 : if ( bOk )
666 : {
667 : // Breite lesen
668 0 : rStm >> nTemp16;
669 0 : rStm.SeekRel( 4 );
670 0 : if ( nTemp16 == 3 )
671 : {
672 0 : rStm >> nTemp16;
673 0 : aPixSize.Width() = nTemp16;
674 0 : rStm.SeekRel( 2 );
675 : }
676 : else
677 : {
678 0 : rStm >> nTemp32;
679 0 : aPixSize.Width() = nTemp32;
680 : }
681 0 : nCount += 12;
682 :
683 : // Hoehe lesen
684 0 : rStm.SeekRel( 2 );
685 0 : rStm >> nTemp16;
686 0 : rStm.SeekRel( 4 );
687 0 : if ( nTemp16 == 3 )
688 : {
689 0 : rStm >> nTemp16;
690 0 : aPixSize.Height() = nTemp16;
691 0 : rStm.SeekRel( 2 );
692 : }
693 : else
694 : {
695 0 : rStm >> nTemp32;
696 0 : aPixSize.Height() = nTemp32;
697 : }
698 0 : nCount += 12;
699 :
700 : // ggf. Bits/Pixel lesen
701 0 : rStm >> nTemp16;
702 0 : if ( nTemp16 == 258 )
703 : {
704 0 : rStm.SeekRel( 6 );
705 0 : rStm >> nTemp16;
706 0 : nBitsPerPixel = nTemp16;
707 0 : rStm.SeekRel( 2 );
708 0 : nCount += 12;
709 : }
710 : else
711 0 : rStm.SeekRel( -2 );
712 :
713 : // ggf. Compression lesen
714 0 : rStm >> nTemp16;
715 0 : if ( nTemp16 == 259 )
716 : {
717 0 : rStm.SeekRel( 6 );
718 0 : rStm >> nTemp16;
719 0 : bCompressed = ( nTemp16 > 1 );
720 0 : rStm.SeekRel( 2 );
721 0 : nCount += 12;
722 : }
723 : else
724 0 : rStm.SeekRel( -2 );
725 : }
726 : }
727 : }
728 : }
729 : }
730 : }
731 0 : rStm.Seek( nStmPos );
732 0 : return bRet;
733 : }
734 :
735 0 : sal_Bool GraphicDescriptor::ImpDetectXBM( SvStream&, sal_Bool )
736 : {
737 0 : sal_Bool bRet = aPathExt.CompareToAscii( "xbm", 3 ) == COMPARE_EQUAL;
738 0 : if (bRet)
739 0 : nFormat = GFF_XBM;
740 :
741 0 : return bRet;
742 : }
743 :
744 0 : sal_Bool GraphicDescriptor::ImpDetectXPM( SvStream&, sal_Bool )
745 : {
746 0 : sal_Bool bRet = aPathExt.CompareToAscii( "xpm", 3 ) == COMPARE_EQUAL;
747 0 : if (bRet)
748 0 : nFormat = GFF_XPM;
749 :
750 0 : return bRet;
751 : }
752 :
753 0 : sal_Bool GraphicDescriptor::ImpDetectPBM( SvStream& rStm, sal_Bool )
754 : {
755 0 : sal_Bool bRet = sal_False;
756 :
757 : // erst auf Datei Extension pruefen, da diese aussagekraeftiger ist
758 : // als die 2 ID Bytes
759 :
760 0 : if ( aPathExt.CompareToAscii( "pbm", 3 ) == COMPARE_EQUAL )
761 0 : bRet = sal_True;
762 : else
763 : {
764 0 : sal_Int32 nStmPos = rStm.Tell();
765 : sal_uInt8 nFirst, nSecond;
766 0 : rStm >> nFirst >> nSecond;
767 0 : if ( nFirst == 'P' && ( ( nSecond == '1' ) || ( nSecond == '4' ) ) )
768 0 : bRet = sal_True;
769 0 : rStm.Seek( nStmPos );
770 : }
771 :
772 0 : if ( bRet )
773 0 : nFormat = GFF_PBM;
774 :
775 0 : return bRet;
776 : }
777 :
778 0 : sal_Bool GraphicDescriptor::ImpDetectPGM( SvStream& rStm, sal_Bool )
779 : {
780 0 : sal_Bool bRet = sal_False;
781 :
782 0 : if ( aPathExt.CompareToAscii( "pgm", 3 ) == COMPARE_EQUAL )
783 0 : bRet = sal_True;
784 : else
785 : {
786 : sal_uInt8 nFirst, nSecond;
787 0 : sal_Int32 nStmPos = rStm.Tell();
788 0 : rStm >> nFirst >> nSecond;
789 0 : if ( nFirst == 'P' && ( ( nSecond == '2' ) || ( nSecond == '5' ) ) )
790 0 : bRet = sal_True;
791 0 : rStm.Seek( nStmPos );
792 : }
793 :
794 0 : if ( bRet )
795 0 : nFormat = GFF_PGM;
796 :
797 0 : return bRet;
798 : }
799 :
800 0 : sal_Bool GraphicDescriptor::ImpDetectPPM( SvStream& rStm, sal_Bool )
801 : {
802 0 : sal_Bool bRet = sal_False;
803 :
804 0 : if ( aPathExt.CompareToAscii( "ppm", 3 ) == COMPARE_EQUAL )
805 0 : bRet = sal_True;
806 : else
807 : {
808 : sal_uInt8 nFirst, nSecond;
809 0 : sal_Int32 nStmPos = rStm.Tell();
810 0 : rStm >> nFirst >> nSecond;
811 0 : if ( nFirst == 'P' && ( ( nSecond == '3' ) || ( nSecond == '6' ) ) )
812 0 : bRet = sal_True;
813 0 : rStm.Seek( nStmPos );
814 : }
815 :
816 0 : if ( bRet )
817 0 : nFormat = GFF_PPM;
818 :
819 0 : return bRet;
820 : }
821 :
822 0 : sal_Bool GraphicDescriptor::ImpDetectRAS( SvStream& rStm, sal_Bool )
823 : {
824 : sal_uInt32 nMagicNumber;
825 0 : sal_Bool bRet = sal_False;
826 0 : sal_Int32 nStmPos = rStm.Tell();
827 0 : rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
828 0 : rStm >> nMagicNumber;
829 0 : if ( nMagicNumber == 0x59a66a95 )
830 : {
831 0 : nFormat = GFF_RAS;
832 0 : bRet = sal_True;
833 : }
834 0 : rStm.Seek( nStmPos );
835 0 : return bRet;
836 : }
837 :
838 0 : sal_Bool GraphicDescriptor::ImpDetectTGA( SvStream&, sal_Bool )
839 : {
840 0 : sal_Bool bRet = aPathExt.CompareToAscii( "tga", 3 ) == COMPARE_EQUAL;
841 0 : if (bRet)
842 0 : nFormat = GFF_TGA;
843 :
844 0 : return bRet;
845 : }
846 :
847 0 : sal_Bool GraphicDescriptor::ImpDetectPSD( SvStream& rStm, sal_Bool bExtendedInfo )
848 : {
849 0 : sal_Bool bRet = sal_False;
850 :
851 : sal_uInt32 nMagicNumber;
852 0 : sal_Int32 nStmPos = rStm.Tell();
853 0 : rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
854 0 : rStm >> nMagicNumber;
855 0 : if ( nMagicNumber == 0x38425053 )
856 : {
857 : sal_uInt16 nVersion;
858 0 : rStm >> nVersion;
859 0 : if ( nVersion == 1 )
860 : {
861 0 : bRet = sal_True;
862 0 : if ( bExtendedInfo )
863 : {
864 : sal_uInt16 nChannels;
865 : sal_uInt32 nRows;
866 : sal_uInt32 nColumns;
867 : sal_uInt16 nDepth;
868 : sal_uInt16 nMode;
869 0 : rStm.SeekRel( 6 ); // Pad
870 0 : rStm >> nChannels >> nRows >> nColumns >> nDepth >> nMode;
871 0 : if ( ( nDepth == 1 ) || ( nDepth == 8 ) || ( nDepth == 16 ) )
872 : {
873 0 : nBitsPerPixel = ( nDepth == 16 ) ? 8 : nDepth;
874 0 : switch ( nChannels )
875 : {
876 : case 4 :
877 : case 3 :
878 0 : nBitsPerPixel = 24;
879 : case 2 :
880 : case 1 :
881 0 : aPixSize.Width() = nColumns;
882 0 : aPixSize.Height() = nRows;
883 0 : break;
884 : default:
885 0 : bRet = sal_False;
886 : }
887 : }
888 : else
889 0 : bRet = sal_False;
890 : }
891 : }
892 : }
893 :
894 0 : if ( bRet )
895 0 : nFormat = GFF_PSD;
896 0 : rStm.Seek( nStmPos );
897 0 : return bRet;
898 : }
899 :
900 0 : sal_Bool GraphicDescriptor::ImpDetectEPS( SvStream& rStm, sal_Bool )
901 : {
902 : // es wird die EPS mit Vorschaubild Variante und die Extensionuebereinstimmung
903 : // geprueft
904 :
905 : sal_uInt32 nFirstLong;
906 : sal_uInt8 nFirstBytes[20];
907 0 : sal_Bool bRet = sal_False;
908 :
909 0 : sal_Int32 nStmPos = rStm.Tell();
910 0 : rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
911 0 : rStm >> nFirstLong;
912 0 : rStm.SeekRel( -4 );
913 0 : rStm.Read( &nFirstBytes, 20 );
914 :
915 0 : if ( ( nFirstLong == 0xC5D0D3C6 ) || ( aPathExt.CompareToAscii( "eps", 3 ) == COMPARE_EQUAL ) ||
916 0 : ( ImplSearchEntry( nFirstBytes, (sal_uInt8*)"%!PS-Adobe", 10, 10 )
917 0 : && ImplSearchEntry( &nFirstBytes[15], (sal_uInt8*)"EPS", 3, 3 ) ) )
918 : {
919 0 : nFormat = GFF_EPS;
920 0 : bRet = sal_True;
921 : }
922 0 : rStm.Seek( nStmPos );
923 0 : return bRet;
924 : }
925 :
926 0 : sal_Bool GraphicDescriptor::ImpDetectDXF( SvStream&, sal_Bool )
927 : {
928 0 : sal_Bool bRet = aPathExt.CompareToAscii( "dxf", 3 ) == COMPARE_EQUAL;
929 0 : if (bRet)
930 0 : nFormat = GFF_DXF;
931 :
932 0 : return bRet;
933 : }
934 :
935 0 : sal_Bool GraphicDescriptor::ImpDetectMET( SvStream&, sal_Bool )
936 : {
937 0 : sal_Bool bRet = aPathExt.CompareToAscii( "met", 3 ) == COMPARE_EQUAL;
938 0 : if (bRet)
939 0 : nFormat = GFF_MET;
940 :
941 0 : return bRet;
942 : }
943 :
944 : extern bool isPCT(SvStream& rStream, sal_uLong nStreamPos, sal_uLong nStreamLen);
945 :
946 0 : sal_Bool GraphicDescriptor::ImpDetectPCT( SvStream& rStm, sal_Bool )
947 : {
948 0 : sal_Bool bRet = aPathExt.CompareToAscii( "pct", 3 ) == COMPARE_EQUAL;
949 0 : if (bRet)
950 0 : nFormat = GFF_PCT;
951 : else
952 : {
953 0 : sal_Size nStreamPos = rStm.Tell();
954 0 : sal_Size nStreamLen = rStm.remainingSize();
955 0 : if (isPCT(rStm, nStreamPos, nStreamLen))
956 : {
957 0 : bRet = sal_True;
958 0 : nFormat = GFF_PCT;
959 : }
960 0 : rStm.Seek(nStreamPos);
961 : }
962 :
963 0 : return bRet;
964 : }
965 :
966 0 : sal_Bool GraphicDescriptor::ImpDetectSGF( SvStream& rStm, sal_Bool )
967 : {
968 0 : sal_Bool bRet = sal_False;
969 0 : if( aPathExt.CompareToAscii( "sgf", 3 ) == COMPARE_EQUAL )
970 0 : bRet = sal_True;
971 : else
972 : {
973 0 : sal_Int32 nStmPos = rStm.Tell();
974 :
975 : sal_uInt8 nFirst, nSecond;
976 :
977 0 : rStm >> nFirst >> nSecond;
978 :
979 0 : if( nFirst == 'J' && nSecond == 'J' )
980 0 : bRet = sal_True;
981 :
982 0 : rStm.Seek( nStmPos );
983 : }
984 :
985 0 : if( bRet )
986 0 : nFormat = GFF_SGF;
987 :
988 0 : return bRet;
989 : }
990 :
991 0 : sal_Bool GraphicDescriptor::ImpDetectSGV( SvStream&, sal_Bool )
992 : {
993 0 : sal_Bool bRet = aPathExt.CompareToAscii( "sgv", 3 ) == COMPARE_EQUAL;
994 0 : if (bRet)
995 0 : nFormat = GFF_SGV;
996 :
997 0 : return bRet;
998 : }
999 :
1000 0 : sal_Bool GraphicDescriptor::ImpDetectSVM( SvStream& rStm, sal_Bool bExtendedInfo )
1001 : {
1002 : sal_uInt32 n32;
1003 0 : sal_Bool bRet = sal_False;
1004 : sal_uInt8 cByte;
1005 :
1006 0 : sal_Int32 nStmPos = rStm.Tell();
1007 0 : rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1008 0 : rStm >> n32;
1009 0 : if ( n32 == 0x44475653 )
1010 : {
1011 0 : rStm >> cByte;
1012 0 : if ( cByte == 0x49 )
1013 : {
1014 0 : nFormat = GFF_SVM;
1015 0 : bRet = sal_True;
1016 :
1017 0 : if ( bExtendedInfo )
1018 : {
1019 : sal_uInt32 nTemp32;
1020 : sal_uInt16 nTemp16;
1021 :
1022 0 : rStm.SeekRel( 0x04 );
1023 :
1024 : // Breite auslesen
1025 0 : rStm >> nTemp32;
1026 0 : aLogSize.Width() = nTemp32;
1027 :
1028 : // Hoehe auslesen
1029 0 : rStm >> nTemp32;
1030 0 : aLogSize.Height() = nTemp32;
1031 :
1032 : // Map-Unit auslesen und PrefSize ermitteln
1033 0 : rStm >> nTemp16;
1034 : aLogSize = OutputDevice::LogicToLogic( aLogSize,
1035 : MapMode( (MapUnit) nTemp16 ),
1036 0 : MapMode( MAP_100TH_MM ) );
1037 : }
1038 : }
1039 : }
1040 : else
1041 : {
1042 0 : rStm.SeekRel( -4L );
1043 0 : rStm >> n32;
1044 :
1045 0 : if( n32 == 0x4D4C4356 )
1046 : {
1047 : sal_uInt16 nTmp16;
1048 :
1049 0 : rStm >> nTmp16;
1050 :
1051 0 : if( nTmp16 == 0x4654 )
1052 : {
1053 0 : nFormat = GFF_SVM;
1054 0 : bRet = sal_True;
1055 :
1056 0 : if( bExtendedInfo )
1057 : {
1058 0 : MapMode aMapMode;
1059 :
1060 0 : rStm.SeekRel( 0x06 );
1061 0 : rStm >> aMapMode;
1062 0 : rStm >> aLogSize;
1063 0 : aLogSize = OutputDevice::LogicToLogic( aLogSize, aMapMode, MapMode( MAP_100TH_MM ) );
1064 : }
1065 : }
1066 : }
1067 : }
1068 0 : rStm.Seek( nStmPos );
1069 0 : return bRet;
1070 : }
1071 :
1072 0 : sal_Bool GraphicDescriptor::ImpDetectWMF( SvStream&, sal_Bool )
1073 : {
1074 0 : sal_Bool bRet = aPathExt.CompareToAscii( "wmf",3 ) == COMPARE_EQUAL;
1075 0 : if (bRet)
1076 0 : nFormat = GFF_WMF;
1077 :
1078 0 : return bRet;
1079 : }
1080 :
1081 0 : sal_Bool GraphicDescriptor::ImpDetectEMF( SvStream&, sal_Bool )
1082 : {
1083 0 : sal_Bool bRet = aPathExt.CompareToAscii( "emf", 3 ) == COMPARE_EQUAL;
1084 0 : if (bRet)
1085 0 : nFormat = GFF_EMF;
1086 :
1087 0 : return bRet;
1088 : }
1089 :
1090 0 : sal_Bool GraphicDescriptor::ImpDetectSVG( SvStream& /*rStm*/, sal_Bool /*bExtendedInfo*/ )
1091 : {
1092 0 : sal_Bool bRet = aPathExt.CompareToAscii( "svg", 3 ) == COMPARE_EQUAL;
1093 0 : if (bRet)
1094 0 : nFormat = GFF_SVG;
1095 :
1096 0 : return bRet;
1097 : }
1098 :
1099 0 : String GraphicDescriptor::GetImportFormatShortName( sal_uInt16 nFormat )
1100 : {
1101 0 : const char *pKeyName = 0;
1102 :
1103 0 : switch( nFormat )
1104 : {
1105 0 : case( GFF_BMP ) : pKeyName = "bmp"; break;
1106 0 : case( GFF_GIF ) : pKeyName = "gif"; break;
1107 0 : case( GFF_JPG ) : pKeyName = "jpg"; break;
1108 0 : case( GFF_PCD ) : pKeyName = "pcd"; break;
1109 0 : case( GFF_PCX ) : pKeyName = "pcx"; break;
1110 0 : case( GFF_PNG ) : pKeyName = "png"; break;
1111 0 : case( GFF_XBM ) : pKeyName = "xbm"; break;
1112 0 : case( GFF_XPM ) : pKeyName = "xpm"; break;
1113 0 : case( GFF_PBM ) : pKeyName = "pbm"; break;
1114 0 : case( GFF_PGM ) : pKeyName = "pgm"; break;
1115 0 : case( GFF_PPM ) : pKeyName = "ppm"; break;
1116 0 : case( GFF_RAS ) : pKeyName = "ras"; break;
1117 0 : case( GFF_TGA ) : pKeyName = "tga"; break;
1118 0 : case( GFF_PSD ) : pKeyName = "psd"; break;
1119 0 : case( GFF_EPS ) : pKeyName = "eps"; break;
1120 0 : case( GFF_TIF ) : pKeyName = "tif"; break;
1121 0 : case( GFF_DXF ) : pKeyName = "dxf"; break;
1122 0 : case( GFF_MET ) : pKeyName = "met"; break;
1123 0 : case( GFF_PCT ) : pKeyName = "pct"; break;
1124 0 : case( GFF_SGF ) : pKeyName = "sgf"; break;
1125 0 : case( GFF_SGV ) : pKeyName = "sgv"; break;
1126 0 : case( GFF_SVM ) : pKeyName = "svm"; break;
1127 0 : case( GFF_WMF ) : pKeyName = "wmf"; break;
1128 0 : case( GFF_EMF ) : pKeyName = "emf"; break;
1129 0 : case( GFF_SVG ) : pKeyName = "svg"; break;
1130 : }
1131 :
1132 0 : return rtl::OUString::createFromAscii(pKeyName);
1133 : }
1134 :
1135 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|