图像调整大小在任何GUI框架中几乎是普遍的。事实上,在Web开发中刚开始学习时,你学习的第一件事情之一就是如何使用CSS或HTML的img属性缩放图像。但它是如何工作的呢?
当我要求计算机将一个500x500的图像缩放为100x50,或者相反地,计算机如何知道从原始图像中绘制哪些像素呢?最后,我是否可以用其他编程语言编写自己的“图像转换器”,而不会显著降低性能?
图像调整大小在任何GUI框架中几乎是普遍的。事实上,在Web开发中刚开始学习时,你学习的第一件事情之一就是如何使用CSS或HTML的img属性缩放图像。但它是如何工作的呢?
当我要求计算机将一个500x500的图像缩放为100x50,或者相反地,计算机如何知道从原始图像中绘制哪些像素呢?最后,我是否可以用其他编程语言编写自己的“图像转换器”,而不会显著降低性能?
根据一些研究,我可以得出结论,大多数网络浏览器将使用最近邻或线性插值进行图像调整大小。我编写了一个概念上的最近邻算法,成功地调整了图像大小,尽管非常缓慢。
using System;
using System.Drawing;
using System.Timers;
namespace Image_Resize
{
class ImageResizer
{
public static Image Resize(Image baseImage, int newHeight, int newWidth)
{
var baseBitmap = new Bitmap(baseImage);
int baseHeight = baseBitmap.Height;
int baseWidth = baseBitmap.Width;
//Nearest neighbor interpolation converts pixels in the resized image to pixels closest to the old image. We have a 2x2 image, and want to make it a 9x9.
//Step 1. Take a 9x9 image and shrink it back to old value. To do this, divide the new width by old width (i.e. 9/2 = 4.5)
float widthRatio = (float)baseWidth/newWidth;
float heightRatio = (float)baseHeight/newHeight;
//Step 2. Perform an integer comparison for each pixel in old I believe. If we have a pixel in the new located at (4,5), then the proportional will be
//(.8888, 1.11111) which SHOULD GO DOWN to (0,1) coordinates on a 2x2. Seems counter intuitive, but imagining a 2x2 grid, (4.5) is on the left-bottom coordinate
//so it makes sense the to be on the (0,1) pixel.
var watch = new System.Diagnostics.Stopwatch();
watch.Start();
Bitmap resized = new Bitmap(newWidth, newHeight);
int oldX = 0; int oldY = 0;
for (int i = 0; i < newWidth; i++)
{
oldX = (int)(i*widthRatio);
for (int j = 0; j < newHeight; j++)
{
oldY = (int)(j*heightRatio);
Color newColor = baseBitmap.GetPixel(oldX,oldY);
resized.SetPixel(i,j, newColor);
}
}
//This works, but is 100x slower than standard library methods due to GetPixel() and SetPixel() methods. The average time to set a 1920x1080 image is a second.
watch.Stop();
Console.WriteLine("Resizing the image took " + watch.Elapsed.TotalMilliseconds + "ms.");
return resized;
}
}
class Program
{
static void Main(string[] args)
{
var img = Image.FromFile(@"C:\Users\kpsin\Pictures\codeimage.jpg");
img = ImageResizer.Resize(img, 1000, 1500);
img.Save(@"C:\Users\kpsin\Pictures\codeimage1.jpg");
}
}
}