上一章介紹的色彩空間轉換,都是使用一維陣列處理,接著因為要用到類似捲積的方式去做濾鏡,所以將一維陣列轉為二維陣列存取能增加可讀性,而在轉二維陣列之前要先實現填補功能,而在OpenCV函數為copyMakeBorder,它有很多不同的填補類型,今天我們要做的單純補上0跟捲積處理方式一樣,以下開始介紹填補。
這裡使用到Assert是方便進行Debug(單元測試也很好用),主要將自己認為絕對不可能地排除在外,若不成立則會跳出錯誤訊息,詳細使用可到assert觀看,而[1]提到加入#define NDEBUG,assert就會關閉(assert也會吃效能,發行通常會關閉)。
填補是將上下左右擴充到需要的大小,假如填補為1,如下圖,可以看到要填補的地方為紅色和藍色,而在C++能使用拷貝記憶體值的函數memcpy來去達成,輸出圖的大小則是在C#函數處理好,為了記憶體方便自己控管盡量不要在C++回傳指標。
輸出圖大小為:(輸入圖寬 + 2 * padding) * (輸入圖高 + 2 * padding)。
C++加入ImagePadding8bit函數:
標頭檔:Library.h
	/*
		ImagePadding8bit Parameter:
		src		= source of image
		pur		= purpose of image
		width		= Image's width
		height		= Image's height
		pad		= padding size
	*/
	void ImagePadding8bit(C_UCHAE* src, UCHAE* pur
		, C_UINT32 width, C_UINT32 height
		, C_INT32 pad);
加入實作檔:Library.cpp
void Library::ImagePadding8bit(C_UCHAE* src, UCHAE* pur
	, C_UINT32 width, C_UINT32 height
	, C_INT32 pad)
{
	assert(src != nullptr && pur != nullptr);
	assert(width > 0 && height > 0);
	assert(pad >= 0);
	C_UINT32 copySize = width * sizeof(UCHAE);
	C_UINT32 purWidth = (width + 2 * pad);
	C_UCHAE* srcEnd = src + width * height;
	pur += (pad * purWidth) + pad;
	while (src < srcEnd)
	{
		memcpy(pur, src, copySize);
		pur += purWidth;
		src += width;
	}
}
C#加入mndtImagePadding8bit函數:
MNDTLibrary.cs
        [DllImport(DLL_PATH)]
        unsafe private static extern void mndtImagePadding8bit(IntPtr src, IntPtr pur, int width, int height, int pad);
        public Bitmap ImagePadding8bit(Bitmap srcImage, int pad)
        {
            Bitmap purImage = new Bitmap(srcImage.Width + pad * 2, srcImage.Height + pad * 2, PixelFormat.Format8bppIndexed);
            Rectangle size = new Rectangle(0, 0, srcImage.Width, srcImage.Height);
            BitmapData srcData = srcImage.LockBits(size, ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
            BitmapData purData = purImage.LockBits(size, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
            unsafe
            {
                IntPtr srcPtr = srcData.Scan0;
                IntPtr purPtr = purData.Scan0;
                mndtImagePadding8bit(srcPtr, purPtr, srcImage.Width, srcImage.Height, pad);
            }
            purImage.Palette = _colorPalette;
            srcImage.UnlockBits(srcData);
            purImage.UnlockBits(purData);
            return purImage;
        }
呼叫方式,先轉為灰階8bit。
Bitmap bitmap =  _lib.Change8BitColor(_fileImage, ColerType.BGR2GRAY_8BIT);
pic_pur.Image = _lib.ImagePadding8bit(bitmap, 10);

目前只有長、寬和二維指標。
主要建立height大小指標指向每個width的第一個,解構式記得要刪除指標並指向nullptr。
新增標頭檔:Image.h
#pragma once
#ifndef IMAGE_H
#define IMAGE_H
#include "general.h"
class Image
{
public:
	/*
		Image Parameter:
		src			= source of image
		width		= Image width
		height		= Image height
		type		= Image type
	*/
	Image(UCHAE* src
		, C_UINT32 width, C_UINT32 height
		, C_UINT32 type);
	~Image();
	UINT32 Width() const;
	UINT32 Height() const;
	UCHAE** image;
private:
	MNDT::ImageType _type;
	UINT32 _width;
	UINT32 _height;
};
#endif // !IMAGE_H
新增實作檔:Image.cpp
#include "Image.h"
Image::Image(UCHAE* src
	, C_UINT32 width, C_UINT32 height
	, C_UINT32 type)
{
	_width = width;
	_height = height;
	_type = static_cast<MNDT::ImageType>(type);
	image = new UCHAE*[height];
	for (UINT32 index = 0; index < height; index++)
	{
		*(image + index) = (src + width * index);
	}
}
Image::~Image()
{
	delete[] image;
	image = nullptr;
}
UINT32 Image::Width() const 
{
	return _width;
}
UINT32 Image::Height() const 
{
	return _height;
}
接著就可以開始介紹各式各樣的濾波器,後面使用濾波器的頻率會很大所以必須先知道這些方便往後處理,若有問題歡迎提問和指導。
[1]http://www.cplusplus.com/reference/cassert/assert/