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 <tools/stream.hxx>
22 : #include <tools/fract.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 5 : GraphicDescriptor::GraphicDescriptor( const INetURLObject& rPath ) :
31 10 : pFileStm( ::utl::UcbStreamHelper::CreateStream( rPath.GetMainURL( INetURLObject::NO_DECODE ), StreamMode::READ ) ),
32 : aPathExt( rPath.GetFileExtension().toAsciiLowerCase() ),
33 15 : bOwnStream( true )
34 : {
35 5 : ImpConstruct();
36 5 : }
37 :
38 2356 : GraphicDescriptor::GraphicDescriptor( SvStream& rInStream, const OUString* pPath) :
39 : pFileStm ( &rInStream ),
40 2356 : bOwnStream ( false )
41 : {
42 2356 : ImpConstruct();
43 :
44 2356 : if ( pPath )
45 : {
46 2356 : INetURLObject aURL( *pPath );
47 2356 : aPathExt = aURL.GetFileExtension().toAsciiLowerCase();
48 : }
49 2356 : }
50 :
51 4722 : GraphicDescriptor::~GraphicDescriptor()
52 : {
53 2361 : if ( bOwnStream )
54 5 : delete pFileStm;
55 2361 : }
56 :
57 2361 : bool GraphicDescriptor::Detect( bool bExtendedInfo )
58 : {
59 2361 : bool bRet = false;
60 2361 : if ( pFileStm && !pFileStm->GetError() )
61 : {
62 2361 : SvStream& rStm = *pFileStm;
63 2361 : SvStreamEndian nOldFormat = rStm.GetEndian();
64 :
65 2361 : if ( ImpDetectGIF( rStm, bExtendedInfo ) ) bRet = true;
66 2361 : else if ( ImpDetectJPG( rStm, bExtendedInfo ) ) bRet = true;
67 2353 : else if ( ImpDetectBMP( rStm, bExtendedInfo ) ) bRet = true;
68 2353 : else if ( ImpDetectPNG( rStm, bExtendedInfo ) ) bRet = true;
69 2353 : else if ( ImpDetectTIF( rStm, bExtendedInfo ) ) bRet = true;
70 2353 : else if ( ImpDetectPCX( rStm, bExtendedInfo ) ) bRet = true;
71 2353 : else if ( ImpDetectDXF( rStm, bExtendedInfo ) ) bRet = true;
72 2353 : else if ( ImpDetectMET( rStm, bExtendedInfo ) ) bRet = true;
73 2353 : else if ( ImpDetectSGF( rStm, bExtendedInfo ) ) bRet = true;
74 2353 : else if ( ImpDetectSGV( rStm, bExtendedInfo ) ) bRet = true;
75 2353 : else if ( ImpDetectSVM( rStm, bExtendedInfo ) ) bRet = true;
76 2353 : else if ( ImpDetectWMF( rStm, bExtendedInfo ) ) bRet = true;
77 2353 : else if ( ImpDetectEMF( rStm, bExtendedInfo ) ) bRet = true;
78 2352 : else if ( ImpDetectSVG( rStm, bExtendedInfo ) ) bRet = true;
79 2352 : else if ( ImpDetectPCT( rStm, bExtendedInfo ) ) bRet = true;
80 2352 : else if ( ImpDetectXBM( rStm, bExtendedInfo ) ) bRet = true;
81 2352 : else if ( ImpDetectXPM( rStm, bExtendedInfo ) ) bRet = true;
82 2352 : else if ( ImpDetectPBM( rStm, bExtendedInfo ) ) bRet = true;
83 2352 : else if ( ImpDetectPGM( rStm, bExtendedInfo ) ) bRet = true;
84 2352 : else if ( ImpDetectPPM( rStm, bExtendedInfo ) ) bRet = true;
85 2352 : else if ( ImpDetectRAS( rStm, bExtendedInfo ) ) bRet = true;
86 2352 : else if ( ImpDetectTGA( rStm, bExtendedInfo ) ) bRet = true;
87 2352 : else if ( ImpDetectPSD( rStm, bExtendedInfo ) ) bRet = true;
88 2352 : else if ( ImpDetectEPS( rStm, bExtendedInfo ) ) bRet = true;
89 2352 : else if ( ImpDetectPCD( rStm, bExtendedInfo ) ) bRet = true;
90 :
91 2361 : rStm.SetEndian( nOldFormat );
92 : }
93 2361 : return bRet;
94 : }
95 :
96 2361 : void GraphicDescriptor::ImpConstruct()
97 : {
98 2361 : nFormat = GraphicFileFormat::NOT;
99 2361 : nBitsPerPixel = 0;
100 2361 : nPlanes = 0;
101 2361 : bCompressed = false;
102 2361 : }
103 :
104 2353 : bool GraphicDescriptor::ImpDetectBMP( SvStream& rStm, bool bExtendedInfo )
105 : {
106 2353 : sal_uInt16 nTemp16 = 0;
107 2353 : bool bRet = false;
108 2353 : sal_Int32 nStmPos = rStm.Tell();
109 :
110 2353 : rStm.SetEndian( SvStreamEndian::LITTLE );
111 2353 : rStm.ReadUInt16( nTemp16 );
112 :
113 : // OS/2-BitmapArray
114 2353 : if ( nTemp16 == 0x4142 )
115 : {
116 0 : rStm.SeekRel( 0x0c );
117 0 : rStm.ReadUInt16( nTemp16 );
118 : }
119 :
120 : // Bitmap
121 2353 : if ( nTemp16 == 0x4d42 )
122 : {
123 0 : nFormat = GraphicFileFormat::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 = GraphicFileFormat::NOT;
169 0 : bRet = false;
170 : }
171 : }
172 : }
173 2353 : rStm.Seek( nStmPos );
174 2353 : return bRet;
175 : }
176 :
177 2361 : bool GraphicDescriptor::ImpDetectGIF( SvStream& rStm, bool bExtendedInfo )
178 : {
179 2361 : sal_uInt32 n32 = 0;
180 2361 : sal_uInt16 n16 = 0;
181 2361 : bool bRet = false;
182 2361 : sal_uInt8 cByte = 0;
183 :
184 2361 : sal_Int32 nStmPos = rStm.Tell();
185 2361 : rStm.SetEndian( SvStreamEndian::LITTLE );
186 2361 : rStm.ReadUInt32( n32 );
187 :
188 2361 : if ( n32 == 0x38464947 )
189 : {
190 0 : rStm.ReadUInt16( n16 );
191 0 : if ( ( n16 == 0x6137 ) || ( n16 == 0x6139 ) )
192 : {
193 0 : nFormat = GraphicFileFormat::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 2361 : rStm.Seek( nStmPos );
215 2361 : 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 2361 : bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm, bool bExtendedInfo )
245 : {
246 2361 : sal_uInt32 nTemp32 = 0;
247 2361 : bool bRet = false;
248 :
249 2361 : sal_Int32 nStmPos = rStm.Tell();
250 :
251 2361 : rStm.SetEndian( SvStreamEndian::BIG );
252 2361 : rStm.ReadUInt32( nTemp32 );
253 :
254 : // compare upper 24 bits
255 2361 : if( 0xffd8ff00 == ( nTemp32 & 0xffffff00 ) )
256 : {
257 8 : nFormat = GraphicFileFormat::JPG;
258 8 : bRet = true;
259 :
260 8 : 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 2361 : rStm.Seek( nStmPos );
398 2361 : return bRet;
399 : }
400 :
401 2352 : bool GraphicDescriptor::ImpDetectPCD( SvStream& rStm, bool )
402 : {
403 2352 : bool bRet = false;
404 :
405 2352 : sal_Int32 nStmPos = rStm.Tell();
406 2352 : rStm.SetEndian( SvStreamEndian::LITTLE );
407 :
408 2352 : sal_uInt32 nTemp32 = 0;
409 2352 : sal_uInt16 nTemp16 = 0;
410 2352 : sal_uInt8 cByte = 0;
411 :
412 2352 : rStm.SeekRel( 2048 );
413 2352 : rStm.ReadUInt32( nTemp32 );
414 2352 : rStm.ReadUInt16( nTemp16 );
415 2352 : rStm.ReadUChar( cByte );
416 :
417 2352 : if ( ( nTemp32 == 0x5f444350 ) &&
418 0 : ( nTemp16 == 0x5049 ) &&
419 0 : ( cByte == 0x49 ) )
420 : {
421 0 : nFormat = GraphicFileFormat::PCD;
422 0 : bRet = true;
423 : }
424 2352 : rStm.Seek( nStmPos );
425 2352 : return bRet;
426 : }
427 :
428 2353 : 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 2353 : bExtendedInfo = true;
435 :
436 2353 : bool bRet = false;
437 2353 : sal_uInt8 cByte = 0;
438 :
439 2353 : sal_Int32 nStmPos = rStm.Tell();
440 2353 : rStm.SetEndian( SvStreamEndian::LITTLE );
441 2353 : rStm.ReadUChar( cByte );
442 :
443 2353 : if ( cByte == 0x0a )
444 : {
445 0 : nFormat = GraphicFileFormat::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 2353 : rStm.Seek( nStmPos );
508 2353 : return bRet;
509 : }
510 :
511 2353 : bool GraphicDescriptor::ImpDetectPNG( SvStream& rStm, bool bExtendedInfo )
512 : {
513 2353 : sal_uInt32 nTemp32 = 0;
514 2353 : bool bRet = false;
515 :
516 2353 : sal_Int32 nStmPos = rStm.Tell();
517 2353 : rStm.SetEndian( SvStreamEndian::BIG );
518 2353 : rStm.ReadUInt32( nTemp32 );
519 :
520 2353 : if ( nTemp32 == 0x89504e47 )
521 : {
522 0 : rStm.ReadUInt32( nTemp32 );
523 0 : if ( nTemp32 == 0x0d0a1a0a )
524 : {
525 0 : nFormat = GraphicFileFormat::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 2353 : rStm.Seek( nStmPos );
603 2353 : return bRet;
604 : }
605 :
606 2353 : bool GraphicDescriptor::ImpDetectTIF( SvStream& rStm, bool bExtendedInfo )
607 : {
608 2353 : bool bRet = false;
609 2353 : sal_uInt8 cByte1 = 0;
610 2353 : sal_uInt8 cByte2 = 1;
611 :
612 2353 : sal_Int32 nStmPos = rStm.Tell();
613 2353 : rStm.ReadUChar( cByte1 );
614 2353 : rStm.ReadUChar( cByte2 );
615 2353 : if ( cByte1 == cByte2 )
616 : {
617 0 : bool bDetectOk = false;
618 :
619 0 : if ( cByte1 == 0x49 )
620 : {
621 0 : rStm.SetEndian( SvStreamEndian::LITTLE );
622 0 : bDetectOk = true;
623 : }
624 0 : else if ( cByte1 == 0x4d )
625 : {
626 0 : rStm.SetEndian( SvStreamEndian::BIG );
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 = GraphicFileFormat::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 :
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 0 : bool bOk = false;
653 :
654 : // read tags till we find Tag256 ( Width )
655 : // do not read more bytes than DATA_SIZE
656 0 : rStm.ReadUInt16( nTemp16 );
657 0 : while ( nTemp16 != 256 )
658 : {
659 0 : bOk = nCount < nMax;
660 0 : if ( !bOk )
661 : {
662 0 : break;
663 : }
664 0 : rStm.SeekRel( 10 );
665 0 : rStm.ReadUInt16( nTemp16 );
666 0 : nCount += 12;
667 : }
668 :
669 0 : if ( bOk )
670 : {
671 : // width
672 0 : rStm.ReadUInt16( nTemp16 );
673 0 : rStm.SeekRel( 4 );
674 0 : if ( nTemp16 == 3 )
675 : {
676 0 : rStm.ReadUInt16( nTemp16 );
677 0 : aPixSize.Width() = nTemp16;
678 0 : rStm.SeekRel( 2 );
679 : }
680 : else
681 : {
682 0 : rStm.ReadUInt32( nTemp32 );
683 0 : aPixSize.Width() = nTemp32;
684 : }
685 0 : nCount += 12;
686 :
687 : // height
688 0 : rStm.SeekRel( 2 );
689 0 : rStm.ReadUInt16( nTemp16 );
690 0 : rStm.SeekRel( 4 );
691 0 : if ( nTemp16 == 3 )
692 : {
693 0 : rStm.ReadUInt16( nTemp16 );
694 0 : aPixSize.Height() = nTemp16;
695 0 : rStm.SeekRel( 2 );
696 : }
697 : else
698 : {
699 0 : rStm.ReadUInt32( nTemp32 );
700 0 : aPixSize.Height() = nTemp32;
701 : }
702 0 : nCount += 12;
703 :
704 : // Bits/Pixel
705 0 : rStm.ReadUInt16( nTemp16 );
706 0 : if ( nTemp16 == 258 )
707 : {
708 0 : rStm.SeekRel( 6 );
709 0 : rStm.ReadUInt16( nTemp16 );
710 0 : nBitsPerPixel = nTemp16;
711 0 : rStm.SeekRel( 2 );
712 0 : nCount += 12;
713 : }
714 : else
715 0 : rStm.SeekRel( -2 );
716 :
717 : // compression
718 0 : rStm.ReadUInt16( nTemp16 );
719 0 : if ( nTemp16 == 259 )
720 : {
721 0 : rStm.SeekRel( 6 );
722 0 : rStm.ReadUInt16( nTemp16 );
723 0 : bCompressed = ( nTemp16 > 1 );
724 0 : rStm.SeekRel( 2 );
725 0 : nCount += 12;
726 : }
727 : else
728 0 : rStm.SeekRel( -2 );
729 : }
730 : }
731 : }
732 : }
733 : }
734 : }
735 2353 : rStm.Seek( nStmPos );
736 2353 : return bRet;
737 : }
738 :
739 2352 : bool GraphicDescriptor::ImpDetectXBM( SvStream&, bool )
740 : {
741 2352 : bool bRet = aPathExt.startsWith( "xbm" );
742 2352 : if (bRet)
743 0 : nFormat = GraphicFileFormat::XBM;
744 :
745 2352 : return bRet;
746 : }
747 :
748 2352 : bool GraphicDescriptor::ImpDetectXPM( SvStream&, bool )
749 : {
750 2352 : bool bRet = aPathExt.startsWith( "xpm" );
751 2352 : if (bRet)
752 0 : nFormat = GraphicFileFormat::XPM;
753 :
754 2352 : return bRet;
755 : }
756 :
757 2352 : bool GraphicDescriptor::ImpDetectPBM( SvStream& rStm, bool )
758 : {
759 2352 : bool bRet = false;
760 :
761 : // check file extension first, as this trumps the 2 ID bytes
762 2352 : if ( aPathExt.startsWith( "pbm" ) )
763 0 : bRet = true;
764 : else
765 : {
766 2352 : sal_Int32 nStmPos = rStm.Tell();
767 2352 : sal_uInt8 nFirst = 0, nSecond = 0;
768 2352 : rStm.ReadUChar( nFirst ).ReadUChar( nSecond );
769 2352 : if ( nFirst == 'P' && ( ( nSecond == '1' ) || ( nSecond == '4' ) ) )
770 0 : bRet = true;
771 2352 : rStm.Seek( nStmPos );
772 : }
773 :
774 2352 : if ( bRet )
775 0 : nFormat = GraphicFileFormat::PBM;
776 :
777 2352 : return bRet;
778 : }
779 :
780 2352 : bool GraphicDescriptor::ImpDetectPGM( SvStream& rStm, bool )
781 : {
782 2352 : bool bRet = false;
783 :
784 2352 : if ( aPathExt.startsWith( "pgm" ) )
785 0 : bRet = true;
786 : else
787 : {
788 2352 : sal_uInt8 nFirst = 0, nSecond = 0;
789 2352 : sal_Int32 nStmPos = rStm.Tell();
790 2352 : rStm.ReadUChar( nFirst ).ReadUChar( nSecond );
791 2352 : if ( nFirst == 'P' && ( ( nSecond == '2' ) || ( nSecond == '5' ) ) )
792 0 : bRet = true;
793 2352 : rStm.Seek( nStmPos );
794 : }
795 :
796 2352 : if ( bRet )
797 0 : nFormat = GraphicFileFormat::PGM;
798 :
799 2352 : return bRet;
800 : }
801 :
802 2352 : bool GraphicDescriptor::ImpDetectPPM( SvStream& rStm, bool )
803 : {
804 2352 : bool bRet = false;
805 :
806 2352 : if ( aPathExt.startsWith( "ppm" ) )
807 0 : bRet = true;
808 : else
809 : {
810 2352 : sal_uInt8 nFirst = 0, nSecond = 0;
811 2352 : sal_Int32 nStmPos = rStm.Tell();
812 2352 : rStm.ReadUChar( nFirst ).ReadUChar( nSecond );
813 2352 : if ( nFirst == 'P' && ( ( nSecond == '3' ) || ( nSecond == '6' ) ) )
814 0 : bRet = true;
815 2352 : rStm.Seek( nStmPos );
816 : }
817 :
818 2352 : if ( bRet )
819 0 : nFormat = GraphicFileFormat::PPM;
820 :
821 2352 : return bRet;
822 : }
823 :
824 2352 : bool GraphicDescriptor::ImpDetectRAS( SvStream& rStm, bool )
825 : {
826 2352 : sal_uInt32 nMagicNumber = 0;
827 2352 : bool bRet = false;
828 2352 : sal_Int32 nStmPos = rStm.Tell();
829 2352 : rStm.SetEndian( SvStreamEndian::BIG );
830 2352 : rStm.ReadUInt32( nMagicNumber );
831 2352 : if ( nMagicNumber == 0x59a66a95 )
832 : {
833 0 : nFormat = GraphicFileFormat::RAS;
834 0 : bRet = true;
835 : }
836 2352 : rStm.Seek( nStmPos );
837 2352 : return bRet;
838 : }
839 :
840 2352 : bool GraphicDescriptor::ImpDetectTGA( SvStream&, bool )
841 : {
842 2352 : bool bRet = aPathExt.startsWith( "tga" );
843 2352 : if (bRet)
844 0 : nFormat = GraphicFileFormat::TGA;
845 :
846 2352 : return bRet;
847 : }
848 :
849 2352 : bool GraphicDescriptor::ImpDetectPSD( SvStream& rStm, bool bExtendedInfo )
850 : {
851 2352 : bool bRet = false;
852 :
853 2352 : sal_uInt32 nMagicNumber = 0;
854 2352 : sal_Int32 nStmPos = rStm.Tell();
855 2352 : rStm.SetEndian( SvStreamEndian::BIG );
856 2352 : rStm.ReadUInt32( nMagicNumber );
857 2352 : if ( nMagicNumber == 0x38425053 )
858 : {
859 0 : sal_uInt16 nVersion = 0;
860 0 : rStm.ReadUInt16( nVersion );
861 0 : if ( nVersion == 1 )
862 : {
863 0 : bRet = true;
864 0 : if ( bExtendedInfo )
865 : {
866 0 : sal_uInt16 nChannels = 0;
867 0 : sal_uInt32 nRows = 0;
868 0 : sal_uInt32 nColumns = 0;
869 0 : sal_uInt16 nDepth = 0;
870 0 : sal_uInt16 nMode = 0;
871 0 : rStm.SeekRel( 6 ); // Pad
872 0 : rStm.ReadUInt16( nChannels ).ReadUInt32( nRows ).ReadUInt32( nColumns ).ReadUInt16( nDepth ).ReadUInt16( nMode );
873 0 : if ( ( nDepth == 1 ) || ( nDepth == 8 ) || ( nDepth == 16 ) )
874 : {
875 0 : nBitsPerPixel = ( nDepth == 16 ) ? 8 : nDepth;
876 0 : switch ( nChannels )
877 : {
878 : case 4 :
879 : case 3 :
880 0 : nBitsPerPixel = 24;
881 : case 2 :
882 : case 1 :
883 0 : aPixSize.Width() = nColumns;
884 0 : aPixSize.Height() = nRows;
885 0 : break;
886 : default:
887 0 : bRet = false;
888 : }
889 : }
890 : else
891 0 : bRet = false;
892 : }
893 : }
894 : }
895 :
896 2352 : if ( bRet )
897 0 : nFormat = GraphicFileFormat::PSD;
898 2352 : rStm.Seek( nStmPos );
899 2352 : return bRet;
900 : }
901 :
902 2352 : bool GraphicDescriptor::ImpDetectEPS( SvStream& rStm, bool )
903 : {
904 : // check the EPS preview and the file extension
905 2352 : sal_uInt32 nFirstLong = 0;
906 : sal_uInt8 nFirstBytes[20];
907 2352 : bool bRet = false;
908 2352 : memset(nFirstBytes, 0, sizeof (nFirstBytes));
909 :
910 2352 : sal_Int32 nStmPos = rStm.Tell();
911 2352 : rStm.SetEndian( SvStreamEndian::BIG );
912 2352 : rStm.ReadUInt32( nFirstLong );
913 2352 : rStm.SeekRel( -4 );
914 2352 : rStm.Read( &nFirstBytes, 20 );
915 :
916 4704 : if ( ( nFirstLong == 0xC5D0D3C6 ) || aPathExt.startsWith( "eps" ) ||
917 2352 : ( ImplSearchEntry( nFirstBytes, reinterpret_cast<sal_uInt8 const *>("%!PS-Adobe"), 10, 10 )
918 0 : && ImplSearchEntry( &nFirstBytes[15], reinterpret_cast<sal_uInt8 const *>("EPS"), 3, 3 ) ) )
919 : {
920 0 : nFormat = GraphicFileFormat::EPS;
921 0 : bRet = true;
922 : }
923 2352 : rStm.Seek( nStmPos );
924 2352 : return bRet;
925 : }
926 :
927 2353 : bool GraphicDescriptor::ImpDetectDXF( SvStream&, bool )
928 : {
929 2353 : bool bRet = aPathExt.startsWith( "dxf" );
930 2353 : if (bRet)
931 0 : nFormat = GraphicFileFormat::DXF;
932 :
933 2353 : return bRet;
934 : }
935 :
936 2353 : bool GraphicDescriptor::ImpDetectMET( SvStream&, bool )
937 : {
938 2353 : bool bRet = aPathExt.startsWith( "met" );
939 2353 : if (bRet)
940 0 : nFormat = GraphicFileFormat::MET;
941 :
942 2353 : return bRet;
943 : }
944 :
945 2352 : bool GraphicDescriptor::ImpDetectPCT( SvStream& rStm, bool )
946 : {
947 2352 : bool bRet = aPathExt.startsWith( "pct" );
948 2352 : if (bRet)
949 0 : nFormat = GraphicFileFormat::PCT;
950 : else
951 : {
952 2352 : sal_Size nStreamPos = rStm.Tell();
953 2352 : sal_Size nStreamLen = rStm.remainingSize();
954 2352 : if (isPCT(rStm, nStreamPos, nStreamLen))
955 : {
956 0 : bRet = true;
957 0 : nFormat = GraphicFileFormat::PCT;
958 : }
959 2352 : rStm.Seek(nStreamPos);
960 : }
961 :
962 2352 : return bRet;
963 : }
964 :
965 2353 : bool GraphicDescriptor::ImpDetectSGF( SvStream& rStm, bool )
966 : {
967 2353 : bool bRet = false;
968 2353 : if( aPathExt.startsWith( "sgf" ) )
969 0 : bRet = true;
970 : else
971 : {
972 2353 : sal_Int32 nStmPos = rStm.Tell();
973 :
974 2353 : sal_uInt8 nFirst = 0, nSecond = 0;
975 :
976 2353 : rStm.ReadUChar( nFirst ).ReadUChar( nSecond );
977 :
978 2353 : if( nFirst == 'J' && nSecond == 'J' )
979 0 : bRet = true;
980 :
981 2353 : rStm.Seek( nStmPos );
982 : }
983 :
984 2353 : if( bRet )
985 0 : nFormat = GraphicFileFormat::SGF;
986 :
987 2353 : return bRet;
988 : }
989 :
990 2353 : bool GraphicDescriptor::ImpDetectSGV( SvStream&, bool )
991 : {
992 2353 : bool bRet = aPathExt.startsWith( "sgv" );
993 2353 : if (bRet)
994 0 : nFormat = GraphicFileFormat::SGV;
995 :
996 2353 : return bRet;
997 : }
998 :
999 2353 : bool GraphicDescriptor::ImpDetectSVM( SvStream& rStm, bool bExtendedInfo )
1000 : {
1001 2353 : sal_uInt32 n32 = 0;
1002 2353 : bool bRet = false;
1003 2353 : sal_uInt8 cByte = 0;
1004 :
1005 2353 : sal_Int32 nStmPos = rStm.Tell();
1006 2353 : rStm.SetEndian( SvStreamEndian::LITTLE );
1007 2353 : rStm.ReadUInt32( n32 );
1008 2353 : if ( n32 == 0x44475653 )
1009 : {
1010 0 : cByte = 0;
1011 0 : rStm.ReadUChar( cByte );
1012 0 : if ( cByte == 0x49 )
1013 : {
1014 0 : nFormat = GraphicFileFormat::SVM;
1015 0 : bRet = true;
1016 :
1017 0 : if ( bExtendedInfo )
1018 : {
1019 : sal_uInt32 nTemp32;
1020 : sal_uInt16 nTemp16;
1021 :
1022 0 : rStm.SeekRel( 0x04 );
1023 :
1024 : // width
1025 0 : nTemp32 = 0;
1026 0 : rStm.ReadUInt32( nTemp32 );
1027 0 : aLogSize.Width() = nTemp32;
1028 :
1029 : // height
1030 0 : nTemp32 = 0;
1031 0 : rStm.ReadUInt32( nTemp32 );
1032 0 : aLogSize.Height() = nTemp32;
1033 :
1034 : // read MapUnit and determine PrefSize
1035 0 : nTemp16 = 0;
1036 0 : rStm.ReadUInt16( nTemp16 );
1037 : aLogSize = OutputDevice::LogicToLogic( aLogSize,
1038 : MapMode( (MapUnit) nTemp16 ),
1039 0 : MapMode( MAP_100TH_MM ) );
1040 : }
1041 : }
1042 : }
1043 : else
1044 : {
1045 2353 : rStm.SeekRel( -4L );
1046 2353 : n32 = 0;
1047 2353 : rStm.ReadUInt32( n32 );
1048 :
1049 2353 : if( n32 == 0x4D4C4356 )
1050 : {
1051 0 : sal_uInt16 nTmp16 = 0;
1052 :
1053 0 : rStm.ReadUInt16( nTmp16 );
1054 :
1055 0 : if( nTmp16 == 0x4654 )
1056 : {
1057 0 : nFormat = GraphicFileFormat::SVM;
1058 0 : bRet = true;
1059 :
1060 0 : if( bExtendedInfo )
1061 : {
1062 0 : MapMode aMapMode;
1063 :
1064 0 : rStm.SeekRel( 0x06 );
1065 0 : ReadMapMode( rStm, aMapMode );
1066 0 : ReadPair( rStm, aLogSize );
1067 0 : aLogSize = OutputDevice::LogicToLogic( aLogSize, aMapMode, MapMode( MAP_100TH_MM ) );
1068 : }
1069 : }
1070 : }
1071 : }
1072 2353 : rStm.Seek( nStmPos );
1073 2353 : return bRet;
1074 : }
1075 :
1076 2353 : bool GraphicDescriptor::ImpDetectWMF( SvStream&, bool )
1077 : {
1078 2353 : bool bRet = aPathExt.startsWith( "wmf" );
1079 2353 : if (bRet)
1080 0 : nFormat = GraphicFileFormat::WMF;
1081 :
1082 2353 : return bRet;
1083 : }
1084 :
1085 2353 : bool GraphicDescriptor::ImpDetectEMF( SvStream&, bool )
1086 : {
1087 2353 : bool bRet = aPathExt.startsWith( "emf" );
1088 2353 : if (bRet)
1089 1 : nFormat = GraphicFileFormat::EMF;
1090 :
1091 2353 : return bRet;
1092 : }
1093 :
1094 2352 : bool GraphicDescriptor::ImpDetectSVG( SvStream& /*rStm*/, bool /*bExtendedInfo*/ )
1095 : {
1096 2352 : bool bRet = aPathExt.startsWith( "svg" );
1097 2352 : if (bRet)
1098 0 : nFormat = GraphicFileFormat::SVG;
1099 :
1100 2352 : return bRet;
1101 : }
1102 :
1103 4 : OUString GraphicDescriptor::GetImportFormatShortName( GraphicFileFormat nFormat )
1104 : {
1105 4 : const char *pKeyName = 0;
1106 :
1107 4 : switch( nFormat )
1108 : {
1109 0 : case( GraphicFileFormat::BMP ) : pKeyName = "bmp"; break;
1110 0 : case( GraphicFileFormat::GIF ) : pKeyName = "gif"; break;
1111 3 : case( GraphicFileFormat::JPG ) : pKeyName = "jpg"; break;
1112 0 : case( GraphicFileFormat::PCD ) : pKeyName = "pcd"; break;
1113 0 : case( GraphicFileFormat::PCX ) : pKeyName = "pcx"; break;
1114 0 : case( GraphicFileFormat::PNG ) : pKeyName = "png"; break;
1115 0 : case( GraphicFileFormat::XBM ) : pKeyName = "xbm"; break;
1116 0 : case( GraphicFileFormat::XPM ) : pKeyName = "xpm"; break;
1117 0 : case( GraphicFileFormat::PBM ) : pKeyName = "pbm"; break;
1118 0 : case( GraphicFileFormat::PGM ) : pKeyName = "pgm"; break;
1119 0 : case( GraphicFileFormat::PPM ) : pKeyName = "ppm"; break;
1120 0 : case( GraphicFileFormat::RAS ) : pKeyName = "ras"; break;
1121 0 : case( GraphicFileFormat::TGA ) : pKeyName = "tga"; break;
1122 0 : case( GraphicFileFormat::PSD ) : pKeyName = "psd"; break;
1123 0 : case( GraphicFileFormat::EPS ) : pKeyName = "eps"; break;
1124 0 : case( GraphicFileFormat::TIF ) : pKeyName = "tif"; break;
1125 0 : case( GraphicFileFormat::DXF ) : pKeyName = "dxf"; break;
1126 0 : case( GraphicFileFormat::MET ) : pKeyName = "met"; break;
1127 0 : case( GraphicFileFormat::PCT ) : pKeyName = "pct"; break;
1128 0 : case( GraphicFileFormat::SGF ) : pKeyName = "sgf"; break;
1129 0 : case( GraphicFileFormat::SGV ) : pKeyName = "sgv"; break;
1130 0 : case( GraphicFileFormat::SVM ) : pKeyName = "svm"; break;
1131 0 : case( GraphicFileFormat::WMF ) : pKeyName = "wmf"; break;
1132 1 : case( GraphicFileFormat::EMF ) : pKeyName = "emf"; break;
1133 0 : case( GraphicFileFormat::SVG ) : pKeyName = "svg"; break;
1134 : default: assert(false);
1135 : }
1136 :
1137 4 : return OUString::createFromAscii(pKeyName);
1138 801 : }
1139 :
1140 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|