/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <string.h>
#include <tools/stream.hxx>
#include <tools/fract.hxx>
#include <vcl/outdev.hxx>
#include <vcl/graphicfilter.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include "graphicfilter_internal.hxx"
#define DATA_SIZE 640
GraphicDescriptor::GraphicDescriptor( const INetURLObject& rPath ) :
pFileStm( ::utl::UcbStreamHelper::CreateStream( rPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ).release() ),
aPathExt( rPath.GetFileExtension().toAsciiLowerCase() ),
bOwnStream( true )
{
ImpConstruct();
}
GraphicDescriptor::GraphicDescriptor( SvStream& rInStream, const OUString* pPath) :
pFileStm ( &rInStream ),
bOwnStream ( false )
{
ImpConstruct();
if ( pPath )
{
INetURLObject aURL( *pPath );
aPathExt = aURL.GetFileExtension().toAsciiLowerCase();
}
}
GraphicDescriptor::~GraphicDescriptor()
{
if ( bOwnStream )
delete pFileStm;
}
bool GraphicDescriptor::Detect( bool bExtendedInfo )
{
bool bRet = false;
if ( pFileStm && !pFileStm->GetError() )
{
SvStream& rStm = *pFileStm;
SvStreamEndian nOldFormat = rStm.GetEndian();
if ( ImpDetectGIF( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectJPG( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectBMP( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectPNG( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectTIF( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectPCX( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectDXF( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectMET( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectSVM( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectWMF( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectEMF( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectSVG( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectPCT( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectXBM( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectXPM( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectPBM( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectPGM( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectPPM( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectRAS( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectTGA( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectPSD( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectEPS( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectPCD( rStm, bExtendedInfo ) ) bRet = true;
rStm.SetEndian( nOldFormat );
}
return bRet;
}
void GraphicDescriptor::ImpConstruct()
{
nFormat = GraphicFileFormat::NOT;
nBitsPerPixel = 0;
nPlanes = 0;
mnNumberOfImageComponents = 0;
}
bool GraphicDescriptor::ImpDetectBMP( SvStream& rStm, bool bExtendedInfo )
{
sal_uInt16 nTemp16 = 0;
bool bRet = false;
sal_Int32 nStmPos = rStm.Tell();
rStm.SetEndian( SvStreamEndian::LITTLE );
rStm.ReadUInt16( nTemp16 );
// OS/2-BitmapArray
if ( nTemp16 == 0x4142 )
{
rStm.SeekRel( 0x0c );
rStm.ReadUInt16( nTemp16 );
}
// Bitmap
if ( nTemp16 == 0x4d42 )
{
nFormat = GraphicFileFormat::BMP;
bRet = true;
if ( bExtendedInfo )
{
sal_uInt32 nTemp32;
sal_uInt32 nCompression;
// up to first info
rStm.SeekRel( 0x10 );
// Pixel width
rStm.ReadUInt32( nTemp32 );
aPixSize.setWidth( nTemp32 );
// Pixel height
rStm.ReadUInt32( nTemp32 );
aPixSize.setHeight( nTemp32 );
// Planes
rStm.ReadUInt16( nTemp16 );
nPlanes = nTemp16;
// BitCount
rStm.ReadUInt16( nTemp16 );
nBitsPerPixel = nTemp16;
// Compression
rStm.ReadUInt32( nTemp32 );
nCompression = nTemp32;
// logical width
rStm.SeekRel( 4 );
rStm.ReadUInt32( nTemp32 );
if ( nTemp32 )
aLogSize.setWidth( ( aPixSize.Width() * 100000 ) / nTemp32 );
// logical height
rStm.ReadUInt32( nTemp32 );
if ( nTemp32 )
aLogSize.setHeight( ( aPixSize.Height() * 100000 ) / nTemp32 );
// further validation, check for rational values
if ( ( nBitsPerPixel > 24 ) || ( nCompression > 3 ) )
{
nFormat = GraphicFileFormat::NOT;
bRet = false;
}
}
}
rStm.Seek( nStmPos );
return bRet;
}
bool GraphicDescriptor::ImpDetectGIF( SvStream& rStm, bool bExtendedInfo )
{
sal_uInt32 n32 = 0;
sal_uInt16 n16 = 0;
bool bRet = false;
sal_uInt8 cByte = 0;
sal_Int32 nStmPos = rStm.Tell();
rStm.SetEndian( SvStreamEndian::LITTLE );
rStm.ReadUInt32( n32 );
if ( n32 == 0x38464947 )
{
rStm.ReadUInt16( n16 );
if ( ( n16 == 0x6137 ) || ( n16 == 0x6139 ) )
{
nFormat = GraphicFileFormat::GIF;
bRet = true;
if ( bExtendedInfo )
{
sal_uInt16 nTemp16 = 0;
// Pixel width
rStm.ReadUInt16( nTemp16 );
aPixSize.setWidth( nTemp16 );
// Pixel height
rStm.ReadUInt16( nTemp16 );
aPixSize.setHeight( nTemp16 );
// Bits/Pixel
rStm.ReadUChar( cByte );
nBitsPerPixel = ( ( cByte & 112 ) >> 4 ) + 1;
}
}
}
rStm.Seek( nStmPos );
return bRet;
}
// returns the next jpeg marker, a return value of 0 represents an error
sal_uInt8 ImpDetectJPG_GetNextMarker( SvStream& rStm )
{
sal_uInt8 nByte;
do
{
do
{
rStm.ReadUChar( nByte );
if (!rStm.good()) // as 0 is not allowed as marker,
return 0; // we can use it as errorcode
}
while ( nByte != 0xff );
do
{
rStm.ReadUChar( nByte );
if (!rStm.good())
return 0;
}
while( nByte == 0xff );
}
while( nByte == 0 ); // 0xff00 represents 0xff and not a marker,
// the marker detection has to be restarted.
return nByte;
}
bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm, bool bExtendedInfo )
{
sal_uInt32 nTemp32 = 0;
bool bRet = false;
sal_Int32 nStmPos = rStm.Tell();
rStm.SetEndian( SvStreamEndian::BIG );
rStm.ReadUInt32( nTemp32 );
// compare upper 24 bits
if( 0xffd8ff00 == ( nTemp32 & 0xffffff00 ) )
{
nFormat = GraphicFileFormat::JPG;
bRet = true;
if ( bExtendedInfo )
{
rStm.SeekRel( -2 );
ErrCode nError( rStm.GetError() );
bool bScanFailure = false;
bool bScanFinished = false;
MapMode aMap;
while (!bScanFailure && !bScanFinished && rStm.good())
{
sal_uInt8 nMarker = ImpDetectJPG_GetNextMarker( rStm );
switch( nMarker )
{
// fixed size marker, not having a two byte length parameter
case 0xd0 : // RST0
case 0xd1 :
case 0xd2 :
case 0xd3 :
case 0xd4 :
case 0xd5 :
case 0xd6 :
case 0xd7 : // RST7
case 0x01 : // TEM
break;
case 0xd8 : // SOI (has already been checked, there should not be a second one)
case 0x00 : // marker is invalid, we should stop now
bScanFailure = true;
break;
case 0xd9 : // EOI
bScanFinished = true;
break;
// per default we assume marker segments containing a length parameter
default :
{
sal_uInt16 nLength = 0;
rStm.ReadUInt16( nLength );
if ( nLength < 2 )
bScanFailure = true;
else
{
sal_uInt32 nNextMarkerPos = rStm.Tell() + nLength - 2;
switch( nMarker )
{
case 0xe0 : // APP0 Marker
{
if ( nLength == 16 )
{
sal_Int32 nIdentifier = 0;
rStm.ReadInt32( nIdentifier );
if ( nIdentifier == 0x4a464946 ) // JFIF Identifier
{
sal_uInt8 nStringTerminator = 0;
sal_uInt8 nMajorRevision = 0;
sal_uInt8 nMinorRevision = 0;
sal_uInt8 nUnits = 0;
sal_uInt16 nHorizontalResolution = 0;
sal_uInt16 nVerticalResolution = 0;
sal_uInt8 nHorzThumbnailPixelCount = 0;
sal_uInt8 nVertThumbnailPixelCount = 0;
rStm.ReadUChar( nStringTerminator )
.ReadUChar( nMajorRevision )
.ReadUChar( nMinorRevision )
.ReadUChar( nUnits )
.ReadUInt16( nHorizontalResolution )
.ReadUInt16( nVerticalResolution )
.ReadUChar( nHorzThumbnailPixelCount )
.ReadUChar( nVertThumbnailPixelCount );
// setting the logical size
if ( nUnits && nHorizontalResolution && nVerticalResolution )
{
aMap.SetMapUnit( nUnits == 1 ? MapUnit::MapInch : MapUnit::MapCM );
aMap.SetScaleX( Fraction( 1, nHorizontalResolution ) );
aMap.SetScaleY( Fraction( 1, nVerticalResolution ) );
aLogSize = OutputDevice::LogicToLogic( aPixSize, aMap, MapMode( MapUnit::Map100thMM ) );
}
}
}
}
break;
// Start of Frame Markers
case 0xc0 : // SOF0
case 0xc1 : // SOF1
case 0xc2 : // SOF2
case 0xc3 : // SOF3
case 0xc5 : // SOF5
case 0xc6 : // SOF6
case 0xc7 : // SOF7
case 0xc9 : // SOF9
case 0xca : // SOF10
case 0xcb : // SOF11
case 0xcd : // SOF13
case 0xce : // SOF14
case 0xcf : // SOF15
{
sal_uInt8 nSamplePrecision = 0;
sal_uInt16 nNumberOfLines = 0;
sal_uInt16 nSamplesPerLine = 0;
sal_uInt8 nNumberOfImageComponents = 0;
sal_uInt8 nComponentsIdentifier = 0;
sal_uInt8 nSamplingFactor = 0;
sal_uInt8 nQuantizationTableDestinationSelector = 0;
rStm.ReadUChar( nSamplePrecision )
.ReadUInt16( nNumberOfLines )
.ReadUInt16( nSamplesPerLine )
.ReadUChar( nNumberOfImageComponents )
.ReadUChar( nComponentsIdentifier )
.ReadUChar( nSamplingFactor )
.ReadUChar( nQuantizationTableDestinationSelector );
mnNumberOfImageComponents = nNumberOfImageComponents;
// nSamplingFactor (lower nibble: vertical,
// upper nibble: horizontal) is unused
aPixSize.setHeight( nNumberOfLines );
aPixSize.setWidth( nSamplesPerLine );
nBitsPerPixel = ( nNumberOfImageComponents == 3 ? 24 : nNumberOfImageComponents == 1 ? 8 : 0 );
nPlanes = 1;
if (aMap.GetMapUnit() != MapUnit::MapPixel)
// We already know the DPI, but the
// pixel size arrived later, so do the
// conversion again.
aLogSize = OutputDevice::LogicToLogic(
aPixSize, aMap, MapMode(MapUnit::Map100thMM));
bScanFinished = true;
}
break;
}
rStm.Seek( nNextMarkerPos );
}
}
break;
}
}
rStm.SetError( nError );
}
}
rStm.Seek( nStmPos );
return bRet;
}
bool GraphicDescriptor::ImpDetectPCD( SvStream& rStm, bool )
{
bool bRet = false;
sal_Int32 nStmPos = rStm.Tell();
rStm.SetEndian( SvStreamEndian::LITTLE );
sal_uInt32 nTemp32 = 0;
sal_uInt16 nTemp16 = 0;
sal_uInt8 cByte = 0;
rStm.SeekRel( 2048 );
rStm.ReadUInt32( nTemp32 );
rStm.ReadUInt16( nTemp16 );
rStm.ReadUChar( cByte );
if ( ( nTemp32 == 0x5f444350 ) &&
( nTemp16 == 0x5049 ) &&
( cByte == 0x49 ) )
{
nFormat = GraphicFileFormat::PCD;
bRet = true;
}
rStm.Seek( nStmPos );
return bRet;
}
bool GraphicDescriptor::ImpDetectPCX( SvStream& rStm, bool bExtendedInfo )
{
// ! Because 0x0a can be interpreted as LF too ...
// we can't be sure that this special sign represent a PCX file only.
// Every Ascii file is possible here :-(
// We must detect the whole header.
bExtendedInfo = true;
bool bRet = false;
sal_uInt8 cByte = 0;
sal_Int32 nStmPos = rStm.Tell();
rStm.SetEndian( SvStreamEndian::LITTLE );
rStm.ReadUChar( cByte );
if ( cByte == 0x0a )
{
nFormat = GraphicFileFormat::PCX;
bRet = true;
if ( bExtendedInfo )
{
sal_uInt16 nTemp16;
sal_uInt16 nXmin;
sal_uInt16 nXmax;
sal_uInt16 nYmin;
sal_uInt16 nYmax;
sal_uInt16 nDPIx;
sal_uInt16 nDPIy;
rStm.SeekRel( 1 );
// compression
rStm.ReadUChar( cByte );
bRet = (cByte==0 || cByte ==1);
if (bRet)
{
// Bits/Pixel
rStm.ReadUChar( cByte );
nBitsPerPixel = cByte;
// image dimensions
rStm.ReadUInt16( nTemp16 );
nXmin = nTemp16;
rStm.ReadUInt16( nTemp16 );
nYmin = nTemp16;
rStm.ReadUInt16( nTemp16 );
nXmax = nTemp16;
rStm.ReadUInt16( nTemp16 );
nYmax = nTemp16;
aPixSize.setWidth( nXmax - nXmin + 1 );
aPixSize.setHeight( nYmax - nYmin + 1 );
// resolution
rStm.ReadUInt16( nTemp16 );
nDPIx = nTemp16;
rStm.ReadUInt16( nTemp16 );
nDPIy = nTemp16;
// set logical size
MapMode aMap( MapUnit::MapInch, Point(),
Fraction( 1, nDPIx ), Fraction( 1, nDPIy ) );
aLogSize = OutputDevice::LogicToLogic( aPixSize, aMap,
MapMode( MapUnit::Map100thMM ) );
// number of color planes
cByte = 5; // Illegal value in case of EOF.
rStm.SeekRel( 49 );
rStm.ReadUChar( cByte );
nPlanes = cByte;
bRet = (nPlanes<=4);
}
}
}
rStm.Seek( nStmPos );
return bRet;
}
bool GraphicDescriptor::ImpDetectPNG( SvStream& rStm, bool bExtendedInfo )
{
sal_uInt32 nTemp32 = 0;
bool bRet = false;
sal_Int32 nStmPos = rStm.Tell();
rStm.SetEndian( SvStreamEndian::BIG );
rStm.ReadUInt32( nTemp32 );
if ( nTemp32 == 0x89504e47 )
{
rStm.ReadUInt32( nTemp32 );
if ( nTemp32 == 0x0d0a1a0a )
{
nFormat = GraphicFileFormat::PNG;
bRet = true;
if ( bExtendedInfo )
{
sal_uInt8 cByte = 0;
// IHDR-Chunk
rStm.SeekRel( 8 );
// width
rStm.ReadUInt32( nTemp32 );
aPixSize.setWidth( nTemp32 );
// height
rStm.ReadUInt32( nTemp32 );
aPixSize.setHeight( nTemp32 );
// Bits/Pixel
rStm.ReadUChar( cByte );
nBitsPerPixel = cByte;
// Planes always 1;
// compression always
nPlanes = 1;
sal_uInt32 nLen32 = 0;
nTemp32 = 0;
rStm.SeekRel( 8 );
// read up to the pHYs-Chunk or the start of the image
rStm.ReadUInt32( nLen32 );
rStm.ReadUInt32( nTemp32 );
while( ( nTemp32 != 0x70485973 ) && ( nTemp32 != 0x49444154 )
&& rStm.good() )
{
rStm.SeekRel( 4 + nLen32 );
rStm.ReadUInt32( nLen32 );
rStm.ReadUInt32( nTemp32 );
}
if (nTemp32 == 0x70485973 && rStm.good())
{
sal_uLong nXRes;
sal_uLong nYRes;
// horizontal resolution
nTemp32 = 0;
rStm.ReadUInt32( nTemp32 );
nXRes = nTemp32;
// vertical resolution
nTemp32 = 0;
rStm.ReadUInt32( nTemp32 );
nYRes = nTemp32;
// unit
cByte = 0;
rStm.ReadUChar( cByte );
if ( cByte )
{
if ( nXRes )
aLogSize.setWidth( (aPixSize.Width() * 100000) / nXRes );
if ( nYRes )
aLogSize.setHeight( (aPixSize.Height() * 100000) / nYRes );
}
}
}
}
}
rStm.Seek( nStmPos );
return bRet;
}
bool GraphicDescriptor::ImpDetectTIF( SvStream& rStm, bool bExtendedInfo )
{
bool bRet = false;
sal_uInt8 cByte1 = 0;
sal_uInt8 cByte2 = 1;
sal_Int32 nStmPos = rStm.Tell();
rStm.ReadUChar( cByte1 );
rStm.ReadUChar( cByte2 );
if ( cByte1 == cByte2 )
{
bool bDetectOk = false;
if ( cByte1 == 0x49 )
{
rStm.SetEndian( SvStreamEndian::LITTLE );
bDetectOk = true;
}
else if ( cByte1 == 0x4d )
{
rStm.SetEndian( SvStreamEndian::BIG );
bDetectOk = true;
}
if ( bDetectOk )
{
sal_uInt16 nTemp16 = 0;
rStm.ReadUInt16( nTemp16 );
if ( nTemp16 == 0x2a )
{
nFormat = GraphicFileFormat::TIF;
bRet = true;
if ( bExtendedInfo )
{
sal_uLong nCount;
sal_uLong nMax = DATA_SIZE - 48;
sal_uInt32 nTemp32 = 0;
// Offset of the first IFD
rStm.ReadUInt32( nTemp32 );
rStm.SeekRel( ( nCount = ( nTemp32 + 2 ) ) - 0x08 );
if ( nCount < nMax )
{
bool bOk = false;
// read tags till we find Tag256 ( Width )
// do not read more bytes than DATA_SIZE
rStm.ReadUInt16( nTemp16 );
while ( nTemp16 != 256 )
{
bOk = nCount < nMax;
if ( !bOk )
{
break;
}
rStm.SeekRel( 10 );
rStm.ReadUInt16( nTemp16 );
nCount += 12;
}
if ( bOk )
{
// width
rStm.ReadUInt16( nTemp16 );
rStm.SeekRel( 4 );
if ( nTemp16 == 3 )
{
rStm.ReadUInt16( nTemp16 );
aPixSize.setWidth( nTemp16 );
rStm.SeekRel( 2 );
}
else
{
rStm.ReadUInt32( nTemp32 );
aPixSize.setWidth( nTemp32 );
}
// height
rStm.SeekRel( 2 );
rStm.ReadUInt16( nTemp16 );
rStm.SeekRel( 4 );
if ( nTemp16 == 3 )
{
rStm.ReadUInt16( nTemp16 );
aPixSize.setHeight( nTemp16 );
rStm.SeekRel( 2 );
}
else
{
rStm.ReadUInt32( nTemp32 );
aPixSize.setHeight( nTemp32 );
}
// Bits/Pixel
rStm.ReadUInt16( nTemp16 );
if ( nTemp16 == 258 )
{
rStm.SeekRel( 6 );
rStm.ReadUInt16( nTemp16 );
nBitsPerPixel = nTemp16;
rStm.SeekRel( 2 );
}
else
rStm.SeekRel( -2 );
// compression
rStm.ReadUInt16( nTemp16 );
if ( nTemp16 == 259 )
{
rStm.SeekRel( 6 );
rStm.ReadUInt16( nTemp16 ); // compression
rStm.SeekRel( 2 );
}
else
rStm.SeekRel( -2 );
}
}
}
}
}
}
rStm.Seek( nStmPos );
return bRet;
}
bool GraphicDescriptor::ImpDetectXBM( SvStream&, bool )
{
bool bRet = aPathExt.startsWith( "xbm" );
if (bRet)
nFormat = GraphicFileFormat::XBM;
return bRet;
}
bool GraphicDescriptor::ImpDetectXPM( SvStream&, bool )
{
bool bRet = aPathExt.startsWith( "xpm" );
if (bRet)
nFormat = GraphicFileFormat::XPM;
return bRet;
}
bool GraphicDescriptor::ImpDetectPBM( SvStream& rStm, bool )
{
bool bRet = false;
// check file extension first, as this trumps the 2 ID bytes
if ( aPathExt.startsWith( "pbm" ) )
bRet = true;
else
{
sal_Int32 nStmPos = rStm.Tell();
sal_uInt8 nFirst = 0, nSecond = 0;
rStm.ReadUChar( nFirst ).ReadUChar( nSecond );
if ( nFirst == 'P' && ( ( nSecond == '1' ) || ( nSecond == '4' ) ) )
bRet = true;
rStm.Seek( nStmPos );
}
if ( bRet )
nFormat = GraphicFileFormat::PBM;
return bRet;
}
bool GraphicDescriptor::ImpDetectPGM( SvStream& rStm, bool )
{
bool bRet = false;
if ( aPathExt.startsWith( "pgm" ) )
bRet = true;
else
{
sal_uInt8 nFirst = 0, nSecond = 0;
sal_Int32 nStmPos = rStm.Tell();
rStm.ReadUChar( nFirst ).ReadUChar( nSecond );
if ( nFirst == 'P' && ( ( nSecond == '2' ) || ( nSecond == '5' ) ) )
bRet = true;
rStm.Seek( nStmPos );
}
if ( bRet )
nFormat = GraphicFileFormat::PGM;
return bRet;
}
bool GraphicDescriptor::ImpDetectPPM( SvStream& rStm, bool )
{
bool bRet = false;
if ( aPathExt.startsWith( "ppm" ) )
bRet = true;
else
{
sal_uInt8 nFirst = 0, nSecond = 0;
sal_Int32 nStmPos = rStm.Tell();
rStm.ReadUChar( nFirst ).ReadUChar( nSecond );
if ( nFirst == 'P' && ( ( nSecond == '3' ) || ( nSecond == '6' ) ) )
bRet = true;
rStm.Seek( nStmPos );
}
if ( bRet )
nFormat = GraphicFileFormat::PPM;
return bRet;
}
bool GraphicDescriptor::ImpDetectRAS( SvStream& rStm, bool )
{
sal_uInt32 nMagicNumber = 0;
bool bRet = false;
sal_Int32 nStmPos = rStm.Tell();
rStm.SetEndian( SvStreamEndian::BIG );
rStm.ReadUInt32( nMagicNumber );
if ( nMagicNumber == 0x59a66a95 )
{
nFormat = GraphicFileFormat::RAS;
bRet = true;
}
rStm.Seek( nStmPos );
return bRet;
}
bool GraphicDescriptor::ImpDetectTGA( SvStream&, bool )
{
bool bRet = aPathExt.startsWith( "tga" );
if (bRet)
nFormat = GraphicFileFormat::TGA;
return bRet;
}
bool GraphicDescriptor::ImpDetectPSD( SvStream& rStm, bool bExtendedInfo )
{
bool bRet = false;
sal_uInt32 nMagicNumber = 0;
sal_Int32 nStmPos = rStm.Tell();
rStm.SetEndian( SvStreamEndian::BIG );
rStm.ReadUInt32( nMagicNumber );
if ( nMagicNumber == 0x38425053 )
{
sal_uInt16 nVersion = 0;
rStm.ReadUInt16( nVersion );
if ( nVersion == 1 )
{
bRet = true;
if ( bExtendedInfo )
{
sal_uInt16 nChannels = 0;
sal_uInt32 nRows = 0;
sal_uInt32 nColumns = 0;
sal_uInt16 nDepth = 0;
sal_uInt16 nMode = 0;
rStm.SeekRel( 6 ); // Pad
rStm.ReadUInt16( nChannels ).ReadUInt32( nRows ).ReadUInt32( nColumns ).ReadUInt16( nDepth ).ReadUInt16( nMode );
if ( ( nDepth == 1 ) || ( nDepth == 8 ) || ( nDepth == 16 ) )
{
nBitsPerPixel = ( nDepth == 16 ) ? 8 : nDepth;
switch ( nChannels )
{
case 4 :
case 3 :
nBitsPerPixel = 24;
SAL_FALLTHROUGH;
case 2 :
case 1 :
aPixSize.setWidth( nColumns );
aPixSize.setHeight( nRows );
break;
default:
bRet = false;
}
}
else
bRet = false;
}
}
}
if ( bRet )
nFormat = GraphicFileFormat::PSD;
rStm.Seek( nStmPos );
return bRet;
}
bool GraphicDescriptor::ImpDetectEPS( SvStream& rStm, bool )
{
// check the EPS preview and the file extension
sal_uInt32 nFirstLong = 0;
sal_uInt8 nFirstBytes[20];
bool bRet = false;
memset(nFirstBytes, 0, sizeof (nFirstBytes));
sal_Int32 nStmPos = rStm.Tell();
rStm.SetEndian( SvStreamEndian::BIG );
rStm.ReadUInt32( nFirstLong );
rStm.SeekRel( -4 );
rStm.ReadBytes( &nFirstBytes, 20 );
if ( ( nFirstLong == 0xC5D0D3C6 ) || aPathExt.startsWith( "eps" ) ||
( ImplSearchEntry( nFirstBytes, reinterpret_cast<sal_uInt8 const *>("%!PS-Adobe"), 10, 10 )
&& ImplSearchEntry( &nFirstBytes[15], reinterpret_cast<sal_uInt8 const *>("EPS"), 3, 3 ) ) )
{
nFormat = GraphicFileFormat::EPS;
bRet = true;
}
rStm.Seek( nStmPos );
return bRet;
}
bool GraphicDescriptor::ImpDetectDXF( SvStream&, bool )
{
bool bRet = aPathExt.startsWith( "dxf" );
if (bRet)
nFormat = GraphicFileFormat::DXF;
return bRet;
}
bool GraphicDescriptor::ImpDetectMET( SvStream&, bool )
{
bool bRet = aPathExt.startsWith( "met" );
if (bRet)
nFormat = GraphicFileFormat::MET;
return bRet;
}
bool GraphicDescriptor::ImpDetectPCT( SvStream& rStm, bool )
{
bool bRet = aPathExt.startsWith( "pct" );
if (bRet)
nFormat = GraphicFileFormat::PCT;
else
{
sal_uInt64 const nStreamPos = rStm.Tell();
sal_uInt64 const nStreamLen = rStm.remainingSize();
if (isPCT(rStm, nStreamPos, nStreamLen))
{
bRet = true;
nFormat = GraphicFileFormat::PCT;
}
rStm.Seek(nStreamPos);
}
return bRet;
}
bool GraphicDescriptor::ImpDetectSVM( SvStream& rStm, bool bExtendedInfo )
{
sal_uInt32 n32 = 0;
bool bRet = false;
sal_uInt8 cByte = 0;
sal_Int32 nStmPos = rStm.Tell();
rStm.SetEndian( SvStreamEndian::LITTLE );
rStm.ReadUInt32( n32 );
if ( n32 == 0x44475653 )
{
cByte = 0;
rStm.ReadUChar( cByte );
if ( cByte == 0x49 )
{
nFormat = GraphicFileFormat::SVM;
bRet = true;
if ( bExtendedInfo )
{
sal_uInt32 nTemp32;
sal_uInt16 nTemp16;
rStm.SeekRel( 0x04 );
// width
nTemp32 = 0;
rStm.ReadUInt32( nTemp32 );
aLogSize.setWidth( nTemp32 );
// height
nTemp32 = 0;
rStm.ReadUInt32( nTemp32 );
aLogSize.setHeight( nTemp32 );
// read MapUnit and determine PrefSize
nTemp16 = 0;
rStm.ReadUInt16( nTemp16 );
aLogSize = OutputDevice::LogicToLogic( aLogSize,
MapMode( static_cast<MapUnit>(nTemp16) ),
MapMode( MapUnit::Map100thMM ) );
}
}
}
else
{
rStm.SeekRel( -4 );
n32 = 0;
rStm.ReadUInt32( n32 );
if( n32 == 0x4D4C4356 )
{
sal_uInt16 nTmp16 = 0;
rStm.ReadUInt16( nTmp16 );
if( nTmp16 == 0x4654 )
{
nFormat = GraphicFileFormat::SVM;
bRet = true;
if( bExtendedInfo )
{
MapMode aMapMode;
rStm.SeekRel( 0x06 );
ReadMapMode( rStm, aMapMode );
ReadPair( rStm, aLogSize );
aLogSize = OutputDevice::LogicToLogic( aLogSize, aMapMode, MapMode( MapUnit::Map100thMM ) );
}
}
}
}
rStm.Seek( nStmPos );
return bRet;
}
bool GraphicDescriptor::ImpDetectWMF( SvStream&, bool )
{
bool bRet = aPathExt.startsWith( "wmf" );
if (bRet)
nFormat = GraphicFileFormat::WMF;
return bRet;
}
bool GraphicDescriptor::ImpDetectEMF( SvStream&, bool )
{
bool bRet = aPathExt.startsWith( "emf" );
if (bRet)
nFormat = GraphicFileFormat::EMF;
return bRet;
}
bool GraphicDescriptor::ImpDetectSVG( SvStream& /*rStm*/, bool /*bExtendedInfo*/ )
{
bool bRet = aPathExt.startsWith( "svg" );
if (bRet)
nFormat = GraphicFileFormat::SVG;
return bRet;
}
OUString GraphicDescriptor::GetImportFormatShortName( GraphicFileFormat nFormat )
{
const char *pKeyName = nullptr;
switch( nFormat )
{
case GraphicFileFormat::BMP : pKeyName = "bmp"; break;
case GraphicFileFormat::GIF : pKeyName = "gif"; break;
case GraphicFileFormat::JPG : pKeyName = "jpg"; break;
case GraphicFileFormat::PCD : pKeyName = "pcd"; break;
case GraphicFileFormat::PCX : pKeyName = "pcx"; break;
case GraphicFileFormat::PNG : pKeyName = "png"; break;
case GraphicFileFormat::XBM : pKeyName = "xbm"; break;
case GraphicFileFormat::XPM : pKeyName = "xpm"; break;
case GraphicFileFormat::PBM : pKeyName = "pbm"; break;
case GraphicFileFormat::PGM : pKeyName = "pgm"; break;
case GraphicFileFormat::PPM : pKeyName = "ppm"; break;
case GraphicFileFormat::RAS : pKeyName = "ras"; break;
case GraphicFileFormat::TGA : pKeyName = "tga"; break;
case GraphicFileFormat::PSD : pKeyName = "psd"; break;
case GraphicFileFormat::EPS : pKeyName = "eps"; break;
case GraphicFileFormat::TIF : pKeyName = "tif"; break;
case GraphicFileFormat::DXF : pKeyName = "dxf"; break;
case GraphicFileFormat::MET : pKeyName = "met"; break;
case GraphicFileFormat::PCT : pKeyName = "pct"; break;
case GraphicFileFormat::SVM : pKeyName = "svm"; break;
case GraphicFileFormat::WMF : pKeyName = "wmf"; break;
case GraphicFileFormat::EMF : pKeyName = "emf"; break;
case GraphicFileFormat::SVG : pKeyName = "svg"; break;
default: assert(false);
}
return OUString::createFromAscii(pKeyName);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V763 Parameter 'bExtendedInfo' is always rewritten in function body before being used.
↑ V547 Expression 'bExtendedInfo' is always true.