1: // noise -- Inject white noise into a fax image.

  3: #include <iostream.h>
  4: #include <fstream.h>
  5: #include <sys/stat.h>
  6: #include <stdlib.h>
  7: #include <stdio.h>

  9: #include "bit_array.H"
 10: #include "random_sample.H"


 13: // Calling sequence:
 14: //
 15: //   stegafax noise <seed> <percent> <input_file> <output_file>
 16: //
 17: // This entry point injects noise into a fax raster as a pbm file.
 18: // This has the effect of lowering the contrast of the fax image, and
 19: // also acting as "cover" for the steganographic message bits, which
 20: // otherwise likewise introduce a "graying" of the background white
 21: // space.
 22: // 
 23: int noise(int nargs, char* args[]) {

 25:   // Get the parameters.

 27:   if (nargs != 6) return -1;                      // check number of parameters

 29:   char* SEED = args[2];                           
 30:   char* PERCENT = args[3];
 31:   char* INPUT_FILE = args[4];
 32:   char* OUTPUT_FILE = args[5];

 34:   double percent = atof(PERCENT);
 35:   if (percent > (double)100                       // sanity checks
 36:       || percent < (double)0) {
 37:     printf("Noise percentage must be between 0%% and 100%%.\n");

 39:     return -1;
 40:   }

 42:   // Note that an inversion of 100% of the bits will produce a
 43:   // negative of the fax image.  Therefore, inverting 50% of the bits
 44:   // produces maximum entropy -- pure noise.

 46:   percent /= (double)200;                         // fudge factor :->~ 

 48:   // Instantiate a random number generator.

 50:   int seed = atoi(SEED);
 51:   prng rand(seed);

 53:   // Read in the fax raster from stdin.

 55:   ifstream input_file(INPUT_FILE);
 56:   input_file.ignore(3);                           // trash the raster's magic number 
 57:   long rows;                                      // number of rows in raster
 58:   input_file >> rows;                             // get number of rows from pbm file
 59:   long cols;                                      // number of collums in raster
 60:   input_file >> cols;                             // get number of cols from pbm file
 61:   input_file.ignore(1);                           // discard terminal newline
 62:   long npixels = rows*cols;                       // number of pixels in raster
 63:   long nbytes = (npixels + 7)/8;                  // number of bytes in raster
 64:   bit_array raster(rows, cols);                   // make a bit array to hold the pbm raster
 65:   input_file.read(raster.bytes, nbytes);          // read the pbm raster file into it

 67:   // Take a random sample of the bits in the image.

 69:   long N = npixels;
 70:   long n = (long)((double)N*percent);             // number of bits we're going to hit
 71:   random_sample spot(rand, n, N);                 // all the spots in the image we're going to clobber

 73:   // Invert the sampled bits.

 75:   long i;
 76:   for (i = 0; i < n; i++) {
 77:     raster.set(spot(i), !raster(spot(i)));        // compliment the selected bits
 78:   }

 80:   // Output the stegafax raster.

 82:   ofstream output_file(OUTPUT_FILE);
 83:   output_file << "P4\n";                          // pbm magic number
 84:   output_file << rows << " " << cols << "\n";
 85:   output_file.write(raster.bytes, nbytes);        // output stegafax raster to stdout

 87:   return 0;
 88: }