lib/pgmppm/test/test.cpp

Go to the documentation of this file.
00001 /*
00002  * test.cpp
00003  *
00004  * Copyright (C) 2008  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  * Program to test the pgmppm library.
00008  */
00009 
00010 // includes --------------------------------------------------------------------
00011 #include "common/common.h"
00012 
00013 #include <fstream>
00014 #include <math.h>
00015 
00016 #include "pgmppm/pgmppm.h"
00017 
00018 
00019 static int s_width                      = -1;
00020 static int s_height                     = -1;
00021 
00022 static const int s_maxGray              = 255;
00023 static const int s_maxColor             = 255;
00024 
00025 struct hc_entry_t {
00026         int             height;
00027         pgmppm::color_t color;
00028 };
00029 
00030 
00031 static const hc_entry_t s_hcolors[] = {
00032         {   0,          {   0,   0, 128 } },
00033         {  32,          {   0,   0, 255 } },
00034         {  64,          { 192, 160,   0 } },
00035         {  96,          {   0, 255,   0 } },
00036         { 160,          {   0, 128,   0 } },
00037         { 192,          { 116, 116, 116 } },
00038         { 256,          { 255, 255, 255 } },
00039 
00040         // must be last!
00041         {  -1,          {   0,   0,   0 } }
00042 };
00043 
00044 
00045 
00046 ////////////////////////////////////////////////////////////////////////////////
00047 //
00048 //      static helper methods
00049 //
00050 ////////////////////////////////////////////////////////////////////////////////
00051 
00052 static int
00053 mix
00054 (
00055 IN int v1,
00056 IN int v2,
00057 IN float q
00058 )
00059 {
00060         ASSERT(v1 >= 0 && v1 <= s_maxColor, "Bad v1: %d", v1);
00061         ASSERT(v2 >= 0 && v2 <= s_maxColor, "Bad v2: %d", v2);
00062         ASSERT(q >= 0.0 && q <= 1.0, "Bad q: %f", q);
00063 
00064         float r = 1.0 - q;
00065 
00066         float f1 = r * v1;
00067         float f2 = q * v2;
00068 
00069         return (int) (f1 + f2 + 0.49);
00070 }
00071 
00072 
00073 
00074 static pgmppm::color_t
00075 getColorForHeight
00076 (
00077 IN byte_t h             // height
00078 )
00079 {
00080         int idx = 0;
00081         for (int i = 1; ; ++i) {
00082                 const hc_entry_t& e = s_hcolors[i];
00083                 ASSERT(e.height >= 0, "bad input height?");
00084                 if (e.height > h) {
00085                         idx = i;
00086                         break;
00087                 }
00088         }
00089         ASSERT(idx > 0, "bad index: %d", idx);
00090 
00091         // get prev + next color entries
00092         const hc_entry_t& prev = s_hcolors[idx - 1];
00093         const hc_entry_t& next = s_hcolors[idx];
00094 
00095         int denom = next.height - prev.height;
00096         ASSERT(denom > 0, "Bad diff? denom = %d", denom);
00097 
00098         int dh = h - prev.height;
00099         ASSERT(dh >= 0, "Bad diff? dh = %d", dh);
00100 
00101         float q = (1.0 * dh) / (denom);
00102 
00103         pgmppm::color_t c;
00104         c.red = mix(prev.color.red, next.color.red, q);
00105         c.green = mix(prev.color.green, next.color.green, q);
00106         c.blue = mix(prev.color.blue , next.color.blue , q);
00107 
00108         return c;
00109 }
00110 
00111 
00112 
00113 static int
00114 getHeight
00115 (
00116 IN void * context,
00117 IN int x,
00118 IN int y
00119 )
00120 {
00121         ASSERT(x >= 0 && x < s_width, "bad x: %d", x);
00122         ASSERT(y >= 0 && y < s_width, "bad y: %d", y);
00123 
00124         float fx = x - (0.5 * s_width);
00125         float fy = y - (0.5 * s_height);
00126 
00127         float z1 = sin(0.05 * fx);
00128         float z2 = sin(0.05 * fy);
00129 
00130         float z = 128 + 127.0 * z1 * z2;
00131 
00132         int iz = (int) z;
00133         return iz % (s_maxGray + 1);
00134 }
00135 
00136 
00137 
00138 static pgmppm::color_t
00139 getColor
00140 (
00141 IN void * context,
00142 IN int x,
00143 IN int y
00144 )
00145 {
00146         int z = getHeight(context, x, y);
00147 
00148         // randomize height for color effects
00149         float mag = 8.0;
00150         float dz = (1.0 * rand()) / RAND_MAX;
00151         z += (int) (mag * (dz - 0.5));
00152         if (z < 0) {
00153                 z = 0;
00154         }
00155         if (z > s_maxColor) {
00156                 z = s_maxColor;
00157         }
00158 
00159         byte_t b = (byte_t) (z % (s_maxColor + 1));
00160 
00161         return getColorForHeight(b);
00162 }
00163 
00164 
00165 
00166 ////////////////////////////////////////////////////////////////////////////////
00167 //
00168 //      entry point
00169 //
00170 ////////////////////////////////////////////////////////////////////////////////
00171 
00172 int
00173 main
00174 (
00175 IN int argc,
00176 IN const char * argv[]
00177 )
00178 {
00179         ASSERT(4 == argc,
00180             "Usage: test_pgm <dimension> <pgm_file> <ppm_file>");
00181 
00182         int dim = atoi(argv[1]);
00183         ASSERT(dim > 1, "bad dimension: %d", dim);
00184         s_width = dim;
00185         s_height = dim;
00186         const char * pgm_file = argv[2];
00187         const char * ppm_file = argv[3];
00188 
00189         std::ofstream opgm(pgm_file);
00190         ASSERT(opgm.good(), "Failed to open pgm file for writing: %s",
00191             pgm_file);
00192         pgmppm::writePgm(opgm, s_width, s_height, s_maxGray, getHeight, NULL);
00193 
00194         std::ofstream oppm(ppm_file);
00195         ASSERT(oppm.good(), "Failed to open ppm file for writing: %s",
00196             ppm_file);
00197         pgmppm::writePpm(oppm, s_width, s_height, s_maxColor, getColor, NULL);
00198 
00199         return 0;
00200 }
00201