blob: 3c5be5aa000c0a00f9094b07a58012e4b1fc9d07 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_filter.hxx"
#include <vcl/graph.hxx>
#include <vcl/bmpacc.hxx>
#include <svtools/fltcall.hxx>
#define RAS_TYPE_OLD 0x00000000 // supported formats by this filter
#define RAS_TYPE_STANDARD 0x00000001
#define RAS_TYPE_BYTE_ENCODED 0x00000002
#define RAS_TYPE_RGB_FORMAT 0x00000003
#define RAS_COLOR_NO_MAP 0x00000000
#define RAS_COLOR_RGB_MAP 0x00000001
#define RAS_COLOR_RAW_MAP 0x00000002
#define SUNRASTER_MAGICNUMBER 0x59a66a95
//============================ RASReader ==================================
class RASReader {
private:
SvStream* mpRAS; // Die einzulesende RAS-Datei
sal_Bool mbStatus;
Bitmap maBmp;
BitmapWriteAccess* mpAcc;
sal_uInt32 mnWidth, mnHeight; // Bildausmass in Pixeln
sal_uInt16 mnDstBitsPerPix;
sal_uInt16 mnDstColors;
sal_uInt32 mnDepth, mnImageDatSize, mnType;
sal_uInt32 mnColorMapType, mnColorMapSize;
sal_uInt8 mnRepCount, mnRepVal; // RLE Decoding
sal_Bool mbPalette;
sal_Bool ImplReadBody();
sal_Bool ImplReadHeader();
sal_uInt8 ImplGetByte();
public:
RASReader();
~RASReader();
sal_Bool ReadRAS( SvStream & rRAS, Graphic & rGraphic );
};
//=================== Methoden von RASReader ==============================
RASReader::RASReader() :
mbStatus ( sal_True ),
mpAcc ( NULL ),
mnRepCount ( 0 ),
mbPalette ( sal_False )
{
}
RASReader::~RASReader()
{
}
//----------------------------------------------------------------------------
sal_Bool RASReader::ReadRAS( SvStream & rRAS, Graphic & rGraphic )
{
sal_uInt32 nMagicNumber;
if ( rRAS.GetError() )
return sal_False;
mpRAS = &rRAS;
mpRAS->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
*mpRAS >> nMagicNumber;
if ( nMagicNumber != SUNRASTER_MAGICNUMBER )
return sal_False;
// Kopf einlesen:
if ( ( mbStatus = ImplReadHeader() ) == sal_False )
return sal_False;
maBmp = Bitmap( Size( mnWidth, mnHeight ), mnDstBitsPerPix );
mpAcc = maBmp.AcquireWriteAccess();
if ( !mpAcc )
return sal_False;
if ( mnDstBitsPerPix <= 8 ) // paletten bildchen
{
if ( mnColorMapType == RAS_COLOR_RAW_MAP ) // RAW Colormap wird geskipped
{
sal_uLong nCurPos = mpRAS->Tell();
mpRAS->Seek( nCurPos + mnColorMapSize );
}
else if ( mnColorMapType == RAS_COLOR_RGB_MAP ) // RGB koennen wir auslesen
{
mnDstColors = (sal_uInt16)( mnColorMapSize / 3 );
if ( ( 1 << mnDstBitsPerPix ) < mnDstColors )
return sal_False;
if ( ( mnDstColors >= 2 ) && ( ( mnColorMapSize % 3 ) == 0 ) )
{
mpAcc->SetPaletteEntryCount( mnDstColors );
sal_uInt16 i;
sal_uInt8 nRed[256], nGreen[256], nBlue[256];
for ( i = 0; i < mnDstColors; i++ ) *mpRAS >> nRed[ i ];
for ( i = 0; i < mnDstColors; i++ ) *mpRAS >> nGreen[ i ];
for ( i = 0; i < mnDstColors; i++ ) *mpRAS >> nBlue[ i ];
for ( i = 0; i < mnDstColors; i++ )
{
mpAcc->SetPaletteColor( i, BitmapColor( nRed[ i ], nGreen[ i ], nBlue[ i ] ) );
}
mbPalette = sal_True;
}
else
return sal_False;
}
else if ( mnColorMapType != RAS_COLOR_NO_MAP ) // alles andere ist kein standard
return sal_False;
if ( !mbPalette )
{
mnDstColors = 1 << mnDstBitsPerPix;
mpAcc->SetPaletteEntryCount( mnDstColors );
for ( sal_uInt16 i = 0; i < mnDstColors; i++ )
{
sal_uLong nCount = 255 - ( 255 * i / ( mnDstColors - 1 ) );
mpAcc->SetPaletteColor( i, BitmapColor( (sal_uInt8)nCount, (sal_uInt8)nCount, (sal_uInt8)nCount ) );
}
}
}
else
{
if ( mnColorMapType != RAS_COLOR_NO_MAP ) // when graphic has more then 256 colors and a color map we skip
{ // the colormap
sal_uLong nCurPos = mpRAS->Tell();
mpRAS->Seek( nCurPos + mnColorMapSize );
}
}
// Bitmap-Daten einlesen
mbStatus = ImplReadBody();
if ( mpAcc )
{
maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
}
if ( mbStatus )
rGraphic = maBmp;
return mbStatus;
}
//----------------------------------------------------------------------------
sal_Bool RASReader::ImplReadHeader()
{
*mpRAS >> mnWidth >> mnHeight >> mnDepth >> mnImageDatSize >>
mnType >> mnColorMapType >> mnColorMapSize;
if ( mnWidth == 0 || mnHeight == 0 )
mbStatus = sal_False;
switch ( mnDepth )
{
case 24 :
case 8 :
case 1 :
mnDstBitsPerPix = (sal_uInt16)mnDepth;
break;
case 32 :
mnDstBitsPerPix = 24;
break;
default :
mbStatus = sal_False;
}
switch ( mnType )
{
case RAS_TYPE_OLD :
case RAS_TYPE_STANDARD :
case RAS_TYPE_RGB_FORMAT :
case RAS_TYPE_BYTE_ENCODED : // this type will be supported later
break;
default:
mbStatus = sal_False;
}
return mbStatus;
}
//----------------------------------------------------------------------------
sal_Bool RASReader::ImplReadBody()
{
sal_uLong x, y;
sal_uInt8 nDat = 0;
sal_uInt8 nRed, nGreen, nBlue;
switch ( mnDstBitsPerPix )
{
case 1 :
for ( y = 0; y < mnHeight; y++ )
{
for ( x = 0; x < mnWidth; x++ )
{
if (!(x & 7))
nDat = ImplGetByte();
mpAcc->SetPixelIndex( y, x,
sal::static_int_cast< sal_uInt8 >(
nDat >> ( ( x & 7 ) ^ 7 )) );
}
if (!( ( x - 1 ) & 0x8 ) ) ImplGetByte(); // WORD ALIGNMENT ???
}
break;
case 8 :
for ( y = 0; y < mnHeight; y++ )
{
for ( x = 0; x < mnWidth; x++ )
{
nDat = ImplGetByte();
mpAcc->SetPixelIndex( y, x, nDat );
}
if ( x & 1 ) ImplGetByte(); // WORD ALIGNMENT ???
}
break;
case 24 :
switch ( mnDepth )
{
case 24 :
for ( y = 0; y < mnHeight; y++ )
{
for ( x = 0; x < mnWidth; x++ )
{
if ( mnType == RAS_TYPE_RGB_FORMAT )
{
nRed = ImplGetByte();
nGreen = ImplGetByte();
nBlue = ImplGetByte();
}
else
{
nBlue = ImplGetByte();
nGreen = ImplGetByte();
nRed = ImplGetByte();
}
mpAcc->SetPixel ( y, x, BitmapColor( nRed, nGreen, nBlue ) );
}
if ( x & 1 ) ImplGetByte(); // WORD ALIGNMENT ???
}
break;
case 32 :
for ( y = 0; y < mnHeight; y++ )
{
for ( x = 0; x < mnWidth; x++ )
{
nDat = ImplGetByte(); // pad byte > nil
if ( mnType == RAS_TYPE_RGB_FORMAT )
{
nRed = ImplGetByte();
nGreen = ImplGetByte();
nBlue = ImplGetByte();
}
else
{
nBlue = ImplGetByte();
nGreen = ImplGetByte();
nRed = ImplGetByte();
}
mpAcc->SetPixel ( y, x, BitmapColor( nRed, nGreen, nBlue ) );
}
}
break;
}
break;
default:
mbStatus = sal_False;
break;
}
return mbStatus;
}
//----------------------------------------------------------------------------
sal_uInt8 RASReader::ImplGetByte()
{
sal_uInt8 nRetVal;
if ( mnType != RAS_TYPE_BYTE_ENCODED )
{
*mpRAS >> nRetVal;
return nRetVal;
}
else
{
if ( mnRepCount )
{
mnRepCount--;
return mnRepVal;
}
else
{
*mpRAS >> nRetVal;
if ( nRetVal != 0x80 )
return nRetVal;
*mpRAS >> nRetVal;
if ( nRetVal == 0 )
return 0x80;
mnRepCount = nRetVal ;
*mpRAS >> mnRepVal;
return mnRepVal;
}
}
}
//================== GraphicImport - die exportierte Funktion ================
extern "C" sal_Bool __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, sal_Bool )
{
RASReader aRASReader;
return aRASReader.ReadRAS( rStream, rGraphic );
}