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

📄 ppm_util.cpp

📁 The goal of this project is to explore the idea of point-based radiosity, which is a shooting radio
💻 CPP
字号:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "ppm_util.hpp"

/*+----------------------------------------------------------------------------
  consume_PPM_comment
	
  Consume the bytes from the FILE* until a '\r' a '\n' 
  is read.

  No return value.  It just returns when a '\r', '\n' 
  or EOF is read.
	
*/
void consume_PPM_comment (FILE* file)
{
  assert(file != NULL);
  char    data;
  size_t  num_objects_read;
  bool 	done = false;

  while (!done)
  {
    num_objects_read = fread(&data, 1, 1, file);
		
    if ((num_objects_read < 1) || 
        data == '\r' ||
        data == '\n')
    {
      done = true;  // Not needed, this is for debugging.
      break;
    }
  }
}


/*+----------------------------------------------------------------------------
  read_PPM_integer
	
*/
int read_PPM_integer (FILE* file)
{
  assert(file != NULL);
	
  size_t num_objects_read = 0;
  char   data;
  bool   done = false;
  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[num_digits + 1]; 
  int       num_pos = 0;
	
  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 = true;
        state = 2;
      }
      // If the state is 0, then just keep 
      //going
    }
    else if (data == '#')
    {
      consume_PPM_comment(file);
    }
    else
    {
      // Put the character back , and we're done.
      fputc(data, file);
      done = true;
      state = 2;
    }
  }			

  return atoi(num_buffer);

}

/*+----------------------------------------------------------------------------
	read_PPM_image_data
	
	
*/

bool read_PPM_image_data (FILE* file, 
                          unsigned char** ppData, 
                          unsigned int width, 
                          unsigned int height,
                          unsigned int colorDepth
                          )
{
  assert(file != NULL);
  assert(ppData != NULL);

  bool success = false;
  //int current_pos = 0;
  char data;  // data for red, green or blue channel
		
  size_t num_read = 0;
	
  // FIXME - Take color depth into account
  int  max_size = 3 * width * height;

  *ppData = new unsigned char[max_size];

  unsigned char* image_data = *ppData;

  int pos = -1;
	
  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 = true;
		
  return success;
}

void flip_PPM_image (unsigned char* pData, 
                     unsigned int width, 
                     unsigned int height,
                     unsigned int colorDepth)
{    
    unsigned char* pScanLine = new unsigned char [3 * width];
  
  int last_scanline = (height / 2) - 1;

  int src_offset = 0;
  int dst_offset = 0;

  // FIXME - Use color depth
  int bytes_per_row = 3 * width;

  for (int i = 0; i <= last_scanline; i++)
  {
    src_offset = bytes_per_row * i;
    dst_offset = bytes_per_row * (height - i - 1);
    
    memcpy(pScanLine, &(pData[src_offset]), bytes_per_row);
    memcpy(&(pData[src_offset]), &(pData[dst_offset]), bytes_per_row);
    memcpy(&(pData[dst_offset]), pScanLine, bytes_per_row);
    
  }

  if (pScanLine)
  {
    delete [] pScanLine;
  }
}
/*+----------------------------------------------------------------------------
	read_PPM_File
	
	Read a PPM (Portable Pixmap) file.  
	
	Place the dimensions of the file in the global variables 
	g_image_width and g_image_height.  Place the image data itself
	in g_image_data;
	

	Returns true if the PPM file was read successfully, and false
	otherwise.
	
	0 is looking for the magic number
	1 is looking for the width 
	2 is looking for the height
	3 is looking for the color depth
	4 is looking for the image data
	
*/
bool read_PPM_file (FILE* file, 
                    unsigned char** ppData, 
                    unsigned int* width, 
                    unsigned int* height,
                    unsigned int* colorDepth
                    )
                    
{
  assert(ppData != NULL);

  bool done 		= false;
  bool success 	        = false;
		
  int  state = 0;
		
  char   data;
  size_t result;
	
  // States.
  // Does comment count as a state?
  // 
  while (!done)
    {
      // If there is an error, just break w/o setting
      // the success flag.
		
      switch(state)
	{
	case 0: // looking for header

	  result = fread(&data, 1, 1, file);
				
	  if (data != 'P') 
	    {
	      // bail out, maybe I need an exception or a 
	      // (gasp) goto.
	      break;
	    }		
				
	  result = fread(&data, 1, 1, file);
				
	  if ((data == '6') && (result == 1))
	    {
	      state = 1;
	    }
		
	  break;

	case 1:
	  *width = read_PPM_integer(file);
	  state = 2;
	  break;
			
	case 2:
	  *height = read_PPM_integer(file);
	  state = 3;
	  break;
			
	case 3:
	  *colorDepth = read_PPM_integer(file);
	  state = 4;
	  break;	
			
	case 4:
	  success = read_PPM_image_data(file, ppData, *width, *height, *colorDepth);
	  state = 5;	  
	  done = true;
	  break;
	}
    }
	
  // The PPM image is top down, OpenGL likes
  // pixel data to be bottom up.  Maybe I'll figure out
  // how to use glPixelZoom and glRasterPos2i 

  flip_PPM_image(*ppData, *width, *height, *colorDepth);
  
  // Check to see 
  if (!success)
    {
      // spit out an error message.
    }
	


  return true;
}


/*+-----------------------------------------------------------------------------
  save_PPM_file

*/
bool save_PPM_file (FILE* file,
                    unsigned char* pData,
                    unsigned int width,
                    unsigned int height,
                    unsigned int maxChannelValue
                    )
{
  if (file == NULL)
    return false;

  if (pData == NULL)
    return false;


  flip_PPM_image(pData, width, height, maxChannelValue);


  fprintf(file, "P6\n");
  fprintf(file, "%d %d\n", width, height);
  
  assert (maxChannelValue == 255);
  fprintf(file, "%d\n", maxChannelValue); // should be 255
  
  size_t data_size = 3 * width * height;

  unsigned char* ptr = pData;

  for (unsigned int i = 0; i < data_size; i++, ptr++)
  {
    fputc(*ptr, file);
  }
  return true;
}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -