The pseudo color generation program

Below is the C++ program used to take a grayscale 8 bits per channel, 1 channel, RAW input image and convert it into a pseudo color 8 bits per channel, 3 channel, RAW color interlaced output image. The program does this by first reading in the b/w image and determining what the intensity range of the image is. The program then re-reads the input image one scanline at a time and it takes each pixel's red, green and blue components and linearly scales the components into the user's selected output color range. Each color scanline is then written out to the output image.

/*******************************************
 Program: Pseudo Colorize
 Written By: Timothy S. Fox
 Date: September 3, 1999
*******************************************/

#include "stdio.h"
#include "stdlib.h"

main()
{
   int file_width, file_height;
   FILE *matte_ptr, *output_ptr;
   int n_written, row, col, result_color_comp;
   float red_slope, green_slope, blue_slope, normalized_value;
   unsigned char *output_image = NULL;
   unsigned char *matte_pixels = NULL;
   unsigned char start_color_red, start_color_green;
   unsigned char start_color_blue;
   unsigned char end_color_red, end_color_green, end_color_blue;
   unsigned char intensity_difference;
   unsigned char red_delta, green_delta, blue_delta;
   unsigned char min_intensity, max_intensity;
   char path[80];
   char base_name[] = "holo";

   //starting color at low end

   start_color_red   = 11;
   start_color_green = 35;
   start_color_blue  = 54;

   //ending color at high end

   end_color_red   = 150;
   end_color_green = 200;
   end_color_blue  = 250;

   //array space to hold one scanline of b/w and output images

   output_image = (unsigned char *) malloc(9000);
   matte_pixels = (unsigned char *) malloc(3000);

   file_width  = 700;    /*file width*/
   file_height = 292;    /*file height*/

   printf("image width = %d\n", file_width);
   printf("image height = %d\n", file_height);

   //now lets open up the b/w input file

   sprintf(path, "Krusty:%s.matte", base_name);
   matte_ptr = fopen(path, "rb");

   if (matte_ptr == NULL)
     {
       free(output_image);
       free(matte_pixels);

       printf("Not able to open the b/w file %s\n", path);
       exit(1);
     }

   printf("Scanning b/w file to determine intensity range..\n");

   //initialize our limit variables

   min_intensity = 255;
   max_intensity = 0;

   //now lets go through the input b/w file and determine what
   //the lower and upper intensity limits are for the file

   for (row=1; row <= file_height; row++)
     {
        //read in a 8 bit matte pixel scanline

        if (fread((void *) matte_pixels, sizeof(char),
            file_width, matte_ptr) != file_width)
          {
            fclose(matte_ptr);

            free(output_image);
            free(matte_pixels);

            printf("Unable to read matte pixel block %d.\n", row);
            exit(1);
          }

        //lets look through the scanline one pixel at a time
        //and determine if we have a new min or max intensity

        for (col=0; col < file_width; col++)
          {
            if (matte_pixels[col] < min_intensity)
               min_intensity = matte_pixels[col];
            if (matte_pixels[col] > max_intensity)
               max_intensity = matte_pixels[col];
          }
     }

   //what is the difference between the max intensity and the
   //min intensity

   intensity_difference = max_intensity - min_intensity;

   printf("Finished scanning the input b/w image.\n");
   printf("intensity range = %d\n", intensity_difference);
 
   fclose(matte_ptr);  //close input file

   matte_ptr = fopen(path, "rb");  //lets reopen the input file

   printf("matte image = %s\n", path);

   //create an empty output file that will store the resulting
   //pseudo color output image

   sprintf(path, "Krusty:%s.out", base_name);

   output_ptr = fopen(path, "wb");

   if (output_ptr == NULL)
     {
        fclose(matte_ptr);

        free(output_image);
        free(matte_pixels);

        printf("Unable to open output file %s for write.\n", path);
        exit(1);
     }

   printf("output image = %s\n", path);

   //are we going up or down to go from the starting color
   //to the ending color for the red, blue, and green components

   if (end_color_red > start_color_red)
     {
       red_slope = 1.0;
       red_delta = end_color_red - start_color_red;
     }
   else
     {
       red_slope = -1.0;
       red_delta = start_color_red - end_color_red;
     }
 
   if (end_color_green > start_color_green)
     {
       green_slope = 1.0;
       green_delta = end_color_green - start_color_green;
     }
   else
     {
       green_slope = -1.0;
       green_delta = start_color_green - end_color_green;
     }

   if (end_color_blue > start_color_blue)
     {
       blue_slope = 1.0;
       blue_delta = end_color_blue - start_color_blue;
     }
   else
     {
       blue_slope = -1.0;
       blue_delta = start_color_blue - end_color_blue;
     }

   //now lets go through and retrieve each row of the b/w image

   for (row=1; row <= file_height; row++)
     {
        //read in a 8 bit b/w input image scanline

        if (fread((void *) matte_pixels, sizeof(char),
            file_width, matte_ptr) != file_width)
           {
             fclose(matte_ptr);
             fclose(output_ptr);

             free(output_image);
             free(matte_pixels);

             printf("Unable to read matte pixel block %d.\n", row);
             exit(1);
	   }

        for (col=0; col < file_width; col++)
          {
            //normalize the matte value
            normalized_value = (matte_pixels[col] - min_intensity) /
                               ((float) intensity_difference);

            //calculate the resulting red color component
            //for this pixel in the scanline

            result_color_comp = start_color_red + (red_slope *
                                normalized_value * red_delta);

            //make sure the color is within 0-255 range

            if (result_color_comp > 255) 
               output_image[col*3] = 255;
            else if (result_color_comp < 0) 
               output_image[col*3] = 0;
            else
               output_image[col*3] = result_color_comp;
	

            //calculate the resulting green color component
            //for this pixel in the scanline

            result_color_comp = start_color_green + (green_slope *
                                normalized_value * green_delta);

            //make sure the color is within 0-255 range

            if (result_color_comp > 255) 
               output_image[col*3+1] = 255;
            else if (result_color_comp < 0) 
               output_image[col*3+1] = 0;
            else
               output_image[col*3+1] = result_color_comp;

            //calculate the resulting blue color component
            //for this pixel in the scanline

            result_color_comp = start_color_blue + (blue_slope *
                                normalized_value * blue_delta);

            //make sure the color is within 0-255 range

            if (result_color_comp > 255) 
                output_image[col*3+2] = 255;
            else if (result_color_comp < 0) 
                output_image[col*3+2] = 0;
            else
                output_image[col*3+2] = result_color_comp;
          }

       //write the pseudo color scanline out to the output file

       n_written = fwrite((void *) output_image, sizeof(char),
                   file_width*3, output_ptr);

       if (n_written != file_width*3)
          {
            fclose(matte_ptr);
            fclose(output_ptr);

            printf("Unable to write scanline to output file.\n");
            exit(1);
          }

       printf("wrote out image row %d\n", row);
     }

   //close all the input and output files

   fclose(matte_ptr);
   fclose(output_ptr);

   exit(0);
}


Last Updated: September 2, 1999
HTML URL: http://geocities.datacellar.net/~special_effect/sw_pseudo_colorize.html
E-Mail: special_effect@geocities.com or click here
1