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