1.image類
// image class template <class T> class image { public: // create image image(const int width, const int height, const bool init = false); // delete image ~image(); // init image void init(const T &val); // deep copy image<T> *copy() const; // get image width/height int width() const { return w; } int height() const { return h; } // image data T *data; // row pointers T **access; private: int w, h; };
-
構造函數(生成圖像)
image(const int width, const int height, const bool init = false);
- 參數:width, height, init
- width:圖像的寬;
- height:圖像的高;
- init:是否初始化;
template <class T> image<T>::image(const int width, const int height, const bool init) { w = width; h = height; data = new T[w * h]; // allocate space for image data access = new T*[h]; // allocate space for row pointers // initialize row pointers for (int i = 0; i < h; i++) access[i] = data + (i * w); // init to zero if (init) memset(data, 0, w * h * sizeof(T)); }
說明:
T **access = new T*[h];
- T *[h]:一個h個元素的指針數組,每個元素可指向一個T類型的數據。
- new T *[h]:申請h個指向T類型的指針數組,其中每個指針都可以指向一個T類型的數組。
- T **access = new T *[h]:定義一個access指針變量,指向數組的首元素。
for (int i = 0; i < h; i++) access[i] = data + (i * w);
- 將二維數組每一行的首地址符給access[i]指針。
if (init) memset(data, 0, w * h * sizeof(T));
- memset函數
void *memset(void *s, int c, unsigned long n);
- memset() 的作用是在一段內存塊中填充某個給定的值。
-
析構函數 (釋放掉圖像)
~image();
template <class T> image<T>::~image() { delete [] data; delete [] access; }
delete
和
delete
[] 的不同之處在對
class
的釋放,
delete
只會調用一個元素的析構函數,而
delete
[]則調用所有元素的析構。
-
初始化函數
void init(const T &val);
template <class T> void image<T>::init(const T &val) { T *ptr = imPtr(this, 0, 0); T *end = imPtr(this, w-1, h-1); while (ptr <= end) *ptr++ = val; }
- 在 C++ 中,每一個對象都能通過 this 指針來訪問自己的地址。this 指針是所有成員函數的隱含參數。因此,在成員函數內部,它可以用來指向調用對象。友元函數沒有 this 指針,因爲友元不是類的成員。只有成員函數纔有 this 指針。
#define imRef(im, x, y) (im->access[y][x]) #define imPtr(im, x, y) &(im->access[y][x])
- ++的優先級高於×號
-
深度拷貝函數
image<T> *copy() const;
template <class T> image<T> *image<T>::copy() const { image<T> *im = new image<T>(w, h, false); memcpy(im->data, data, w * h * sizeof(T)); return im; }
void *memcpy(void *destin, void *source, unsigned n);
-
獲取圖像的高/寬
int width() const { return w; } int height() const { return h; }
-
成員變量:
- public:
// image data T *data; // row pointers T **access;
- private
int w, h;
// basic image I/O, based on Pedro Felzenszwalb's code
#ifndef IMAGE_H
#define IMAGE_H
#include <cstdlib>
#include <climits>
#include <cstring>
#include <fstream>
// use imRef to access image data.獲取圖片數據
#define imRef(im, x, y) (im->access[y][x])
// use imPtr to get pointer to image data.獲取圖片數據指針
#define imPtr(im, x, y) &(im->access[y][x])
#define BUF_SIZE 256
typedef unsigned char uchar;
typedef struct { uchar r, g, b; } rgb;
inline bool operator==(const rgb &a, const rgb &b) {
return ((a.r == b.r) && (a.g == b.g) && (a.b == b.b));
}
// image class模板類 T可以用各種類型代替
template <class T> class image {
public:
// create image
image(const int width, const int height, const bool init = false);
// delete image
~image();
// init image
void init(const T &val);
// deep copy
image<T> *copy() const;
// get image width/height
int width() const { return w; }
int height() const { return h; }
// image data
T *data;
// row pointers
T **access;
private:
int w, h;
};
template <class T> image<T>::image(const int width, const int height, const bool init) {
w = width;
h = height;
data = new T[w * h]; // allocate space for image data爲圖片數據分配空間
access = new T*[h]; // allocate space for row pointers爲行指針分配空間
// initialize row pointers
for (int i = 0; i < h; i++)
access[i] = data + (i * w); //初始化行指針
// init to zero
if (init)
memset(data, 0, w * h * sizeof(T));//初始化全0
}
template <class T> image<T>::~image() {
delete [] data;
delete [] access;
}
template <class T> void image<T>::init(const T &val) {
T *ptr = imPtr(this, 0, 0);//取(0,0)地址
T *end = imPtr(this, w-1, h-1);
while (ptr <= end)
*ptr++ = val;
}
template <class T> image<T> *image<T>::copy() const {
image<T> *im = new image<T>(w, h, false);//硬拷貝
memcpy(im->data, data, w * h * sizeof(T));//memcpy 目的 源 大小
return im;
}
class pnm_error {};
void pnm_read(std::ifstream &file, char *buf) {
char doc[BUF_SIZE];
char c;
file >> c;
while (c == '#') {
file.getline(doc, BUF_SIZE);//至少讀取BUF_SIZE個字符到doc裏面
file >> c;
}
file.putback(c);//把c重新放回輸入流,可以被再次讀取
file.width(BUF_SIZE);//輸入BUF_SIZE-1個字符
file >> buf;
file.ignore();//默認參數爲cin.ignore(1,EOF),即把EOF前的1個字符清掉,沒有遇到EOF就清掉一個字符然後結束
}
image<uchar> *loadPGM(const char *name) {
char buf[BUF_SIZE];
// read header
std::ifstream file(name, std::ios::in | std::ios::binary);
pnm_read(file, buf);
if (strncmp(buf, "P5", 2)) {
//str1與str2的前n個字符相同,則返回0;若s1大於s2,則返回大於0的值;若s1 小於s2,則返回小於0的值。
std::cout << "ERROR: Could not read file " << name << std::endl;
throw pnm_error();
}
pnm_read(file, buf);
int width = atoi(buf);
pnm_read(file, buf);
int height = atoi(buf);
pnm_read(file, buf);
if (atoi(buf) > UCHAR_MAX) {//無符號char型所能表示的最大整數
std::cout << "ERROR: Could not read file " << name << std::endl;
throw pnm_error();
}
// read data
image<uchar> *im = new image<uchar>(width, height);
file.read((char *)imPtr(im, 0, 0), width * height * sizeof(uchar));
return im;
}
void savePGM(image<uchar> *im, const char *name) {
int width = im->width();
int height = im->height();
std::ofstream file(name, std::ios::out | std::ios::binary);
file << "P5\n" << width << " " << height << "\n" << UCHAR_MAX << "\n";
file.write((char *)imPtr(im, 0, 0), width * height * sizeof(uchar));
}
#endif