gpt4 book ai didi

c# - 如何避免在具有透明背景的调整大小的 PNG 中出现无用的白色边框?

转载 作者:行者123 更新时间:2023-11-30 15:07:48 30 4
gpt4 key购买 nike

我有一个包含大约 2500 张 PNG 图像的文件夹,没有透明度。每张图片大约为 500 x 500(有些是 491 x 433,有些是 511 x 499 等)。

我想以编程方式将每个图像缩小到其原始大小的 10%,并将每个图像的白色背景设置为透明色。

为了在每次不调整 2500 张图片的情况下测试我的应用程序的功能,我使用了 15 张台球图片作为“测试”文件夹。

现在我的问题是以下代码,我得到一个调整大小和裁剪的 PNG,具有几乎透明背景。问题是在每个图像查看器(Irfan View、Paint.Net 和 GIMP)中左侧和顶部出现白色边框

我怎样才能避免这个边界?

这是我为此使用的代码:

void ResizeI(string[] Paths, string OutPut, Methods m, PointF Values, bool TwoCheck, bool Overwrite, float[] CropVals)
{
for (int i = 0; i < Paths.Length; i++)//Paths is the array of all images
{
string Path = Paths[i];//current image
Bitmap Oimg = (Bitmap)Bitmap.FromFile(Path);//original image
Bitmap img = new Bitmap((int)(Oimg.Width - CropVals[0] - CropVals[1]), (int)(Oimg.Height - CropVals[2] - CropVals[3]));//cropped image
Graphics ggg = Graphics.FromImage(img);
ggg.DrawImage(Oimg, new RectangleF(((float)-CropVals[0]), ((float)-CropVals[2]), Oimg.Width - CropVals[1], Oimg.Height - CropVals[3]));
ggg.Flush(System.Drawing.Drawing2D.FlushIntention.Flush);
ggg.Dispose();
PointF scalefactor = GetScaleFactor(img, Values, TwoCheck);//the scale factor equals 0.1 for 10%
Bitmap newimg = new Bitmap((int)(Math.Ceiling(((float)img.Width) * scalefactor.X)), (int)(Math.Ceiling(((float)img.Height) * scalefactor.Y)));
System.Drawing.Imaging.ImageFormat curform = img.RawFormat;
string OutPath = System.IO.Path.Combine(OutPut, System.IO.Path.GetFileName(Path));
OutPath = CheckPath(OutPath, Overwrite);//Delete if exsits
Graphics g = Graphics.FromImage(newimg);
g.InterpolationMode = GetModeFromMethod(m);//Bicubic interpolation
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.ScaleTransform(scalefactor.X, scalefactor.Y);
g.DrawImage(img, new Rectangle(0, 0, (int)Math.Ceiling(((float)newimg.Width) / scalefactor.X) + 1, (int)Math.Ceiling(((float)newimg.Height) / scalefactor.Y) + 1));
//g.Flush(System.Drawing.Drawing2D.FlushIntention.Flush);
newimg.MakeTransparent(Color.White);
newimg.Save(OutPath, curform);
g.Dispose();
img.Dispose();
}
}

这是我提到的白色边框的示例。下载图片或四处拖动并在其下方放置黑色背景以查看边框:

The resized Image and the white border

-- 编辑--

我设法编写了这个函数而不是 newimg.MakeTransparent(...):

 void SetTransparent(ref Bitmap b)
{
for (int i = 0; i < b.Width; i++)
{
for (int ii = 0; ii < b.Height; ii++)
{
Color cc = b.GetPixel(i, ii);
int tog = cc.R + cc.G + cc.B;
float durch = 255f - (((float)tog) / 3f);
b.SetPixel(i, ii, Color.FromArgb((int)durch, cc.R, cc.G, cc.B));
}
}
}

问题是我的台球现在看起来像这样:

Second version of the billiard ball

最佳答案

我无法提供具体代码,但也许可以解释发生了什么。

newimg.MakeTransparent(Color.White);

这将采用一种颜色,并使其透明。要注意的是,台球边缘(橙色)和纯白色背景之间存在一系列颜色。这是边缘的抗锯齿(它将混合从球的纯橙色到背景的纯白色的颜色)。

通过仅将纯白色变为透明,您仍然会在对象周围留下这种白色的“光环”。

使用白色值作为 alpha 掩码也许有更好的方法来处理这个问题,但我不确定 .net 的图像库是否可以处理这个问题(我将不得不向具有更多 .net 经验的人求助)。

不过,在此期间,如果您在调整大小之前设置透明度,可能会有帮助。这不是真正的修复,但可能会减少一些光环效果。

更新:

所以,我一直在考虑这个问题,但我不完全确定是否有自动创建 alpha channel 透明度的编程解决方案,因为我有一种预感,其中涉及很多主观因素。

在我的脑海中,这就是我想出的:

  • 假设左上角的像素是 100% 透明的颜色(我们称像素 X)。
  • 假设您想要透明的背景是一种纯色(相对于图案)
  • 假设大约 3px 抗锯齿

然后你可以...

  • 检查 X 的相邻像素。对于 X 的每个与 X 颜色匹配的相邻像素,我们将其设置为 100% 透明。
  • 如果 x 旁边的像素不相同,我们可以检查它的相对色调。
  • 从该像素分支并检查它周围的像素。
  • 标记每个像素(a、b、c 等),直到相对色调改变一定百分比和/或像素颜色与其相邻像素相同(具有一定的可变范围)。如果确实如此,我们将假设我们已经进入了物体的内部。
  • 现在通过您标记的像素向后退一步,调整透明度...比如 c=0% b=33% a=66%

但是,这仍然是对真正必须发生的事情的过度简化。它做出了很多假设,没有考虑带图案的背景,并且完全忽略了也需要透明的内部区域(例如 donut 洞)。

通常在图形编辑应用程序中,这是通过选择背景色 block 、羽化所述选择的边缘,然后将其转换为最大 alpha 来完成的。

这是一个非常有趣的问题。唉,我没有给你答案,但我会好奇地看着这个话题!

关于c# - 如何避免在具有透明背景的调整大小的 PNG 中出现无用的白色边框?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6236391/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com