blob: fc79b71dd026799db47fc29a69c2ed530547b72a [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>
//============================ PBMReader ==================================
class PBMReader {
private:
SvStream* mpPBM; // Die einzulesende PBM-Datei
sal_Bool mbStatus;
sal_Bool mbRemark; // sal_False wenn sich stream in einem Kommentar befindet
sal_Bool mbRaw; // RAW/ASCII MODE
sal_uLong mnMode; // 0->PBM, 1->PGM, 2->PPM
Bitmap maBmp;
BitmapWriteAccess* mpAcc;
sal_uLong mnWidth, mnHeight; // Bildausmass in Pixeln
sal_uLong mnCol;
sal_uLong mnMaxVal; // maximaler wert in den
sal_Bool ImplCallback( sal_uInt16 nPercent );
sal_Bool ImplReadBody();
sal_Bool ImplReadHeader();
public:
PBMReader();
~PBMReader();
sal_Bool ReadPBM( SvStream & rPBM, Graphic & rGraphic );
};
//=================== Methoden von PBMReader ==============================
PBMReader::PBMReader() :
mbStatus ( sal_True ),
mbRemark ( sal_False ),
mbRaw ( sal_True ),
mpAcc ( NULL )
{
}
PBMReader::~PBMReader()
{
}
sal_Bool PBMReader::ImplCallback( sal_uInt16 /*nPercent*/ )
{
/*
if ( pCallback != NULL )
{
if ( ( (*pCallback)( pCallerData, nPercent ) ) == sal_True )
{
mpPBM->SetError( SVSTREAM_FILEFORMAT_ERROR );
return sal_True;
}
}
*/
return sal_False;
}
sal_Bool PBMReader::ReadPBM( SvStream & rPBM, Graphic & rGraphic )
{
sal_uInt16 i;
if ( rPBM.GetError() )
return sal_False;
mpPBM = &rPBM;
mpPBM->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
// Kopf einlesen:
if ( ( mbStatus = ImplReadHeader() ) == sal_False )
return sal_False;
if ( ( mnMaxVal == 0 ) || ( mnWidth == 0 ) || ( mnHeight == 0 ) )
return sal_False;
// 0->PBM, 1->PGM, 2->PPM
switch ( mnMode )
{
case 0 :
maBmp = Bitmap( Size( mnWidth, mnHeight ), 1 );
mpAcc = maBmp.AcquireWriteAccess();
if ( !mpAcc )
return sal_False;
mpAcc->SetPaletteEntryCount( 2 );
mpAcc->SetPaletteColor( 0, BitmapColor( 0xff, 0xff, 0xff ) );
mpAcc->SetPaletteColor( 1, BitmapColor( 0x00, 0x00, 0x00 ) );
break;
case 1 :
if ( mnMaxVal <= 1 )
maBmp = Bitmap( Size( mnWidth, mnHeight ), 1);
else if ( mnMaxVal <= 15 )
maBmp = Bitmap( Size( mnWidth, mnHeight ), 4);
else
maBmp = Bitmap( Size( mnWidth, mnHeight ), 8);
mpAcc = maBmp.AcquireWriteAccess();
if ( !mpAcc )
return sal_False;
mnCol = (sal_uInt16)mnMaxVal + 1;
if ( mnCol > 256 )
mnCol = 256;
mpAcc->SetPaletteEntryCount( 256 );
for ( i = 0; i < mnCol; i++ )
{
sal_uLong nCount = 255 * i / mnCol;
mpAcc->SetPaletteColor( i, BitmapColor( (sal_uInt8)nCount, (sal_uInt8)nCount, (sal_uInt8)nCount ) );
}
break;
case 2 :
maBmp = Bitmap( Size( mnWidth, mnHeight ), 24 );
mpAcc = maBmp.AcquireWriteAccess();
if ( !mpAcc )
return sal_False;
break;
}
// Bitmap-Daten einlesen
mbStatus = ImplReadBody();
if ( mpAcc )
{
maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
}
if ( mbStatus )
rGraphic = maBmp;
return mbStatus;
}
sal_Bool PBMReader::ImplReadHeader()
{
sal_uInt8 nID[ 2 ];
sal_uInt8 nDat;
sal_uInt8 nMax, nCount = 0;
sal_Bool bFinished = sal_False;
*mpPBM >> nID[ 0 ] >> nID[ 1 ];
if ( nID[ 0 ] != 'P' )
return sal_False;
mnMaxVal = mnWidth = mnHeight = 0;
switch ( nID[ 1 ] )
{
case '1' :
mbRaw = sal_False;
case '4' :
mnMode = 0;
nMax = 2; // number of parameters in Header
mnMaxVal = 1;
break;
case '2' :
mbRaw = sal_False;
case '5' :
mnMode = 1;
nMax = 3;
break;
case '3' :
mbRaw = sal_False;
case '6' :
mnMode = 2;
nMax = 3;
break;
default:
return sal_False;
}
while ( bFinished == sal_False )
{
if ( mpPBM->GetError() )
return sal_False;
*mpPBM >> nDat;
if ( nDat == '#' )
{
mbRemark = sal_True;
continue;
}
else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
{
mbRemark = sal_False;
nDat = 0x20;
}
if ( mbRemark )
continue;
if ( ( nDat == 0x20 ) || ( nDat == 0x09 ) )
{
if ( ( nCount == 0 ) && mnWidth )
nCount++;
else if ( ( nCount == 1 ) && mnHeight )
{
if ( ++nCount == nMax )
bFinished = sal_True;
}
else if ( ( nCount == 2 ) && mnMaxVal )
{
bFinished = sal_True;
}
continue;
}
if ( ( nDat >= '0' ) && ( nDat <= '9' ) )
{
nDat -= '0';
if ( nCount == 0 )
{
mnWidth *= 10;
mnWidth += nDat;
}
else if ( nCount == 1 )
{
mnHeight *= 10;
mnHeight += nDat;
}
else if ( nCount == 2 )
{
mnMaxVal *= 10;
mnMaxVal += nDat;
}
}
else
return sal_False;
}
return mbStatus;
}
sal_Bool PBMReader::ImplReadBody()
{
sal_Bool bPara, bFinished = sal_False;
sal_uInt8 nDat = 0, nCount;
sal_uLong nGrey, nRGB[3];
sal_uLong nWidth = 0;
sal_uLong nHeight = 0;
signed char nShift = 0;
if ( mbRaw )
{
switch ( mnMode )
{
// PBM
case 0 :
while ( nHeight != mnHeight )
{
if ( mpPBM->IsEof() || mpPBM->GetError() )
return sal_False;
if ( --nShift < 0 )
{
*mpPBM >> nDat;
nShift = 7;
}
mpAcc->SetPixelIndex( nHeight, nWidth, nDat >> nShift );
if ( ++nWidth == mnWidth )
{
nShift = 0;
nWidth = 0;
nHeight++;
ImplCallback( (sal_uInt16)( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
}
}
break;
// PGM
case 1 :
while ( nHeight != mnHeight )
{
if ( mpPBM->IsEof() || mpPBM->GetError() )
return sal_False;
*mpPBM >> nDat;
mpAcc->SetPixelIndex( nHeight, nWidth++, nDat);
if ( nWidth == mnWidth )
{
nWidth = 0;
nHeight++;
ImplCallback( (sal_uInt16)( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
}
}
break;
// PPM
case 2 :
while ( nHeight != mnHeight )
{
if ( mpPBM->IsEof() || mpPBM->GetError() )
return sal_False;
sal_uInt8 nR, nG, nB;
sal_uLong nRed, nGreen, nBlue;
*mpPBM >> nR >> nG >> nB;
nRed = 255 * nR / mnMaxVal;
nGreen = 255 * nG / mnMaxVal;
nBlue = 255 * nB / mnMaxVal;
mpAcc->SetPixel( nHeight, nWidth++, BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
if ( nWidth == mnWidth )
{
nWidth = 0;
nHeight++;
ImplCallback( (sal_uInt16) ( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
}
}
break;
}
}
else switch ( mnMode )
{
// PBM
case 0 :
while ( bFinished == sal_False )
{
if ( mpPBM->IsEof() || mpPBM->GetError() )
return sal_False;
*mpPBM >> nDat;
if ( nDat == '#' )
{
mbRemark = sal_True;
continue;
}
else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
{
mbRemark = sal_False;
continue;
}
if ( mbRemark || nDat == 0x20 || nDat == 0x09 )
continue;
if ( nDat == '0' || nDat == '1' )
{
mpAcc->SetPixelIndex( nHeight, nWidth, static_cast<sal_uInt8>(nDat - '0') );
nWidth++;
if ( nWidth == mnWidth )
{
nWidth = 0;
if ( ++nHeight == mnHeight )
bFinished = sal_True;
ImplCallback( (sal_uInt16) ( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
}
}
else
return sal_False;
}
break;
// PGM
case 1 :
bPara = sal_False;
nCount = 0;
nGrey = 0;
while ( bFinished == sal_False )
{
if ( nCount )
{
nCount--;
if ( nGrey <= mnMaxVal )
nGrey = 255 * nGrey / mnMaxVal;
mpAcc->SetPixelIndex( nHeight, nWidth++, static_cast<sal_uInt8>(nGrey) );
nGrey = 0;
if ( nWidth == mnWidth )
{
nWidth = 0;
if ( ++nHeight == mnHeight )
bFinished = sal_True;
ImplCallback( (sal_uInt16) ( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
}
continue;
}
if ( mpPBM->IsEof() || mpPBM->GetError() )
return sal_False;
*mpPBM >> nDat;
if ( nDat == '#' )
{
mbRemark = sal_True;
if ( bPara )
{
bPara = sal_False;
nCount++;
}
continue;
}
else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
{
mbRemark = sal_False;
if ( bPara )
{
bPara = sal_False;
nCount++;
}
continue;
}
if ( nDat == 0x20 || nDat == 0x09 )
{
if ( bPara )
{
bPara = sal_False;
nCount++;
}
continue;
}
if ( nDat >= '0' && nDat <= '9' )
{
bPara = sal_True;
nGrey *= 10;
nGrey += nDat-'0';
continue;
}
else
return sal_False;
}
break;
// PPM
case 2 :
bPara = sal_False;
nCount = 0;
nRGB[ 0 ] = nRGB[ 1 ] = nRGB[ 2 ] = 0;
while ( bFinished == sal_False )
{
if ( nCount == 3 )
{
nCount = 0;
mpAcc->SetPixel( nHeight, nWidth++, BitmapColor( static_cast< sal_uInt8 >( ( nRGB[ 0 ] * 255 ) / mnMaxVal ),
static_cast< sal_uInt8 >( ( nRGB[ 1 ] * 255 ) / mnMaxVal ),
static_cast< sal_uInt8 >( ( nRGB[ 2 ] * 255 ) / mnMaxVal ) ) );
nCount = 0;
nRGB[ 0 ] = nRGB[ 1 ] = nRGB[ 2 ] = 0;
if ( nWidth == mnWidth )
{
nWidth = 0;
if ( ++nHeight == mnHeight )
bFinished = sal_True;
ImplCallback( (sal_uInt16) ( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
}
continue;
}
if ( mpPBM->IsEof() || mpPBM->GetError() )
return sal_False;
*mpPBM >> nDat;
if ( nDat == '#' )
{
mbRemark = sal_True;
if ( bPara )
{
bPara = sal_False;
nCount++;
}
continue;
}
else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
{
mbRemark = sal_False;
if ( bPara )
{
bPara = sal_False;
nCount++;
}
continue;
}
if ( nDat == 0x20 || nDat == 0x09 )
{
if ( bPara )
{
bPara = sal_False;
nCount++;
}
continue;
}
if ( nDat >= '0' && nDat <= '9' )
{
bPara = sal_True;
nRGB[ nCount ] *= 10;
nRGB[ nCount ] += nDat-'0';
continue;
}
else
return sal_False;
}
break;
}
return mbStatus;
}
//================== GraphicImport - die exportierte Funktion ================
extern "C" sal_Bool __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, sal_Bool )
{
PBMReader aPBMReader;
return aPBMReader.ReadPBM( rStream, rGraphic );
}