Creating starfield images

Below is the C program used to create a b/w 8 bits per channel, 1 channel, RAW format output starfield images.

/***************************************************************
HEADER FILE CODE
**************************************************************/

/***************************************************************
This program was created by Timothy Fox on January 29, 2002
My email: special_effect.geo@yahoo.com
My website: www.geocities.com/hollywood/theater/1991
**************************************************************/

#ifndef _STAR_FIELD
#define _STAR_FIELD

//widescreen format 2700x1149 pixels

#define STARFIELD_IMAGE_HEIGHT  1149    //image height in pixels
#define STARFIELD_IMAGE_WIDTH   2700    //image width in pixels

// 2000 stars creates a very dense starfield

#define NUMBER_STARS 2000 //number of stars we produce

#define XSMALL   0
#define SMALL    1
#define LARGE    3
#define MEDIUM   2
#define XLARGE   4
	
#ifdef _STAR_FIELD_DECLARE

//where do we store the output starfield?

char output_starfield_filename[] = "Krusty:starfields:starfield.out";

//percents of 100 of the total for each star size to create.  Array element 0 is
//the XSmall size up through array element 4 which is XLarge sized stars

float star_percents[5] = { 0.15, 0.4, 0.25, 0.1, 0.1 };

unsigned char **output_starfield_image = NULL;

//the 3D array which holds the actual images of each star at each size

unsigned char stars_array[5][8][8] = {
                                      {{1,1,1,1,1,1,1,1}, //XSmall star
                                      {1,1,1,1,1,1,1,1},
                                      {1,1,46,46,46,1,1,1},
                                      {1,1,46,255,46,1,1,1},
                                      {1,1,46,46,46,1,1,1},
                                      {1,1,1,1,1,1,1,1},
                                      {1,1,1,1,1,1,1,1},
                                      {1,1,1,1,1,1,1,1}},

                                      {{1,1,1,1,1,1,1,1}, //Small star
                                      {1,1,1,1,1,1,1,1},
                                      {1,1,46,134,134,46,1,1},
                                      {1,1,134,255,255,134,1,1},
                                      {1,1,134,255,255,134,1,1},
                                      {1,1,46,134,134,46,1,1},
                                      {1,1,1,1,1,1,1,1},
                                      {1,1,1,1,1,1,1,1}},

                                      {{1,1,1,1,1,1,1,1}, //Medium star
                                      {1,1,46,134,46,1,1,1},
                                      {1,46,134,255,134,46,1,1},
                                      {1,134,255,255,255,134,1,1},
                                      {1,46,134,255,134,46,1,1},
                                      {1,1,46,134,46,1,1,1},
                                      {1,1,1,1,1,1,1,1},
                                      {1,1,1,1,1,1,1,1}},

                                      {{1,1,1,30,1,1,1,1}, //Large star
                                      {1,34,134,202,134,34,1,1},
                                      {1,134,255,255,255,134,1,1},
                                      {30,202,255,255,255,202,30,1},
                                      {1,134,255,255,255,134,1,1},
                                      {1,34,134,202,134,34,1,1},
                                      {1,1,1,30,1,1,1,1},
                                      {1,1,1,1,1,1,1,1}},

                                      {{1,1,1,20,20,1,1,1},  //XLarge star
                                      {1,36,117,192,192,117,36,1},
                                      {1,117,255,255,255,255,117,1},
                                      {21,192,255,255,255,255,192,21},
                                      {21,192,255,255,255,255,192,21},
                                      {1,117,255,255,255,255,117,1},
                                      {1,36,117,192,192,117,36,1},
                                      {1,1,1,20,20,1,1,1}}
                                     };

#else

extern unsigned char stars_array[5][8][8];
extern float star_percents[5];
extern char output_starfield_filename[];
extern unsigned char **output_starfield_image;

#endif   /* _STAR_FIELD_DECLARE */
#endif   /* _STAR_FIELD */

/***************************************************************
SOURCE FILE CODE
**************************************************************/

#define _STAR_FIELD_DECLARE
#include "stdio.h"
#include "stdlib.h"
#include "fcntl.h"
#include "time.h"
#include "star_field.h"

void main()
{
FILE *output_ptr = NULL;
int n_written, row, col, row_coord, col_coord, r,c, starfield_row, starfield_col;
int found_star_location, star, number_stars_to_create, star_size;

if (STARFIELD_IMAGE_HEIGHT * STARFIELD_IMAGE_WIDTH > 1000*1000*100)
   {
   printf("Your starfield is larger than 100MB in size.\n");
   exit(1);
   }

//get 2D array space to hold our entire output starfield image

printf("Getting the starfield image array space...\n");

output_starfield_image = (unsigned char **) malloc(sizeof(unsigned char *) * 
   STARFIELD_IMAGE_HEIGHT);

output_starfield_image[0] = (unsigned char *) malloc(sizeof(unsigned char) * 
   (STARFIELD_IMAGE_HEIGHT * STARFIELD_IMAGE_WIDTH));

//assign the pointer array to point to the various rows of the array

for (row=0; row < STARFIELD_IMAGE_HEIGHT; row++)
   output_starfield_image[row] = output_starfield_image[0] + (row*STARFIELD_IMAGE_WIDTH);
	
//make sure the output starfield image starts out all black

printf("Blacking out the starfield image...\n");

for (row=0; row < STARFIELD_IMAGE_HEIGHT; row++)
   for(col=0; col < STARFIELD_IMAGE_WIDTH; col++)
      output_starfield_image[row][col] = 0;

//now lets create all the stars in the image

//first we initialize our random number generator

srand((unsigned) time(NULL));

printf("Placing stars in the starfield image...\n");

//lets process stars from extra small up to extra large

for (star_size = XSMALL; star_size < = XLARGE; star_size++)
   {
   //how many stars should we create for the selected star size

   number_stars_to_create = star_percents[star_size] * NUMBER_STARS;

   //lets try to create the required number of stars of the selected size

   for (star = 1; star < = number_stars_to_create; star++)
      {
      //we start by saying we haven't yet found the stars location on the image
      found_star_location = 0;

      //while we have not yet found the stars ending location

      while (!found_star_location)
         {
         //lets figure out where the star should be placed

         col_coord = (rand() % (STARFIELD_IMAGE_WIDTH - 5));
         row_coord = (rand() % (STARFIELD_IMAGE_HEIGHT - 4));

         //is the stars center location off the images left or top edges?
         //if so then lets find another location for the star

         if ((col_coord < 3) || (row_coord < 4))
            continue;

         //now lets figure out if we have already placed another star at this location

         //if so lets select another location

         if ((output_starfield_image[row_coord-4][col_coord-3] > 0) || //top left
             (output_starfield_image[row_coord-4][col_coord+4] > 0) || //top right
             (output_starfield_image[row_coord+3][col_coord-3] > 0) || //bottom left
             (output_starfield_image[row_coord+3][col_coord+4] > 0))   //bottom right
            continue;

         found_star_location = 1;  //otherwise we have found a new star location

         //now lets plop a new star into the starfield

         for (starfield_row = row_coord-4, r=0; starfield_row < = row_coord + 3; 
            starfield_row++, r++)
            for (starfield_col = col_coord-3, c=0; starfield_col < = col_coord + 4; 
               starfield_col++, c++)
               output_starfield_image[starfield_row][starfield_col] = 
                  stars_array[star_size][r][c];
         }
      }
   }

printf("Searching starfield image for flag pixels to return to black...\n");

//now lets go through the entire image and return pixel values of 1 back to 0

for (row=0; row < STARFIELD_IMAGE_HEIGHT; row++)
   for(col=0; col < STARFIELD_IMAGE_WIDTH; col++)
      if (output_starfield_image[row][col] == 1)
         output_starfield_image[row][col] = 0;

//now lets write our starfield out to disk

output_ptr = fopen(output_starfield_filename, "wb");  //open an output file

if (output_ptr == NULL)
   {
   free(output_starfield_image[0]);
   free(output_starfield_image);
   return;
   }

printf("Writing output starfield file %s...\n", output_starfield_filename);

//go through the starfield array and output each row of the image

for (row=0; row < STARFIELD_IMAGE_HEIGHT; row++)
   {
   //write a row of the image out to the disk file	

   n_written = fwrite((void *) &(output_starfield_image[row][0]), 
      sizeof(unsigned char), STARFIELD_IMAGE_WIDTH, output_ptr);

   //were we successful at writing out the correct number of pixels?

   if (n_written != STARFIELD_IMAGE_WIDTH)
      {
      printf("wrong number of starfield column pixels written to disk\n");
      printf("row %d (base 0), number of columns attemped = %d\n", row, n_written);

      fclose(output_ptr);
      free(output_starfield_image[0]);
      free(output_starfield_image);
      return;
      }
   }

fclose(output_ptr);

output_ptr = NULL;

free(output_starfield_image[0]);  //free the pixel array
free(output_starfield_image);     //free the pointer array

printf("The program has finished.\n");
}


Last Updated: Feburary 4, 2002
HTML URL: http://geocities.datacellar.net/~special_effect/starfield_generator.html
E-Mail: special_effect.geo@yahoo.com or click here
1