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