通过拍摄一个像素并将其变成具有不同尺寸的新图像上的四个像素来放大图像而不会模糊 [英] Enlarging an image without blurring by taking one pixel and turning it into four on a new image with different dimensions
问题描述
我以前编写过一种图像放大器算法,该算法通过将图像大小加倍并使新图像上的单个像素变为四个像素来放大图像而不会模糊.它最初是为500x500像素的图像而构建的,并且绝对可以正常工作,但是现在我需要将其用于具有不同宽度和高度的图像.
I have previously written an image enlarger algorithm that enlarges images without blurring by doubling the image size and making a single pixel into four pixels on the new image. This was originally built for 500x500 pixel images and it worked absolutely fine but now I need to use it for an image that has a different width and height.
我尝试过更改值,但是我无法使其正常工作,也许有些东西丢失了,但我不知道.有人可以帮助解决此问题,使其适用于不同的尺寸吗?它可以放大500x500像素的图像,但我需要放大的图像是634x490像素.
I have tried changing the values but I cannot get it to work and there maybe something missing but I don't know. Can someone help fix this so it works with different dimensions? It was built to enlarge 500x500 pixel images but the image I need to enlarge is 634x490 pixels.
下面是适用于500x500的原始代码,如果将其粘贴到项目中并运行它,则可以使用该代码,但是必须为其提供500x500像素的图像:
The original code that works with 500x500 is below and this will work if you paste it into a project and run it but you must supply a 500x500 pixel image to it:
Bitmap oldImg = new Bitmap(Image.FromFile(@"NameOfImageToEnlarge.png"));
Bitmap newImg = new Bitmap(1000, 1000);
System.Drawing.Imaging.BitmapData data = oldImg.LockBits(new Rectangle(0, 0, 500, 500), System.Drawing.Imaging.ImageLockMode.ReadOnly, oldImg.PixelFormat);
oldImg.UnlockBits(data);
byte[] rgba = new byte[data.Stride * 500];
System.Runtime.InteropServices.Marshal.Copy(data.Scan0, rgba, 0, data.Stride * 500);
using (Graphics g = Graphics.FromImage(newImg))
{
for (int x = 0; x < 500; x++)
{
for (int y = 0; y < 500; y++)
{
newImg.SetPixel(x * 2, y * 2, Color.FromArgb(oldImg.GetPixel(x, y).ToArgb()));
newImg.SetPixel(x * 2 + 1, y * 2, Color.FromArgb(oldImg.GetPixel(x, y).ToArgb()));
newImg.SetPixel(x * 2, y * 2 + 1, Color.FromArgb(oldImg.GetPixel(x, y).ToArgb()));
newImg.SetPixel(x * 2 + 1, y * 2 + 1, Color.FromArgb(oldImg.GetPixel(x, y).ToArgb()));
}
}
newImg.Save(@"NameOfImageToSave.png");
}
我还使用了一些帮助来使上面的代码正常工作,所以我可能在这里进行了更多说明:
I also used some help to get the code above to work so I may have explained it more here: Taking pixels from one image and enlarging them on a new image to create a larger version of original
推荐答案
您不需要这样做.您使用的方法称为最近邻"插值;您可以设置此属性,然后调用DrawImage
,一切都已设置:
You don't need to do this. The approach you're using is called "Nearest Neighbour" interpolation; you can set this property and then call DrawImage
and you're all set:
using(Bitmap source = ...)
using(Bitmap destination = new Bitmap(1000, 1000))
using(Graphics g = Graphics.FromImage(newImg)) {
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.DrawImage( source, new Rectangle( 0, 0, destination.Width, destination.Height ) );
}
此外,如果您使用的是GetPixel
和SetPixel
,则无需使用LockBits
.实际上,在您的示例中,您先调用LockBits
,然后立即调用UnlockBits
,但是仍然从BitmapData
的指针中读取,这很危险,并且如果在代码执行期间GC转移内存,可能会导致数据损坏正在执行.
Also, if you're using GetPixel
and SetPixel
there is no need to use LockBits
. In fact, in your example you call LockBits
and then immediately call UnlockBits
, but still read from the BitmapData
's pointer, that is dangerous and may result in data-corruption if the GC moves memory around while your code is executing.
这篇关于通过拍摄一个像素并将其变成具有不同尺寸的新图像上的四个像素来放大图像而不会模糊的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!