📄 pgm_util.cpp
字号:
/*+------------------------------------------------------------------
Ben Landon
CSCI E-235
pgm_util.cpp
A module for decoding the data in a PGM (portable graymap) file.
Currently, only the binary version of the PGM format is supported.
*/
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "pgm_util.hpp"
typedef enum PbmFileType
{
BinaryPPM = 0,
BinaryPGM = 1,
Unknown = 2
};
static enum PbmFileType read_pgm_header (FILE* file);
static void consume_comment (FILE* file);
static int read_integer (FILE* file);
static int read_image_data (FILE* file,
unsigned char** ppData,
unsigned int width,
unsigned int height,
unsigned int colorDepth
);
/*+-------------------------------------------------------------------
read_pgm_header
This function expects teh PGM header (P5 for binary)
read_pgm_header returns non-zero on success and
zero on error.
*/
enum PbmFileType read_pgm_header (FILE* file)
{
int done = 0;
int ch = 0;
enum PbmFileType result = Unknown;
while (!done)
{
ch = getc(file);
// If this is whitespace, then continue.
// This is to be forgiving case there is
// leading whitespace in the file
if (isspace(ch))
continue;
if (ch == 'P')
{
ch = getc(file);
if (ch == '5')
{
result = BinaryPGM;
done = 1;
}
}
else if (ch == '#')
{
consume_comment(file);
}
else
{
// Something other than a PGM header
// was found.
done = 1;
result = Unknown;
}
}
return result;
}
// Read until the end of the line
void consume_comment (FILE* file)
{
char data;
size_t num_objects_read;
int done = 0;
assert(file != NULL);
while (!done)
{
num_objects_read = fread(&data, 1, 1, file);
if ((num_objects_read < 1) ||
data == '\r' ||
data == '\n')
{
done = 1;
break;
}
}
}
/*+----------------------------------------------------------------------------
read_integer
*/
int read_integer (FILE* file)
{
size_t num_objects_read = 0;
char data;
int done = 0;
int state = 0;
//
// state = 0 is the number is not yet started
// state = 1 is that we're currently reading the
// number.
// state = 2 is the number is over.
//
// large enum to hold the decimal representation
// of an unsigned 32 bit integer.
//
const int num_digits = 11;
char num_buffer[12];
int num_pos = 0;
assert(file != NULL);
memset(num_buffer, 0, num_digits + 1);
while (!done)
{
num_objects_read = fread(&data, 1, 1, file);
if (isdigit(data))
{
if (num_pos <= num_digits)
{
num_buffer[num_pos++] = data;
state = 1;
}
}
else if (isspace(data))
{
if (state != 0)
{
done = 1;
state = 2;
}
// If the state is 0, then just keep
//going
}
else if (data == '#')
{
consume_comment(file);
}
else
{
// Put the character back , and we're done.
fputc(data, file);
done = 1;
state = 2;
}
}
return atoi(num_buffer);
}
/*+----------------------------------------------------------------------------
read_image_data
*/
int read_image_data (FILE* file,
unsigned char** ppData,
unsigned int width,
unsigned int height,
unsigned int colorDepth
)
{
int success = 0;
//int current_pos = 0;
char data; // data for red, green or blue channel
size_t num_read = 0;
int bytes_per_pixel = colorDepth / 255;
int max_size = bytes_per_pixel * width * height;
unsigned char* image_data;
int pos = -1;
assert(file != NULL);
assert(ppData != NULL);
*ppData = new unsigned char[max_size];
image_data = *ppData;
for (pos = 0; pos < max_size; pos++)
{
num_read = fread(&data, 1, 1, file);
if (num_read < 1)
{
break;
}
image_data[pos] = data;
}
if (pos == max_size) // read the number of bytes expected?
success = 1;
return success;
}
/*+-------------------------------------------------------------------
read_pgm_file
This is the main entry point into the PGM reading code.
state = 0 means expecting the header.
*/
int read_pgm_file (const char* filename,
unsigned int* width,
unsigned int* height,
unsigned int* max_gray,
unsigned char** data)
{
FILE* file = NULL;
int state = 0;
int done = 0;
int success = 0;
assert(filename != NULL);
assert(data != NULL);
if (data == NULL)
return 0;
if (filename == NULL)
{
*data = NULL;
return 0;
}
file = fopen(filename, "rb");
if (!file)
{
*width = 0;
*height = 0;
*data = NULL;
*max_gray = 0;
return 0;
}
while (!done)
{
switch (state)
{
case 0:
// Expecting the header
if (read_pgm_header(file) == BinaryPGM)
{
state = 1;
}
else
{
success = 0;
done = 1;
}
break;
case 1:
// Expecting the width
*width = read_integer(file);
state = 2;
break;
case 2:
*height = read_integer(file);
state = 3;
break;
case 3:
*max_gray = read_integer(file);
state = 4;
break;
case 4:
read_image_data(file, data, *width, *height, *max_gray);
state = 5;
success = 1;
done = 1;
break;
}
}
if (!success)
{
*data = NULL;
*width = 0;
*height = 0;
*max_gray = 0;
}
if (file != NULL)
fclose(file);
return success;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -