C#调整大小的图像有黑色边框
我在.NET中遇到图像缩放问题。我使用标准图形类型调整图像大小,如本例所示:C#调整大小的图像有黑色边框,c#,.net,image,scaling,C#,.net,Image,Scaling,我在.NET中遇到图像缩放问题。我使用标准图形类型调整图像大小,如本例所示: public static Image Scale(Image sourceImage, int destWidth, int destHeight) { Bitmap toReturn = new Bitmap(sourceImage, destWidth, destHeight); toReturn.SetResolution(sourceImage.HorizontalResol
public static Image Scale(Image sourceImage, int destWidth, int destHeight)
{
Bitmap toReturn = new Bitmap(sourceImage, destWidth, destHeight);
toReturn.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
using (Graphics graphics = Graphics.FromImage(toReturn))
{
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.DrawImage(sourceImage, 0, 0, destWidth, destHeight);
}
return toReturn;
}
但是我对调整大小的图像有一个很大的问题:它们有灰色和黑色的边框,所以制作没有边框的图像非常重要
为什么它们会出现,我能做些什么让它们消失
样本输出:
以下内容对您有何作用?这是我用来做同样事情的代码。我注意到的主要区别是我不使用SetResolution(我假设输入和输出为正方形,因为我就是这样)
//
///调整正方形图像的大小
///
///要调整大小的图像
///新图像的宽度和高度
///图像的缩放版本
内部静态图像大小图像(图像原始图像,整数大小)
{
图像最终图像=新位图(大小、大小);
Graphics graphic=Graphics.FromImage(最终图像);
graphic.CompositingQuality=System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
graphic.SmoothingMode=System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
graphic.InterpolationMode=System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
矩形矩形=新矩形(0,0,大小,大小);
图形.绘图图像(原始图像,矩形);
返回最终授权;
}
这是因为采样是从照片的边缘进行的。这是因为在绘制图像时边缘平滑(与背景混合)
您可以绘制两次,一次不绘制,一次启用平滑。或者你可以把它画大一点。或者,如果已知原始背景色,您可以先用背景色填充图像。尝试:
graphic.CompositingMode = CompositingMode.SourceCopy;
问题在于,位图
toReturn
默认背景为黑色。
在其上复制新图像会生成黑色或灰色边框
解决方案是通过调用以下命令删除黑色默认背景:
toReturn.MakeTransparent();
因为在这条线之后,您将在没有任何背景色的新图像上绘制,因此边框将消失。这可能是由于边缘周围的像素被错误插值造成的。我称之为虫子 不过,以下是解决方案:
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.PixelOffsetMode = PixelOffsetMode.Half;
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
// Draw your image here.
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Draw it again.
这样做的目的是首先绘制一个边缘正确填充的“背景”,然后用插值再次绘制。如果不需要插值,则不需要插值。真正的解决方案是使用
DrawImage
的重载,它允许您传递ImageAttributes
对象
在ImageAttributes
实例上,在将以下方法传递给DrawImage
之前,调用该方法:
using (var ia = new ImageAttributes())
{
ia.SetWrapMode(WrapMode.TileFlipXY);
aGraphic.DrawImage(..., ia);
}
另请参见这些都不适合我 但是,将格式从
System.Drawing.Imaging.PixelFormat.Format24bppRgb
到
问题解决了吗
using (System.Drawing.Bitmap newImage = new System.Drawing.Bitmap(newWidth, newHeight,
// System.Drawing.Imaging.PixelFormat.Format24bppRgb // OMG bug
System.Drawing.Imaging.PixelFormat.Format32bppArgb
))
{
从其他一些回答中可以拼凑出一个正确的答案,但没有一个是完整的,有些回答提出了一些非常糟糕的想法(比如画两次图像) 问题 您看到的工件有三个原因:
Graphics.PixelOffsetMode
设置会导致像素值采样错误,从而导致图像轻微失真,尤其是边缘周围InterpolationMode.HighQualityBicubic
从图像边缘以外的像素进行采样,默认情况下这些像素是透明的。取样器将这些透明像素与边缘像素混合,形成半透明边缘位图
构造函数正在通过调整原始图像的大小初始化新的位图
,因此您要执行两次调整大小操作。您应该使用只包含所需维度的构造函数重载来创建空白画布
请记住,Bitmap
类表示内存中图像的非托管副本。需要对其进行处理,以便GDI+在处理完后可以被告知释放该内存。我假设您在接收返回的图像
的代码中这样做,但我指出,以防其他人借用此代码
如果其他设置正确,代码中使用的CompositingQuality.HighQuality
设置将不会产生视觉效果,并且与默认值CompositingMode.SourceOver组合使用时,实际上会显著降低性能。您可以省略CompositingQuality
设置并设置CompositingMode.SourceCopy
,以获得相同的结果和更好的性能
代码中使用的SmoothingMode
设置对DrawImage()
没有任何影响,因此可以将其删除
解决方案
移除这些瑕疵的正确方法是使用PixelOffsetMode.Half
,并使用ImageAttributes
对象指定边缘平铺,以便HighQualityBicubic
采样器具有透明像素以外的采样
您可以在此处阅读有关图形类设置及其对图像质量和性能的影响的更多信息:
修订后的代码应如下所示:
public static Image Scale(Image sourceImage, int destWidth, int destHeight)
{
var toReturn = new Bitmap(destWidth, destHeight);
using (var graphics = Graphics.FromImage(toReturn))
using (var attributes = new ImageAttributes())
{
toReturn.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
attributes.SetWrapMode(WrapMode.TileFlipXY);
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.Half;
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.DrawImage(sourceImage, Rectangle.FromLTRB(0, 0, destWidth, destHeight), 0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel, attributes);
}
return toReturn;
}
对于这些图像,发送到浏览器的HTML是什么样子的?图像的原始类型是什么?我遇到了同样的问题,发布了我的解决方案。图像不再向上,但如果在边缘上看到1px边框,可以通过将ImageAttributes实例传递到设置了TileFlipXY的DrawImage()来修复。这使得相互作用重复使用外部像素边缘,而不是对背景或透明颜色进行平均。资料来源:不幸的是,这根本不是解决办法。它有
using (System.Drawing.Bitmap newImage = new System.Drawing.Bitmap(newWidth, newHeight,
// System.Drawing.Imaging.PixelFormat.Format24bppRgb // OMG bug
System.Drawing.Imaging.PixelFormat.Format32bppArgb
))
{
public static Image Scale(Image sourceImage, int destWidth, int destHeight)
{
var toReturn = new Bitmap(destWidth, destHeight);
using (var graphics = Graphics.FromImage(toReturn))
using (var attributes = new ImageAttributes())
{
toReturn.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
attributes.SetWrapMode(WrapMode.TileFlipXY);
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.Half;
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.DrawImage(sourceImage, Rectangle.FromLTRB(0, 0, destWidth, destHeight), 0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel, attributes);
}
return toReturn;
}