00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
00041 { -1, { 0, 0, 0 } }
00042 };
00043
00044
00045
00046
00047
00048
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
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
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
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
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