When I checked your code you have this:
for (int j = 0; j < num_of_rows; j++){ //compute integral image
for (int i = 0; i < num_of_cols; i++){
integral[i, j] = integral[i - 1, j] +
integral[i, j - 1] -
integral[i - 1, j - 1] +
pixel_value[i, j];
}
}
I'm thinking you meant for it to be like this:
for (int j = 0; j < num_of_rows; j++){ //compute integral image
for (int i = 0; i < num_of_cols; i++){
integral[i, j] = integral[i - 1][j] +
integral[i][j - 1] -
integral[i - 1][j - 1] +
pixel_value[i][j];
}
}
EDIT
It is this section of your code that may be of concern:
int max_val; //255
ss >> max_val;
cout<<max_val;
char pixel;
unsigned int pixel_value[num_of_rows][num_of_cols];
unsigned int integral[num_of_rows][num_of_cols];
for (row = 0; row < num_of_rows; row++){ //pixel values
for (col = 0; col < num_of_cols; col++){
ss >> pixel;
pixel_value[row][col]= pixel;
}
cout << endl;
}
You are declaring your array to hold unsigned int while the pixel data is being saved into a char type, then you try to save this char type into an array of unsigned int. It might help if you change your char to an unsigned char. I am also including a demonstration of a method to one of my classes for reading in a TGA file below.
I am looking at your approach as to how your are reading in your data and it might help you to take a look at the implementation of a function definition that I have for one of my classes that will read data from a TGA file. Here is the provided structures and function definition.
// TextureInfo -------------------------------------------------------------
struct TextureInfo {
enum FilterQuality {
FILTER_NONE = 1,
FILTER_GOOD,
FILTER_BETTER,
FILTER_BEST
}; // FilterQuality
unsigned uTextureId;
bool hasTransparency;
glm::uvec2 size;
TextureInfo() :
uTextureId( INVALID_UNSIGNED ),
hasTransparency( false ),
size( glm::uvec2( 0, 0 ) )
{}
}; // TextureInfo
// -------------------------------------------------------------------------
// Texture
struct Texture {
bool hasAlphaChannel;
bool generateMipMap;
bool wrapRepeat;
unsigned uWidth;
unsigned uHeight;
TextureInfo::FilterQuality filterQuality;
std::vector<unsigned char> vPixelData;
Texture( TextureInfo::FilterQuality filterQualityIn, bool generateMipMapIn, bool wrapRepeatIn ) :
hasAlphaChannel( false ),
generateMipMap( generateMipMapIn ),
wrapRepeat( wrapRepeatIn ),
uWidth( 0 ),
uHeight( 0 ),
filterQuality( filterQualityIn )
{}
}; // Texture
// -------------------------------------------------------------------------
// loadTga()
void TextureFileReader::loadTga( Texture* pTexture ) {
if ( nullptr == pTexture ) {
throw ExceptionHandler( __FUNCTION__ + std::string( " invalid pTexture passed in" ) );
}
struct TgaHeader {
unsigned char idLength;
unsigned char colorMapType;
unsigned char imageType;
unsigned char colorMapSpecifications[5];
short xOrigin;
short yOrigin;
short imageWidth;
short imageHeight;
unsigned char pixelDepth;
unsigned char imageDescriptor;
} tgaHeader;
enum TgaFileType {
TGA_RGB = 2,
TGA_RLE_RGB = 10,
}; // TgaFileType
// Error Message Handling
std::ostringstream strStream;
strStream << __FUNCTION__ << " ";
// Open File For Reading
m_fileStream.open( m_strFilenameWithPath, std::ios_base::in | std::ios_base::binary );
if ( !m_fileStream.is_open() ) {
strStream << "can not open file for reading";
throwError( strStream );
}
// Get TGA File Header
if ( !m_fileStream.read( reinterpret_cast<char*>( &tgaHeader ), sizeof( tgaHeader ) ) ) {
strStream << "error reading header";
throwError( strStream );
}
// This TGA File Loader Can Only Load Uncompressed Or Compressed True-Color Images
if ( (tgaHeader.imageType != TGA_RGB ) && (tgaHeader.imageType != TGA_RLE_RGB ) ) {
strStream << "TGA loader only supports loading RGB{" << TGA_RGB << "} and RLE_RGB{" << TGA_RLE_RGB
<< "} encoded files. This file contains pixels encoded in an unsupported type{" << tgaHeader.imageType << "}";
throwError( strStream );
}
// Convert Bits Per Pixel To Bytes Per Pixel
unsigned uBytesPerPixel = tgaHeader.pixelDepth / 8;
if ( (uBytesPerPixel != 3) && (uBytesPerPixel != 4) ) {
strStream << "TGA loader only supports 24bpp or 32bpp images. This image uses " << tgaHeader.pixelDepth << " bits per pixel";
throwError( strStream );
}
// Make Room For All Pixel Data
if ( 0 == tgaHeader.imageWidth || 0 == tgaHeader.imageHeight ) {
strStream << "invalid image size (" << tgaHeader.imageWidth << "," << tgaHeader.imageHeight << ")";
throwError( strStream );
}
unsigned uTotalNumBytes = tgaHeader.imageWidth * tgaHeader.imageHeight * uBytesPerPixel;
pTexture->vPixelData.resize( uTotalNumBytes );
// Move Read Pointer To Beginning Of Image Data
if ( tgaHeader.idLength > 0 ) {
m_fileStream.ignore( tgaHeader.idLength );
}
// Used To Get And Flip Pixels Data
std::vector<unsigned char> vTempPixel( uBytesPerPixel, 0 );
if ( tgaHeader.imageType == TGA_RLE_RGB ) {
// TGA Data Is Compressed
// All Error Messages The Same If Error Occurs Below
strStream << "file is corrupted, missing pixel data";
unsigned char ucRepetitionCounter = 0;
unsigned uTotalNumberPixels = tgaHeader.imageWidth * tgaHeader.imageHeight;
unsigned uCurrentPixel = 0;
while( uCurrentPixel < uTotalNumberPixels ) {
// Get Repetition Count Value
if ( !m_fileStream.read( reinterpret_cast<char*>( &ucRepetitionCounter ), sizeof( unsigned char ) ) ) {
throwError( strStream );
}
if ( ucRepetitionCounter < 128 ) {
// Raw Packet. Counter Indicates How Many Different Pixels Need To Be Read
++ucRepetitionCounter;
// Get Pixel Values
if ( !m_fileStream.read( reinterpret_cast<char*>( &pTexture->vPixelData[uCurrentPixel * uBytesPerPixel] ), uBytesPerPixel * ucRepetitionCounter ) ) {
throwError( strStream );
}
} else {
// Run-Length Packet. Counter Indicates How Many Times The Text Pixel Needs To Repeat
ucRepetitionCounter -= 127;
// Get Pixel Value
if ( !m_fileStream.read( reinterpret_cast<char*>( &vTempPixel[0] ), uBytesPerPixel ) ) {
throwError( strStream );
}
// Save Pixel Multiple Times
for ( unsigned int u = uCurrentPixel; u < ( uCurrentPixel + ucRepetitionCounter ); ++u ) {
memcpy( &pTexture->vPixelData[u * uBytesPerPixel], &vTempPixel[0], uBytesPerPixel );
}
}
// Increment Counter
uCurrentPixel += ucRepetitionCounter;
}
} else {
// TGA Data Is Uncompressed
// Get Pixel Data
if ( !m_fileStream.read( reinterpret_cast<char*>( &pTexture->vPixelData[0] ), pTexture->vPixelData.size() ) ) {
strStream << "file is corrupted, missing pixel data";
throwError( strStream );
}
}
m_fileStream.close();
// Convert All Pixel Data from BGR To RGB
unsigned char ucTemp;
for ( unsigned int u = 0; u < uTotalNumBytes; u += uBytesPerPixel ) {
ucTemp = pTexture->vPixelData[u]; // Save Blue Color
pTexture->vPixelData[u] = pTexture->vPixelData[u + 2]; // Set Red Color
pTexture->vPixelData[u + 2] = ucTemp; // Set Blue Color
}
// Flip Image Horizontally
if ( tgaHeader.imageDescriptor & 0x10 ) {
short sHalfWidth = tgaHeader.imageWidth >> 1;
for ( short h = 0; h < tgaHeader.imageHeight; ++h ) {
for ( short w = 0; w < sHalfWidth; ++w ) {
unsigned uPixelLeft = uBytesPerPixel * ( h * tgaHeader.imageWidth + w );
unsigned uPixelRight = uBytesPerPixel * ( h * tgaHeader.imageWidth + tgaHeader.imageWidth - 1 - w );
memcpy( &vTempPixel[0], &pTexture->vPixelData[uPixelLeft], uBytesPerPixel ); // Store Left Pixel
memcpy( &pTexture->vPixelData[uPixelLeft], &pTexture->vPixelData[uPixelRight], uBytesPerPixel ); // Save Right Pixel @ Left
memcpy( &pTexture->vPixelData[uPixelRight], &vTempPixel[0], uBytesPerPixel ); // Save Left Pixel @ Right
}
}
}
// Flip Vertically
if ( tgaHeader.imageDescriptor & 0x20 ) {
short sHalfHeight = tgaHeader.imageHeight >> 1;
for ( short w = 0; w < tgaHeader.imageWidth; ++w ) {
for ( short h = 0; h < sHalfHeight; ++h ) {
unsigned uPixelTop = uBytesPerPixel * ( w + tgaHeader.imageWidth * h );
unsigned uPixelBottom = uBytesPerPixel * ( w + tgaHeader.imageWidth * ( tgaHeader.imageHeight - 1 - h ) );
memcpy( &vTempPixel[0], &pTexture->vPixelData[uPixelTop], uBytesPerPixel ); // Store Top Pixel
memcpy( &pTexture->vPixelData[uPixelTop], &pTexture->vPixelData[uPixelBottom], uBytesPerPixel ); // Save Bottom Pixel @ Top
memcpy( &pTexture->vPixelData[uPixelBottom], &vTempPixel[0], uBytesPerPixel ); // Save Top Pixel @ Bottom
}
}
}
// Store Other Values In Texture
pTexture->uWidth = tgaHeader.imageWidth;
pTexture->uHeight = tgaHeader.imageHeight;
pTexture->hasAlphaChannel = ( tgaHeader.pixelDepth == 32 );
} // loadTga
NOTE: - This will not be able to compile if you copy and paste for it relies on other classes and libraries not listed or shown here. This is valid working code from one of my 3D Graphics Engine Solutions.
As you can see here I am using a structure for the TGA Header; I also have a structure for a Texture Object. Now all of this may be more than what you need; but the important parts is seeing how it is that I am reading in the data from the file and storing their values.
The important part is where I am using the C++ keyword reinterpret_cast<>( )
within the file streams read()
method. This may help you to rewrite your parser for reading in the image file so that the data you are reading in and storing is byte aligned with the image structure that you are expecting. This will also depend on the structure of the file that you are reading and the image structure that you are using in your code.
I also have a similar method for reading in a PNG file that this class uses which depends on the PGN Library where I have it installed on my pc and linked to my IDE so the functions for reading in a PGN File can be found. This is quite a bit more simple than the function that I have shown you here for reading in a TGA File.
When you want to use a TGA File you have to know the file structure and write your own file parser where as with a PNG file most of that work is done for you within the PNG Library and all you would have to do is call the appropriate functions in the proper order and check for the appropriate errors. I have not shown the loadPNG() function.
Of course you are reading in a PGM File and not a TGA or PNG but the concept is the same. You have to know exactly how many bytes to read in before you reach the actual pixel data, then you should know the size of the image as in pixel width * pixel length * bytes per pixel. The header information should tell you this much as you read that in and store it to your variables or structures, but this is very important. An example would be the image is say 256 pixels X 256 pixels, however what also needs to be known is how wide each pixel is! Is each pixel 8bits (1bytes), 16bits (2bytes), 24bits(3bytes), 32bits(4bytes). Another important thing to know is what is the color pattern such as black & white, gray scale, RGB, RGBA, CYM, etc., and in which order the color information is stored. Also is the image stored as being inverted not just by color information, but is the image flipped horizontally and or vertically. There are usually flags within an image file's header information that will tell you this. Also is the data compressed, uncompressed, is it raw data, or run length encoded (RLE). All of this information is important when parsing an image file. It even gets to be a little more complicated when you work with BMP - JPEG because they also have a possible color palette stored.
I hope this helps to serve you as a guide so that you can properly read in your image file before you begin to do any processing or work on the image data.