⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgm_util.cpp

📁 The goal of this project is to explore the idea of point-based radiosity, which is a shooting radio
💻 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 + -