.Net 中的图形错误图像插值

发布于 2024-12-08 09:38:00 字数 1786 浏览 0 评论 0原文

我有一个简单的测试。当它解决时,我的问题也解决了。 当处理小图像时,图形插值的效果很差。

请检查您是否知道如何解决以下代码中的结果图像忽略要绘制的图像的后半部分的问题。 使用 JPG 中的 loadimage 或任何您想要的东西在图像上绘制一些内容。

    Dim GrayImage as system.drawing.Bitmap(640,480)    
    Dim bmTmp As New System.Drawing.Bitmap(GrayImage.Width, 1)
    Using gr As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmTmp)
         gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None
         gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear
         gr.DrawImage(GrayImage, New System.Drawing.Rectangle(0, 0, bmTmp.Width, bmTmp.Height), New System.Drawing.Rectangle(0, 0, GrayImage.Width - 0, GrayImage.Height - 0), System.Drawing.GraphicsUnit.Pixel)
     End Using

     GrayImage = New System.Drawing.Bitmap(GrayImage.Width, GrayImage.Height, GrayImage.PixelFormat)
     Using gr As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(GrayImage)
         gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None
         gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor
         gr.DrawImage(bmTmp, New System.Drawing.Rectangle(0, 0, GrayImage.Width, GrayImage.Height ), New System.Drawing.Rectangle(0, 0, bmTmp.Width - 0, bmTmp.Height - 0), System.Drawing.GraphicsUnit.Pixel)
     End Using

源代码已拉伸以便您查看 在此处下载原始源:http://www.goldengel.ch/temp/Source01 %20one%20Pixel.jpg(一张像素高度图像)

* 下载* 在此处下载完整的 VS2010 VB.Net 演示项目:

VS2010 缩放项目及其描述 - Timo Böhme< /a>

I have an simple test. When it is solved, my problem is solved too.
When working with small images, the graphics interpolation does bad work.

Please check out if you know how to fix the problem that the result image in the following code does ignore second half of image to draw.
Draw something on the image by using loadimage from JPG or whatever you want.

    Dim GrayImage as system.drawing.Bitmap(640,480)    
    Dim bmTmp As New System.Drawing.Bitmap(GrayImage.Width, 1)
    Using gr As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmTmp)
         gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None
         gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear
         gr.DrawImage(GrayImage, New System.Drawing.Rectangle(0, 0, bmTmp.Width, bmTmp.Height), New System.Drawing.Rectangle(0, 0, GrayImage.Width - 0, GrayImage.Height - 0), System.Drawing.GraphicsUnit.Pixel)
     End Using

     GrayImage = New System.Drawing.Bitmap(GrayImage.Width, GrayImage.Height, GrayImage.PixelFormat)
     Using gr As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(GrayImage)
         gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None
         gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor
         gr.DrawImage(bmTmp, New System.Drawing.Rectangle(0, 0, GrayImage.Width, GrayImage.Height ), New System.Drawing.Rectangle(0, 0, bmTmp.Width - 0, bmTmp.Height - 0), System.Drawing.GraphicsUnit.Pixel)
     End Using

Source stretched to let you view it
Download original Source here: http://www.goldengel.ch/temp/Source01%20one%20Pixel.jpg (one Pixel height image)

Destination image without fully drawing in half
The second half vertical is not drawn by using the DrawImage methode. I want to have the image as result as you see on first picture. Stretched image with source on whole content.

* DOWNLOAD*
Download here full working VS2010 VB.Net demo project:

VS2010 Scaling Project with description - Timo Böhme

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

九公里浅绿 2024-12-15 09:38:00

请尝试将: 添加

gr.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality

到您的最后一个条款中。我猜 GDI 魔法:)

希望这会有所帮助!

Please try to add:

gr.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality

to your last clause. GDI magic I guess :)

Hope this helps!

桃酥萝莉 2024-12-15 09:38:00

我有一个类似的问题,我通过调整原始图像的大小解决了这个问题。我想这是一个预期的行为,而不是一个错误(通常的 MS 解释,但对于这种情况,它可能是正确的:))。某些插值算法需要多个像素线(适用于两个轴)才能正常工作。如果没有第二行,它们可能会插入空行,从而导致上述问题。您可以将图像宽度/高度更改为最小 2 个像素,或者对单线图像使用正确的插值方法。

I had a similar problem which I had solved by resizing the original image. I guess this is an expected behaviour, not a bug (usual MS explanation but for this case it might be right :)). Some interpolation algorithms reqiure more than one pixel line (applies to both axes) to work correctly. If there is no second line, they may interpolate to an empty line which causes that problem above. You may change you image width/height to 2 pixels minimum or use proper interpolation methods for single line images.

月竹挽风 2024-12-15 09:38:00

正如@EmirAkaydin 在他的回答中所说,你的问题在于插值。我怀疑他关于它只有一个像素高(与微软的调整大小算法相冲突)的答案是正确的。

我为您提供了一个两步解决方案。除非您想编写自己的调整大小代码(我不想)来完全按照您的需要调整大小,否则您仍然可以使用 Graphics.DrawImage 函数至少调整宽度< /em> 你的图像,但只有宽度。然后,您可以直接操作像素数据并复制每个第一个有效行,以获得图像的整个高度。

您可以将您的 DoDemo 代码替换为以下代码(我不使用 VB,所以我不确定编码风格;但是它确实有效):

    Call CreateSampleImage()

    'scale the image to only one single row
    Dim bm As New Bitmap(450, 1)
    Using gr As Graphics = Graphics.FromImage(bm)
        Dim RDst As New Rectangle(0, 0, bm.Width, bm.Height)
        Dim RSrc As New Rectangle(0, 0, Me.PictureBox1.Image.Width, Me.PictureBox1.Image.Height)

        gr.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
        gr.SmoothingMode = Drawing2D.SmoothingMode.None
        gr.DrawImage(Me.PictureBox1.Image, RDst, RSrc, GraphicsUnit.Pixel)
    End Using
    Me.PictureBox2.Image = bm

    'stretch now the single row image back to original width
    Dim bm2 As New Bitmap(Me.PictureBox1.Image.Width, Me.PictureBox1.Image.Height)
    Using gr As Graphics = Graphics.FromImage(bm2)
        Dim RDst As New Rectangle(0, 0, bm2.Width, 1)
        Dim RSrc As New Rectangle(0, 0, Me.PictureBox2.Image.Width, Me.PictureBox2.Image.Height)

        gr.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
        gr.SmoothingMode = Drawing2D.SmoothingMode.None
        gr.DrawImage(Me.PictureBox2.Image, RDst, RSrc, GraphicsUnit.Pixel)
    End Using

    ' use our own custom height stretch code
    Dim rrc As New Rectangle(0, 0, bm2.Width, bm2.Height)
    Dim bmd As BitmapData

    bmd = bm2.LockBits(rrc, ImageLockMode.ReadWrite, bm2.PixelFormat)

    ' stride is the width of the image in pixels
    Dim ba(bmd.Stride - 1) As Byte
    Marshal.Copy(bmd.Scan0, ba, 0, bmd.Stride)

    ' copy pixel data to each line
    For y = 1 To bmd.Height - 1
        Marshal.Copy(ba, 0, bmd.Scan0 + (y * bmd.Stride), ba.Length)
    Next

    bm2.UnlockBits(bmd)

    Me.PictureBox3.Image = bm2

编辑:

有趣的是,代码@ FredrikJohansson 发布的帖子也将起作用:

gr.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality

就在您绘制图像之前。我将留下这段代码并在这里回答,以防有人想看到它,但看起来他以更简单的方式回答了你的问题:)

As @EmirAkaydin said in his answer, your problem lies with the interpolation. I suspect his answer about it only being one pixel high, conflicting with Microsoft's resize algorithm, is correct.

I have a two step solution for you. Unless you want to write your own resize code (I didn't want to) that resizes exactly as you want, you could still use the Graphics.DrawImage function to at least resize the width of your image, but only the width. Then you can manipulate the pixel data directly and copy each that first valid line, for the entire height of the image.

You can replace your DoDemo code with the following (I don't use VB, so I'm not sure about the coding style; it does work, however):

    Call CreateSampleImage()

    'scale the image to only one single row
    Dim bm As New Bitmap(450, 1)
    Using gr As Graphics = Graphics.FromImage(bm)
        Dim RDst As New Rectangle(0, 0, bm.Width, bm.Height)
        Dim RSrc As New Rectangle(0, 0, Me.PictureBox1.Image.Width, Me.PictureBox1.Image.Height)

        gr.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
        gr.SmoothingMode = Drawing2D.SmoothingMode.None
        gr.DrawImage(Me.PictureBox1.Image, RDst, RSrc, GraphicsUnit.Pixel)
    End Using
    Me.PictureBox2.Image = bm

    'stretch now the single row image back to original width
    Dim bm2 As New Bitmap(Me.PictureBox1.Image.Width, Me.PictureBox1.Image.Height)
    Using gr As Graphics = Graphics.FromImage(bm2)
        Dim RDst As New Rectangle(0, 0, bm2.Width, 1)
        Dim RSrc As New Rectangle(0, 0, Me.PictureBox2.Image.Width, Me.PictureBox2.Image.Height)

        gr.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
        gr.SmoothingMode = Drawing2D.SmoothingMode.None
        gr.DrawImage(Me.PictureBox2.Image, RDst, RSrc, GraphicsUnit.Pixel)
    End Using

    ' use our own custom height stretch code
    Dim rrc As New Rectangle(0, 0, bm2.Width, bm2.Height)
    Dim bmd As BitmapData

    bmd = bm2.LockBits(rrc, ImageLockMode.ReadWrite, bm2.PixelFormat)

    ' stride is the width of the image in pixels
    Dim ba(bmd.Stride - 1) As Byte
    Marshal.Copy(bmd.Scan0, ba, 0, bmd.Stride)

    ' copy pixel data to each line
    For y = 1 To bmd.Height - 1
        Marshal.Copy(ba, 0, bmd.Scan0 + (y * bmd.Stride), ba.Length)
    Next

    bm2.UnlockBits(bmd)

    Me.PictureBox3.Image = bm2

EDIT:

Interestingly enough, the code @FredrikJohansson posted will work as well:

gr.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality

right before you draw the image. I'm going to leave this code and answer here, in case anyone ever wants to see it, but it looks like he answered your question in an easier way :)

起风了 2024-12-15 09:38:00

您尝试过最近邻插值吗?

Have you tried NearestNeighbor interpolation?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文