调整大小后,白色图像出现灰色边框

5
我正在谷歌上寻找一种解决方案,后来我找到了一个,我试图在我的代码中实现它,但它没有起作用。问题在于,调整大小后的白色图像会出现灰色边框。
这是我发现的解决方案的链接:
它说: 这个问题的原因是你将图像数据插值到一个新的尺寸,但在边缘处没有像素进行插值,.NET默认使用黑色像素来填充这些边缘。要解决这个问题,你需要在DrawImage调用中使用一个ImageAttributes类...

https://groups.google.com/group/microsoft.public.dotnet.framework.drawing/browse_thread/thread/d834851b49274fd9/81a4fd43694457ac?hl=en&lnk=st&q=DrawImage+resized+border#81a4fd43694457ac

代码 1:这是我的带有ImageAttributes实现的代码:

Private Shared Function ResizeImageFile(ByVal imageFile As Byte(), ByVal targetSize As Integer) As Byte()

    Using oldImage As System.Drawing.Image = System.Drawing.Image.FromStream(New MemoryStream(imageFile))

        Dim newSize As Size = CalculateDimensions(oldImage.Size, targetSize)

        Using newImage As New Bitmap(newSize.Width, newSize.Height, PixelFormat.Format32bppRgb)

            Using canvas As Graphics = Graphics.FromImage(newImage)

                Using ia As New ImageAttributes

                    ia.SetWrapMode(Drawing2D.WrapMode.TileFlipXY)
                    canvas.SmoothingMode = SmoothingMode.AntiAlias
                    canvas.InterpolationMode = InterpolationMode.HighQualityBicubic
                    canvas.PixelOffsetMode = PixelOffsetMode.HighQuality
                    canvas.DrawImage(oldImage, New Rectangle(New Point(0, 0), newSize), 0, 0, newImage.Width, newImage.Height, GraphicsUnit.Pixel, ia)

                    Dim m As New MemoryStream()

                    newImage.Save(m, ImageFormat.Png)
                    Return m.GetBuffer()

                End Using

            End Using

        End Using

    End Using

End Function

Private Shared Function CalculateDimensions(ByVal oldSize As Size, ByVal targetSize As Integer) As Size

    Dim newSize As New Size()

    If oldSize.Height > oldSize.Width Then

        newSize.Width = CInt((oldSize.Width * (CSng(targetSize) / CSng(oldSize.Height))))
        newSize.Height = targetSize

    Else

        newSize.Width = targetSize
        newSize.Height = CInt((oldSize.Height * (CSng(targetSize) / CSng(oldSize.Width))))

    End If

    Return newSize

End Function

代码2:导致白色图像出现灰色边框的代码

在调整大小后,这是图像:

enter image description here

新图像大小宽度为400px

Private Shared Function ResizeImageFile(ByVal imageFile As Byte(), ByVal targetSize As Integer) As Byte()

    Using oldImage As System.Drawing.Image = System.Drawing.Image.FromStream(New MemoryStream(imageFile))

        Dim newSize As Size = CalculateDimensions(oldImage.Size, targetSize)

        Using newImage As New Bitmap(newSize.Width, newSize.Height, PixelFormat.Format32bppRgb)

            Using canvas As Graphics = Graphics.FromImage(newImage)

                    canvas.SmoothingMode = SmoothingMode.AntiAlias
                    canvas.InterpolationMode = InterpolationMode.HighQualityBicubic
                    canvas.PixelOffsetMode = PixelOffsetMode.HighQuality
                    canvas.DrawImage(oldImage, New Rectangle(New Point(0, 0), newSize))

                    Dim m As New MemoryStream()

                    newImage.Save(m, ImageFormat.Png)
                    Return m.GetBuffer()

            End Using

        End Using

    End Using

End Function

Private Shared Function CalculateDimensions(ByVal oldSize As Size, ByVal targetSize As Integer) As Size

    Dim newSize As New Size()

    If oldSize.Height > oldSize.Width Then

        newSize.Width = CInt((oldSize.Width * (CSng(targetSize) / CSng(oldSize.Height))))
        newSize.Height = targetSize

    Else

        newSize.Width = targetSize
        newSize.Height = CInt((oldSize.Height * (CSng(targetSize) / CSng(oldSize.Width))))

    End If

    Return newSize

End Function

更新于2011年7月30日:

代码1解决了白色图片灰色边框的问题,但出现了新问题。问题出在以下代码行:

canvas.DrawImage(oldImage, New Rectangle(New Point(0, 0), newSize), 0, 0, newImage.Width, newImage.Height, GraphicsUnit.Pixel, ia)

使用此代码,输出图像具有所需的宽度和高度,并且没有灰色边框,但oldImage未经缩放。

例如:

如果我想上传、调整大小并保存原始大小为640x480px的图像,并将目标大小设置为400px,则输出的图像的宽度为400px,高度为300px,没有灰色边框,但oldImage未调整大小/缩放到400px。相反,oldImage以原始分辨率绘制。如何缩放oldImage以正确绘制?有人能指导我找到正确的解决方案或修改代码吗?

感谢大家,但我已经找到了解决所有问题的方法。

由于以下代码行,CODE 1 没有正常工作

canvas.DrawImage(oldImage, New Rectangle(New Point(0, 0), newSize), 0, 0, newImage.Width, newImage.Height, GraphicsUnit.Pixel, ia)

解决方案:

canvas.DrawImage(oldImage, New Rectangle(New Point(0, 0), newSize), 0, 0, oldImage.Width, oldImage.Height, GraphicsUnit.Pixel, ia)

这是完整的可工作代码(调整大小的图像没有灰色/黑色边框):

Private Shared Function ResizeImageFile(ByVal imageFile As Byte(), ByVal targetSize As Integer) As Byte()

    Using oldImage As System.Drawing.Image = System.Drawing.Image.FromStream(New MemoryStream(imageFile))

        Dim newSize As Size = CalculateDimensions(oldImage.Size, targetSize)

        Using newImage As New Bitmap(newSize.Width, newSize.Height, PixelFormat.Format32bppRgb)

            Using canvas As Graphics = Graphics.FromImage(newImage)

                Using ia As New ImageAttributes

                    ia.SetWrapMode(Drawing2D.WrapMode.TileFlipXY)
                    canvas.SmoothingMode = SmoothingMode.AntiAlias
                    canvas.InterpolationMode = InterpolationMode.HighQualityBicubic
                    canvas.PixelOffsetMode = PixelOffsetMode.HighQuality
                    canvas.DrawImage(oldImage, New Rectangle(New Point(0, 0), newSize), 0, 0, oldImage.Width, oldImage.Height, GraphicsUnit.Pixel, ia)

                    Dim m As New MemoryStream()

                    newImage.Save(m, ImageFormat.Png)
                    Return m.GetBuffer()

                End Using

            End Using

        End Using

    End Using

End Function

Private Shared Function CalculateDimensions(ByVal oldSize As Size, ByVal targetSize As Integer) As Size

    Dim newSize As New Size()

    If oldSize.Height > oldSize.Width Then

        newSize.Width = CInt((oldSize.Width * (CSng(targetSize) / CSng(oldSize.Height))))
        newSize.Height = targetSize

    Else

        newSize.Width = targetSize
        newSize.Height = CInt((oldSize.Height * (CSng(targetSize) / CSng(oldSize.Width))))

    End If

    Return newSize

End Function

不确定问题是什么。你遇到了一个问题并找到了解决方案。 - Denis
@Antonio,你能提供一个无法工作的示例图像以及newSize的尺寸,这样我们就可以看到你所看到的内容。我尝试了你提供的代码,但我没有发现任何问题。(虽然从技术上讲,我不会真正称之为调整图像大小,你只是在更大的画布上绘制旧图像。) - Chris Haas
请参考以下两个链接:https://dev59.com/9XI-5IYBdhLWcg3wYXH8 和 https://dev59.com/FXI-5IYBdhLWcg3wbHu-#1861575。 - Mark Ransom
这是一篇关于图像大小调整陷阱的好文章,如果你遇到更多问题可以参考它:http://nathanaeljones.com/163/20-image-resizing-pitfalls/。另外,你看过http://imageresizing.net吗?如果你正在进行ASP.NET项目,那么它是必不可少的。 - Lilith River
1
如果您有可用的代码,我认为您应该将其发布为答案并标记为正确,这样该问题就不会再显示为未回答,并且如果其他人从Google或其他地方找到此页面,则更容易将其用作参考。 - SeriousSamP
1个回答

1
这是我所拥有的一个类之外的函数,你需要替换一些类属性(ThumbNailSize.Width,ThumbNailSize.Height):
public void ResizeImage(HttpPostedFile fil, string sPhysicalPath, 
                              string sOrgFileName,string sThumbNailFileName,
                              ImageFormat oFormat, int rez)
{

    try
    {

        System.Drawing.Image oImg = System.Drawing.Image.FromStream(fil.InputStream);

        decimal pixtosubstract = 0;
        decimal percentage;

        //default
        Size ThumbNailSizeToUse = new Size();
        if (ThumbNailSize.Width < oImg.Size.Width || ThumbNailSize.Height < oImg.Size.Height)
        {
            if (oImg.Size.Width > oImg.Size.Height)
            {
                percentage = (((decimal)oImg.Size.Width - (decimal)ThumbNailSize.Width) / (decimal)oImg.Size.Width);
                pixtosubstract = percentage * oImg.Size.Height;
                ThumbNailSizeToUse.Width = ThumbNailSize.Width;
                ThumbNailSizeToUse.Height = oImg.Size.Height - (int)pixtosubstract;
            }
            else
            {
                percentage = (((decimal)oImg.Size.Height - (decimal)ThumbNailSize.Height) / (decimal)oImg.Size.Height);
                pixtosubstract = percentage * (decimal)oImg.Size.Width;
                ThumbNailSizeToUse.Height = ThumbNailSize.Height;
                ThumbNailSizeToUse.Width = oImg.Size.Width - (int)pixtosubstract;
            }

        }
        else
        {
            ThumbNailSizeToUse.Width = oImg.Size.Width;
            ThumbNailSizeToUse.Height = oImg.Size.Height;
        }

        Bitmap bmp = new Bitmap(ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);
        bmp.SetResolution(rez, rez);
        System.Drawing.Image oThumbNail = bmp;

        bmp = null;

        Graphics oGraphic = Graphics.FromImage(oThumbNail);

        oGraphic.CompositingQuality = CompositingQuality.HighQuality;

        oGraphic.SmoothingMode = SmoothingMode.HighQuality;

        oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;

        Rectangle oRectangle = new Rectangle(0, 0, ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);

        oGraphic.DrawImage(oImg, oRectangle);

        oThumbNail.Save(sPhysicalPath  + sThumbNailFileName, oFormat);

        oImg.Dispose();

    }
    catch (Exception ex)
    {
        Response.Write(ex.Message);
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接