Просмотр исходного кода

feat: 添加最近邻插值算法实现和绘制

nicetry12138 1 год назад
Родитель
Сommit
9474c2772a

BIN
OpenGL/Image/026.png


+ 34 - 1
OpenGL/README.md

@@ -1063,7 +1063,40 @@ $\alpha_{\text{final}} = \alpha_{\text{global}} \times \alpha_{\text{pixel}}$
 
 
 ![](Image/025.png)
 ![](Image/025.png)
 
 
-如上图所示,蓝色为原始像素,绿色为计算后的像素。也就是说这里是一个缩小图片的计算过程,
+如上图所示,蓝色为原始像素,绿色为计算后的像素。也就是说这里是一个缩小图片的计算过程。
+
+```cpp
+Image* Image::zoomImage(const Image* inImage, float inZoomX, float inZoomY)
+{
+    int width = inImage->GetWidth() * inZoomX;
+    int height = inImage->GetHeight() * inZoomY;
+    byte* data = new byte[width * height * sizeof(RGBA)];
+    for (int x = 0; x < width; ++x) {
+        for (int y = 0; y < height; ++y) {
+            int imageX = (float)x / inZoomX;
+            int imageY = (float)y / inZoomY;
+            imageX = imageX < inImage->GetWidth() ? imageX : inImage->GetWidth() - 1;
+            imageY = imageY < inImage->GetHeight() ? imageY : inImage->GetHeight() - 1;
+            RGBA color = inImage->GetColor(imageX, imageY);
+            memcpy(data + (x + y * width) * sizeof(RGBA), &color, sizeof(RGBA));
+        }
+    }
+
+    Image* newImage = new Image(width, height, data);
+    delete[] data;
+    data = nullptr;
+    newImage->setAlpha(inImage->getAlpha());
+    return newImage;
+}
+```
+
+最近邻插值其实就是很简单的坐标映射,根据坐标计算将缩放后的图片像素映射到源图片上
+
+![](Image/026.png)
+
+上图中左下角为原图片,右上角为放大后的图片,很明显发现锯齿感,放大后图片失真严重,有明显像素块的感觉
+
+
 
 
 ## 图形学状态机接口封装
 ## 图形学状态机接口封装
 
 

+ 1 - 1
OpenGL/src/WindowsProjectTest/WindowsProjectTest/Canvas.cpp

@@ -301,7 +301,7 @@ namespace GT {
 	{
 	{
 		for (int u = 0; u < inImage->GetWidth(); ++u) {
 		for (int u = 0; u < inImage->GetWidth(); ++u) {
 			for (int v = 0; v < inImage->GetHeight(); ++v) {
 			for (int v = 0; v < inImage->GetHeight(); ++v) {
-				RGBA srcColor = inImage->GetColor(u, v);
+				const RGBA srcColor = inImage->GetColor(u, v);
 				if (!m_UseBlend) {
 				if (!m_UseBlend) {
 					drawPoint(Point(inX + u, inY + v, srcColor));
 					drawPoint(Point(inX + u, inY + v, srcColor));
 				}
 				}

+ 29 - 9
OpenGL/src/WindowsProjectTest/WindowsProjectTest/Image.cpp

@@ -6,17 +6,15 @@
 #include "Tool.h"
 #include "Tool.h"
 
 
 namespace GT {
 namespace GT {
-	RGBA Image::GetColor(int x, int y)
+	RGBA Image::GetColor(int x, int y) const
 	{
 	{
-		{
-			if (!UTool::inRange(x, 0, m_Width) || !UTool::inRange(y, 0, m_Height)) {
-				return RGBA(0, 0, 0, 0);
-			}
-			if (m_Data == nullptr) {
-				return RGBA(0, 0, 0, 0);
-			}
-			return m_Data[y * m_Width + x];
+		if (!UTool::inRange(x, 0, m_Width) || !UTool::inRange(y, 0, m_Height)) {
+			return RGBA(0, 0, 0, 0);
 		}
 		}
+		if (m_Data == nullptr) {
+			return RGBA(0, 0, 0, 0);
+		}
+		return m_Data[y * m_Width + x];
 	}
 	}
 
 
 	Image* Image::readFromFile(const char* _fileName)
 	Image* Image::readFromFile(const char* _fileName)
@@ -42,5 +40,27 @@ namespace GT {
 		stbi_image_free(bits);
 		stbi_image_free(bits);
 		return _image;
 		return _image;
 	}
 	}
+	Image* Image::zoomImage(const Image* inImage, float inZoomX, float inZoomY)
+	{
+		int width = inImage->GetWidth() * inZoomX;
+		int height = inImage->GetHeight() * inZoomY;
+		byte* data = new byte[width * height * sizeof(RGBA)];
+		for (int x = 0; x < width; ++x) {
+			for (int y = 0; y < height; ++y) {
+				int imageX = (float)x / inZoomX;
+				int imageY = (float)y / inZoomY;
+				imageX = imageX < inImage->GetWidth() ? imageX : inImage->GetWidth() - 1;
+				imageY = imageY < inImage->GetHeight() ? imageY : inImage->GetHeight() - 1;
+				RGBA color = inImage->GetColor(imageX, imageY);
+				memcpy(data + (x + y * width) * sizeof(RGBA), &color, sizeof(RGBA));
+			}
+		}
+
+		Image* newImage = new Image(width, height, data);
+		delete[] data;
+		data = nullptr;
+		newImage->setAlpha(inImage->getAlpha());
+		return newImage;
+	}
 }
 }
 
 

BIN
OpenGL/src/WindowsProjectTest/WindowsProjectTest/Image.h


+ 10 - 4
OpenGL/src/WindowsProjectTest/WindowsProjectTest/WindowsProjectTest.cpp

@@ -57,8 +57,8 @@ void Render() {
     //    GT::Point(wWidth, 0, GT::RGBA(0, 255, 0, 0)), 
     //    GT::Point(wWidth, 0, GT::RGBA(0, 255, 0, 0)), 
     //    GT::Point(wWidth / 2, wHeight, GT::RGBA(0, 0, 255, 0)));
     //    GT::Point(wWidth / 2, wHeight, GT::RGBA(0, 0, 255, 0)));
 
 
-    _canvas->drawImage(100, 100, _bgImage);
-    _canvas->drawImage(100, 100, _image);
+    _canvas->drawImage(0, 0, _bgImage);
+    _canvas->drawImage(200, 200, _image);
 
 
 	// 将 hMem 的数据一次写入到 hDC 中
 	// 将 hMem 的数据一次写入到 hDC 中
 	BitBlt(hDC, 0, 0, wWidth, wHeight, hMem, 0, 0, SRCCOPY);
 	BitBlt(hDC, 0, 0, wWidth, wHeight, hMem, 0, 0, SRCCOPY);
@@ -115,8 +115,14 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
 
 
 	_canvas = new GT::Canvas(wWidth, wHeight, buffer);
 	_canvas = new GT::Canvas(wWidth, wHeight, buffer);
 	_image = GT::Image::readFromFile("res/carma.png");
 	_image = GT::Image::readFromFile("res/carma.png");
-    _image->setAlpha(.3f);
-    _bgImage = GT::Image::readFromFile("res/bk.jpg");
+    //_image->setAlpha(.9f);
+
+	GT::Image* zoomImage = GT::Image::zoomImage(_image, 2, 2);
+	//GT::Image* zoomImage = GT::Image::zoomImage(_image, .5f, .5f);
+    delete _image;
+    _image = zoomImage;
+
+    _bgImage = GT::Image::readFromFile("res/carma.png");
 	//_zoomImage = GT::Image::zoomImage(_image, 3, 3);
 	//_zoomImage = GT::Image::zoomImage(_image, 3, 3);
 	//_zoomImageSimple = GT::Image::zoomImageSimple(_image, 3, 3);
 	//_zoomImageSimple = GT::Image::zoomImageSimple(_image, 3, 3);
 	//// _image->setAlpha(0.5);
 	//// _image->setAlpha(0.5);