00001 00002 # ifndef Image_h 00003 # define Image_h Image_h 00004 00005 // C++ Dependencies 00006 # include <string> // uses 00007 # include "Coord.h" // Coord, uint8_t 00008 # include "ImageArgs.h" // ImageArgs 00009 # include "Page.h" // needs friendship for special Image constructor 00010 00011 // C Dependencies 00012 # include "pnm.h" // struct pixmap 00013 00014 namespace Conjecture { 00015 /******************************************************************* 00016 * \class Image 00017 * 00018 * \brief The in-memory representation of the graphical image 00019 * being processed. 00020 * 00021 * Although arbitrary graphical formats will be supported, all 00022 * formats will be converted to pnm, and the internal memory 00023 * representation will be pnm-based (mostly pgm, greyscale). 00024 * 00025 * IMPORTANT: This class is an early candidate for disassociation from 00026 * underlying GOCR C-code reliance. Instead of using the GOCR routines, 00027 * it will be straight-forward to write our own, or use a universally 00028 * available library. We can rely on the existence of the 'convert' 00029 * executable to perform conversions from arbitrary formats to pnm, 00030 * and provide support here for reading and writing pnm files. 00031 * 00032 * FUTURE FIX: The 'verbose' flag to the various methods is dirty. 00033 * Would a static Verbose field be better? Or do we formalize a 00034 * Config structure that can be used by many classes, and have 00035 * 'verbose' be one of the fields in this struct? Passing an optional 00036 * Config pointer seems much cleaner than just passing around a boolean 00037 * value. Code of the form: 00038 * pgmWrite("file.pbm", true); 00039 * just isn't readable, although admittedly 00040 * pgmWrite("file.pbm", verbose); 00041 * is more so. But 00042 * pgmWrite("file.pbm", config); 00043 * is more general. 00044 * 00045 *******************************************************************/ 00046 class Image : public Root { 00047 00048 public: 00049 Image(const std::string& file, bool verbose = false); 00050 00051 /* 00052 * Create a copy of a sub-region of another Image. 00053 * 00054 * 'topleft' and 'bottomright' identify the pixel boundaries of 00055 * the desired region, and are relative to <0,0> in the top left 00056 * corner of 'src'. 00057 * 00058 * See the documentation of ImageConfig for the 'config' parameter. 00059 * 00060 */ 00061 Image(const Image* src, const Coord& topleft, const Coord& bottomright, const ImageArgs& config); 00062 00063 /* 00064 * Destructor for Image instances. 00065 * 00066 * This destructor is critical, because images may be created and 00067 * destroyed often (and allocate nested space). 00068 * 00069 */ 00070 ~Image(); 00071 00072 /* 00073 * Obtain the pixel value for position <x,y> 00074 * 00075 */ 00076 inline u1 get(u2 x, u2 y) const { return this->_data->p[this->index(x,y)]; } 00077 inline u1 get(const Coord& pos) const { return this->_data->p[this->index(pos.x,pos.y)]; } 00078 00079 inline void set(u2 x, u2 y, int val) { this->_data->p[this->index(x,y)] = val; } 00080 inline void set(const Coord& pos, int val) { this->_data->p[this->index(pos.x,pos.y)] = val; } 00081 00082 // Miscellaneous 00083 bool writeMono(const std::string& filebase, bool verbose = false) const; 00084 bool writeGrey(const std::string& filebase, bool verbose = false) const; 00085 bool writeColor(const std::string& filebase, bool verbose = false) const; 00086 00087 /* 00088 * Images can be stored either monochrome, greyscale or color. 00089 * The latter uses 3 bytes per pixel, the former two use 1 byte 00090 * per pixel. FUTURE FIX: I assume pbm packs 8 into one byte?? 00091 * 00092 * FUTURE FIX: Should we not bother with color at all, and always 00093 * read images in greyscale? Problem with this is that color may 00094 * provide useful hints for partitioning and maybe even 00095 * identification. For now, we maintain support for color, 00096 * although the primary focus currently is on greyscale analysis. 00097 * 00098 */ 00099 int bytesPerPixel() const { return this->_data->bpp; } 00100 00101 /* 00102 * Unit testing method. 00103 * 00104 * This static method should create instances of the class (and 00105 * instances of any other class necessary) and perform tests to 00106 * ensure that all methods within the class are working as 00107 * expected. 00108 * 00109 */ 00110 static void test(int argc = 0, const char* argv[] = NULL); 00111 00116 Coord size() const { return Coord(this->data()->x, this->data()->y); } 00117 00122 uint16_t width() const { return this->size().x; } 00123 00128 uint16_t height() const { return this->size().y; } 00129 00130 // Accessors 00131 00132 // This field must go away! 00133 inline const pix* data() const { return this->_data; } 00134 00135 protected: 00136 // Accessors 00137 inline void dataIs(pix* data) { this->_data = data; } 00138 00139 // Methods 00140 00145 inline int index(u2 x, u2 y) const { return x + y*this->_data->x; } 00146 00147 private: 00148 // Methods 00149 00150 // Accessors 00151 inline pix* dataRef() { return this->_data; } 00152 00153 // State 00154 00155 // This field has no public access - dirty - must replace with 00156 // something cleaner! 00157 pix* _data; 00158 }; 00159 }; 00160 00161 # endif // Image_h 00162