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