📄 image.hpp
字号:
// $image\image.hpp 1.5 milbo$// Warning: this is raw research code -- expect it to be quite messy.#if !defined(image_hpp)#define image_hpp#define IM_NO_CLEAR 0 // values for fClear#define IM_CLEAR 1#define CONF_nMaxImageDim 10000 // somewhat arbitrary, mostly used for parameter sanity checking// CIE conversion to gray using integer arithmetic, add 500 to take care of rounding #define RgbToGray(Rgb) ((299 * (Rgb).Red + 587 * (Rgb).Green + 114 * (Rgb).Blue + 500) / 1000)// Convert shape to image coords (TODO move this def?)#define xShapeToImg(x, Img) ((x) + (Img).width/2)#define yShapeToImg(y, Img) ((y) + (Img).height/2) //TODO this may be wrong#define xImgToShape(x, Img) ((x) - (Img).width/2)#define yImgToShape(y, Img) ((y) - (Img).height/2)#if DEBUG_IMAGEextern void __cdecl lprintf(const char *pArgs, ...); // args like printf#endif#ifndef byte#define byte unsigned char#endiftypedef struct tRGB // same layout as RGBTRIPLE in windows file wingdi.h { byte Blue, Green, Red; // we assume packing is on byte boundaries i.e. size of this is 3 bytes }tRGB;//-----------------------------------------------------------------------------template <typename T>class ImageT // templated image, typically instantiate to ImageT<byte> or ImageT<tRGB>{public:T *buf;int width, height;ImageT() :buf(NULL), width(0), height(0) {} // null constructorImageT(int width1, int height1, bool fClear=false): buf(NULL), width(width1), height(height1) { ASSERT(width1 >= 0 && width1 <= CONF_nMaxImageDim && height1 >= 0 && height1 <= CONF_nMaxImageDim); unsigned nLen = width1 * height1; if (nLen) { if (fClear) buf = (T *)calloc(nLen, sizeof(T)); else buf = (T *)malloc(nLen * sizeof(T)); } }template<typename S> ImageT(const ImageT<S> &other) :buf(NULL) { copy(other); }; // construct by copying an image of another typeImageT(const ImageT &other) :buf(NULL) { copy(other); }; // construct by copying an image of same typeImageT(const char sPath[], bool fVerbose=false, bool fExitOnErr=true): buf(NULL) // load image from a file { sLoadImage(*this, sPath, fVerbose, fExitOnErr); }~ImageT() { free(); }T &operator()(int iRow, int iCol) { return buf[iRow + iCol * width]; } // get pixel at iRow,iColconst T &operator()(int iRow, int iCol) const { return buf[iRow + iCol * width]; }T &operator()(int i) { return buf[i]; } // get pixel at iconst T &operator()(int i) const { return buf[i]; }T pixel(int ix, int iy) { return buf[ix + width/2 + (iy + height/2) * width]; } // get pixel using shape coordsconst T pixel(int ix, int iy) const { return buf[ix + width/2 + (iy + height/2) * width]; }// Assignment copies the whole pixel buffer. This is sometimes slower than // optimal, depending on what you are doing with "other" and "this" in your// subsequent code. The advantage is that we don't need reference counts // because we don't share pixel buffers.//// When necessary, this automatically redimensions the lhs to match the rhs// and does a type conversion.ImageT &operator=(const ImageT &other) { copy(other); return *this; }bool operator==(const ImageT<T> &other) const { if (width != other.width || height != other.height) return false; return 0 == memcmp(buf, other.buf, width * height * sizeof(T)); }bool operator!=(const ImageT &other) const { return !(*this == other); }void dim (int width1, int height1) // redimension, contents random, quicker than dimClear { int nelems = width1 * height1; if (nelems != width * height) { DASSERT(width1 >= 0 && width1 <= CONF_nMaxImageDim && height1 >= 0 && height1 <= CONF_nMaxImageDim); free(); buf = (T *)malloc(nelems * sizeof(T)); } width = width1; height = height1; }void dimClear (int width1, int height1) const // redimension and fill with 0s { free(); DASSERT(width1 >= 0 && width1 <= CONF_nMaxImageDim && height1 >= 0 && height1 <= CONF_nMaxImageDim); buf = (T *)calloc(width1 * height1, sizeof(T)); width = width1; height = height1; }void free(void) { if (buf) { ::free(buf); buf = NULL; } width = 0; height = 0; }private:void copyBuf (T *pTo, const T *const pFrom, int width, int height) { memcpy(pTo, pFrom, width * height * sizeof(T)); }void copyBuf (byte *pTo, const tRGB *const pFrom, int width, int height) // specialization for type conversion { for (int iy = 0; iy < height; iy++) for (int ix = 0; ix < width; ix++) { tRGB Pix = pFrom[ix + ((height - 1 - iy) * width)]; pTo[ix + iy * width] = RgbToGray(Pix); } }void copyBuf (tRGB *pTo, const byte *const pFrom, int width, int height) // specialization for type conversion { for (int iy = 0; iy < height; iy++) for (int ix = 0; ix < width; ix++) { tRGB Pix; Pix.Red = Pix.Green = Pix.Blue = pFrom[ix + ((height - 1 - iy) * width)]; pTo[ix + iy * width] = Pix; } }template<typename S>void copy(const S &other) { if (static_cast<const void *>(this) != static_cast<const void *>(&other)) { free(); unsigned nLen = other.width * other.height; buf = (T *)malloc(nLen * sizeof(T)); width = other.width; height = other.height; copyBuf(buf, other.buf, width, height); // does type conversion when needed } }};typedef ImageT<byte> Image;typedef ImageT<tRGB> RgbImage;#endif // image_hpp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -