/* Import from Gabor API
Copyright (c) 2002-3 Adriaan Tijsseling
All Rights Reserved
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/*
Description: class for reading and storing pgm images
Author: Adriaan Tijsseling ( AGT )
Copyright: ( c ) Copyright 2002-3 Adriaan Tijsseling. All rights reserved.
*/
#include
#include "PGMImage.h"
using namespace std;
namespace celeste
{
// read PGM image from file
int PGMImage::Read( char* file )
{
int i,j;
char buf[256];
ifstream imgFile( file );
if ( !imgFile ) // Invalid FileName
{
cerr << "invalid filename: \"" << file << "\"" << endl;
exit(1);
return 0;
}
if ( mVerbosity ) cerr << "reading image from file \"" << file << "\"" << endl;
// get file type
imgFile.getline( mMagicNumber, 256 );
// ignore comments
imgFile.getline( buf, 256 );
while ( buf[0] == '#' ) imgFile.getline( buf, 256 );
// get dimensions of image
mWidth = atoi( buf );
mHeight = atoi( strpbrk( buf, " \t" ) );
mNumPixels = mWidth * mHeight;
// get color levels
if ( mMagicNumber[1] == '1' || mMagicNumber[1] == '4' )
{
mNumLevels = 1;
}
else
{
imgFile.getline( buf, 256 );
mNumLevels = atoi( buf );
}
// determine number of bits given image level
mNumBits = (int)( log( (float)( mNumLevels+2 ) )/log( 2.0 ) );
if ( mVerbosity ) cerr << "[" << mNumBits << "-bit ";
// read pixels
if ( mMagicNumber[1] == '5' || mMagicNumber[1] == '2' ) // GrayScale
{
// allocate pixel storage
Allocate( kChars );
if ( mMagicNumber[1] == '5' ) // RAWBITs
{
if ( mVerbosity ) cerr << "GrayScale RAWBITs PGM format]";
for ( i = 0; i < mHeight; i++ )
imgFile.read( (char *)mPixels[i], mWidth );
}
else // ASCII
{
if ( mVerbosity ) cerr << "GrayScale ASCII PGM format]";
for ( i = 0; i < mHeight; i++ )
{
for ( j = 0; j < mWidth; j++ )
{
int pix;
imgFile >> pix;
mPixels[i][j] = (unsigned char)( pix / pow( 2, (double)(mNumBits-8) ) );
}
}
}
}
else if ( mMagicNumber[1] == '6' || mMagicNumber[1] == '3' ) // RGB
{
unsigned char rgb[3];
// allocate rgb pixel storage
Allocate( kRGB );
if ( mMagicNumber[1] == '6' ) // RAWBITs
{
if ( mVerbosity ) cerr << "RGB RAWBITs PPM format]";
for ( i = 0; i < mHeight; i++ )
for ( j = 0; j < mWidth; j++ )
{
imgFile.read( (char *)rgb,3 );
mRGB[0][i][j] = (int)rgb[0];
mRGB[1][i][j] = (int)rgb[1];
mRGB[2][i][j] = (int)rgb[2];
}
}
else // ASCII
{
if ( mVerbosity ) cerr << "RGB ASCII PPM format]";
for ( i = 0; i < mHeight; i++ )
for ( j = 0; j < mWidth; j++ )
{
imgFile >> mRGB[0][i][j];
imgFile >> mRGB[1][i][j];
imgFile >> mRGB[2][i][j];
}
}
}
else if ( mMagicNumber[1] == '4' || mMagicNumber[1] == '1' ) // Binary
{
// allocate pixel storage
Allocate( kChars );
if ( mMagicNumber[1] == '4' ) // RAWBITs
{
if ( mVerbosity ) cerr << "Binary RAWBITs PBM format]";
for ( i = 0; i < mHeight; i++ )
for ( j = 0; j < mWidth; j += 8 )
{
char pix[1];
imgFile.read( pix, 1 );
unsigned int x = (unsigned int)pix[0];
for ( int k = 0; k < 8; k++ )
{
unsigned int y = x/( (unsigned int)pow( 2, (double)(7-k) ) );
if ( y )
mPixels[i][j+k] = 0;
else
mPixels[i][j+k] = 255;
x -= y*( (unsigned int)pow( 2, (double)(7-k) ) );
}
}
}
else
{
if ( mVerbosity ) cerr << "Binary ASCII PBM format]";
for ( i = 0; i < mHeight; i++ )
for ( j = 0; j < mWidth; j++ )
{
int pix;
imgFile >> pix;
if ( pix == 0 )
mPixels[i][j] = 0;
else
mPixels[i][j] = 255;
}
}
}
imgFile.close();
if ( mVerbosity )
{
cerr << endl;
cerr << "\twidth = " << mWidth << endl;
cerr << "\theight = " << mHeight << endl;
cerr << "\t#pixels = " << mNumPixels << endl;
}
mNumLevels = 255;
mNumBits = 8;
mMagicNumber[1] = '5';
return 1; // No error encountered....successful completion
}
// write PGM image to file
void PGMImage::Write( char* file )
{
ofstream outfile( file );
if ( mVerbosity )
{
//cerr << "writing " << mWidth << "x" << mHeight;
//cerr << " image to file1 \"" << file << "\"...";
}
outfile << mMagicNumber[0] << mMagicNumber[1] << endl; // 8-bit grayscale
outfile << "# grayscale image" << endl;
outfile << mWidth << " " << mHeight << endl;
outfile << mNumLevels << endl;
for ( int i = 0; i < mHeight; i++ )
outfile.write( (char *)mPixels[i], mWidth );
outfile.close();
//if ( mVerbosity ) cerr << "done" << endl;
}
// Write a PGM image in a file from output as is
void PGMImage::Write( char* filename, float** output, int height, int width )
{
int i, j;
// clear old data first
Deallocate();
// set dimensions of pixelmap and allocate memory
mWidth = width;
mHeight = height;
mMagicNumber[0] = 'P';
mMagicNumber[1] = '5';
mNumLevels = 255;
Allocate( kChars );
for( i = 0; i < mHeight; i++ )
for( j = 0; j < mWidth; j++ )
mPixels[i][j] = (unsigned char)output[i][j];
Write( filename );
}
// Write a color PPM image in a file
void PGMImage::Write( char* filename, float*** pixels, int height, int width )
{
ofstream outfile( filename );
unsigned char rgb[3];
// set dimensions of pixelmap and allocate memory
//if ( mVerbosity ) cerr << "writing " << width << "x" << height;
//if ( mVerbosity ) cerr << " image to file2 \"" << filename << "\"...";
outfile << "P6" << endl; // 8-bit color
outfile << "# color image" << endl;
outfile << width << " " << height << endl;
outfile << 255 << endl;
for ( int i = 0; i < height; i++ )
for ( int j = 0; j < width; j++ )
{
rgb[0] = (unsigned char)(pixels[0][i][j]*255.0);
rgb[1] = (unsigned char)(pixels[1][i][j]*255.0);
rgb[2] = (unsigned char)(pixels[2][i][j]*255.0);
outfile.write( (char *)rgb, 3 );
}
outfile.close();
//if ( mVerbosity ) cerr << "done" << endl;
}
// Write a one-channel color PPM image in a file
void PGMImage::Write( char* filename, float** pixels, int height, int width, int channel )
{
ofstream outfile( filename );
unsigned char rgb[3];
float max, min, maxmin;
int i, j;
// set dimensions of pixelmap and allocate memory
//if ( mVerbosity ) cerr << "writing " << width << "x" << height;
//if ( mVerbosity ) cerr << " image to file3 \"" << filename << "\"...";
outfile << "P6" << endl; // 8-bit color
outfile << "# color image" << endl;
outfile << width << " " << height << endl;
outfile << 255 << endl;
// original float values scaled to [0,255]
max = min = pixels[0][0];
for( i = 0; i < height; i++ )
for( j = 0; j < width; j++ )
{
if( pixels[i][j] > max ) max = pixels[i][j];
if( pixels[i][j] < min ) min = pixels[i][j];
}
maxmin = max - min;
if ( channel == 0 )
for ( i = 0; i < height; i++ )
{
for ( j = 0; j < width; j++ )
{
rgb[0] = (unsigned char)(255.0 * ( (pixels[i][j] - min ) / maxmin ));
//(unsigned char)(pixels[i][j]*255.0);
rgb[1] = 0;
rgb[2] = 0;
outfile.write( (char *)rgb, 3 );
}
}
else if ( channel == 1 )
for ( i = 0; i < height; i++ )
{
for ( j = 0; j < width; j++ )
{
rgb[0] = 0;
rgb[1] = (unsigned char)(255.0 * ( (pixels[i][j] - min ) / maxmin ));
rgb[2] = 0;
outfile.write( (char *)rgb, 3 );
}
}
else
for ( i = 0; i < height; i++ )
{
for ( j = 0; j < width; j++ )
{
rgb[0] = 0;
rgb[1] = 0;
rgb[2] = (unsigned char)(255.0 * ( (pixels[i][j] - min ) / maxmin ));
outfile.write( (char *)rgb, 3 );
}
}
outfile.close();
//if ( mVerbosity ) cerr << "done" << endl;
}
// Write a PGM image in a file with output values scaled
void PGMImage::WriteScaled( char* filename, float** output, int height, int width )
{
float max, min, maxmin;
int i, j;
// clear old data first
Deallocate();
// set dimensions of pixelmap and allocate memory
mWidth = width;
mHeight = height;
mMagicNumber[0] = 'P';
mMagicNumber[1] = '5';
mNumLevels = 255;
Allocate( kChars );
// original float values scaled to [0,255]
max = min = output[0][0];
for( i = 0; i < mHeight; i++ )
for( j = 0; j < mWidth; j++ )
{
if( output[i][j] > max ) max = output[i][j];
if( output[i][j] < min ) min = output[i][j];
}
maxmin = max - min;
for( i = 0; i < mHeight; i++ )
for( j = 0; j < mWidth; j++ )
mPixels[i][j] = (unsigned char)(255.0 * ( (output[i][j] - min ) / maxmin ));
Write( filename );
}
}; // namespace