writePgm/main.cpp

Go to the documentation of this file.
00001 /*
00002  * main.cpp
00003  *
00004  * Copyright (C) 2009  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Program that writes a PGM file, given the raw data in text form on stdin.
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include <fstream>
00036 
00037 #include "common/wave_ex.h"
00038 #include "perf/perf.h"
00039 #include "pgmppm/pgmppm.h"
00040 #include "util/parsing.h"
00041 
00042 
00043 
00044 ////////////////////////////////////////////////////////////////////////////////
00045 ///
00046 /// \ingroup wave_tool
00047 /// \defgroup tool_write_pgm writePgm
00048 ///
00049 /// Simple command-line tool to write PGM files.
00050 ////////////////////////////////////////////////////////////////////////////////
00051 
00052 
00053 // statics and typedefs --------------------------------------------------------
00054 struct context_t {
00055         context_t(void) throw() { this->clear(); }
00056         void clear(void) throw() {
00057                         width = 0;
00058                         height = 0;
00059                         array = NULL;
00060                 }
00061 
00062         // data fields
00063         int             width;
00064         int             height;
00065         byte_t *        array;
00066 };
00067 
00068 
00069 
00070 ////////////////////////////////////////////////////////////////////////////////
00071 //
00072 //      static helper methods
00073 //
00074 ////////////////////////////////////////////////////////////////////////////////
00075 
00076 static int
00077 getPixel
00078 (
00079 IN void * context,
00080 IN int x,
00081 IN int y
00082 )
00083 {
00084         context_t * ctx = (context_t *) context;
00085         ASSERT(ctx, "null");
00086         ASSERT(ctx->array, "null");
00087         ASSERT(x >= 0 && x < ctx->width, "bad x: %d", x);
00088         ASSERT(y >= 0 && y < ctx->height, "bad y: %d", y);
00089 
00090         int idx = (y * ctx->width) + x;
00091         return ctx->array[idx];
00092 }
00093 
00094 
00095 
00096 static void
00097 writePgm
00098 (
00099 IO std::istream& stream,
00100 IN const char * filename
00101 )
00102 {
00103         ASSERT(stream.good(), "bad?");
00104         ASSERT(filename, "null");
00105 
00106         // in general, strip out comments and bogus characters (see parsing.h)
00107         eParseBehavior parseFlags = eParse_Strip;
00108 
00109         // parse PGM data from input stream
00110         std::string line = getNextLineFromStream(stream, parseFlags);
00111         std::string token;
00112 
00113         // first line: width and height
00114         dictionary_t dict;
00115         getDictionaryFromString(line.c_str(), "first line of PGM input", dict);
00116         int width = atoi(getRequiredValue(dict, "width"));
00117         int height = atoi(getRequiredValue(dict, "height"));
00118         if (width < 2 || height < 2) {
00119                 WAVE_EX(wex);
00120                 wex << "Bad width or height: " << width << " x " << height;
00121         }
00122 
00123         // allocate memory for gray values
00124         context_t ctx;
00125         ctx.width = width;
00126         ctx.height = height;
00127         ctx.array = new byte_t[width * height];
00128         ASSERT(ctx.array, "out of memory");
00129 
00130         // now parse xy values
00131         int max_gray = 255;             // hard-coded
00132         byte_t * p = ctx.array;
00133         int expectX = 0;
00134         int expectY = 0;
00135         while (!stream.eof()) {
00136                 line = getNextLineFromStream(stream, parseFlags);
00137                 //DPRINTF("line: %s", line.c_str());
00138                 getDictionaryFromString(line.c_str(), "PGM data line", dict);
00139                 int x = atoi(getRequiredValue(dict, "x"));
00140                 int y = atoi(getRequiredValue(dict, "y"));
00141                 int gray = atoi(getRequiredValue(dict, "g"));
00142 
00143                 if (x != expectX || y != expectY) {
00144                         WAVE_EX(wex);
00145                         wex << "unexpected or out of order x,y values?\n";
00146                         wex << "  expected: (" << expectX << ", " << expectY << ")\n";
00147                         wex << "  read: (" << x << ", " << y << ")";
00148                 }
00149                 if (gray < 0 || gray > max_gray) {
00150                         WAVE_EX(wex);
00151                         wex << "invalid gray value: " << gray;
00152                 }
00153 
00154                 *p = (byte_t) gray;
00155                 ++p;
00156 
00157                 ++expectX;
00158                 if (expectX >= width) {
00159                         expectX = 0;
00160                         ++expectY;
00161                 }
00162 
00163                 if (expectY >= height) {
00164                         break;
00165                 }
00166         }
00167 
00168         // write PGM file
00169         std::ofstream outfile(filename);
00170         if (!outfile.good()) {
00171                 WAVE_EX(wex);
00172                 wex << "Failed to open file for writing: " << filename;
00173         }
00174         pgmppm::writePgm(outfile, width, height, max_gray, getPixel,
00175             (void *) &ctx);
00176 }
00177 
00178 
00179 
00180 ////////////////////////////////////////////////////////////////////////////////
00181 //
00182 //      entry point
00183 //
00184 ////////////////////////////////////////////////////////////////////////////////
00185 
00186 int
00187 main
00188 (
00189 IN int argc,
00190 IN const char * argv[]
00191 )
00192 {
00193         ASSERT(2 == argc, "usage: writePgm <pgm-filename>");
00194         const char * filename = argv[1];
00195 
00196         int retval = 0;
00197 
00198         try {
00199                 perf::Timer timer("overall timer");
00200                 writePgm(std::cin, filename);
00201 
00202         } catch (std::exception& e) {
00203                 DPRINTF("Exception: %s", e.what());
00204                 retval = 1;
00205         }
00206 
00207         // dump timers and leave
00208         perf::dumpTimingSummary(std::cerr);
00209         return retval;
00210 }
00211