繁体   English   中英

使用 gdiplus 打印 png24 图像时 GDI memory 泄漏

[英]GDI memory leak when printing png24 images with gdiplus

在 Windows 10 下的某些打印机上打印时,我遇到了一个非常奇怪的遗留“gdi 对象”泄漏。

即使在 Microsoft 虚拟打印机(例如本示例中使用的“Microsoft XPS Document Writer”)上打印时也会发生这种情况。 当涉及 png 24 图像时,似乎发生了 GDI 泄漏。

我创建了一个测试项目来轻松重现该行为:

Imports System.Drawing
Imports System.Drawing.Printing
    
Module Module1
    
    ' The PNG 24 source image
    Private Const SOURCE_PNG24_FILE As String = [Path to any png 24 image]
    
    ' The number of rendering repetitions
    Private Const REPETITIONS As Integer = 100
    
    Sub Main()
    
        MsgBox("Open the task manager and check GDI objects count for this application, should be around 15.", MsgBoxStyle.Information)
    
        ' Get Microsoft XPS Document Writer printer settings
        Dim prnSettings As New PrinterSettings() With {.PrinterName = "Microsoft XPS Document Writer"}
    
        ' Ensure printer is valid
        If prnSettings.IsValid = False Then
            MsgBox("Can't find Microsoft XPS Document Writer.", MsgBoxStyle.Exclamation)
            Exit Sub
        End If
    
        ' Init document settings
        m_prtDoc = New PrintDocument With {.DocumentName = "PNG24 print test",
                                           .PrinterSettings = prnSettings}
    
        ' Start printing
        m_prtDoc.Print()
    
        MsgBox("Check GDI objects count, probably thru the roof.", MsgBoxStyle.Information)
    
    End Sub
    
    ' Document settings
    Private WithEvents m_prtDoc As PrintDocument = Nothing
    
    ' Page count
    Private m_iPageCount As Integer = 0
    
    
    Private Sub PrintPage(sender As Object, e As PrintPageEventArgs) Handles m_prtDoc.PrintPage
    
        Try
    
            ' Load png 24 image
            Using imgSourcePng24 As Image = Image.FromFile(SOURCE_PNG24_FILE)
    
                ' Create in memory image of the same size
                Using imgMemory As New Bitmap(imgSourcePng24.Width, imgSourcePng24.Height)
    
                    ' Get the in-memory graphics
                    Using gphMemory As Graphics = Graphics.FromImage(imgMemory)
    
                        ' Draw source image
                        gphMemory.DrawImage(imgSourcePng24, New Rectangle(Point.Empty, imgSourcePng24.Size), New Rectangle(Point.Empty, imgSourcePng24.Size), GraphicsUnit.Pixel)
    
                    End Using
    
                    ' Draw in-memory image -> Comment this line and no GDI object spike
                    e.Graphics.DrawImage(imgMemory, New Rectangle(Point.Empty, imgMemory.Size), New Rectangle(Point.Empty, imgMemory.Size), GraphicsUnit.Pixel)
    
                End Using
    
            End Using
    
            ' Increase page count
            m_iPageCount += 1
    
            ' Print up to REPETITIONS pages
            e.HasMorePages = (m_iPageCount < REPETITIONS)
    
        Catch ex As Exception
            ' Error, Stop printing
            MsgBox(ex.Message, MsgBoxStyle.Critical)
        End Try
    
    End Sub
    
End Module

memory 泄漏发生在 Windows 10 19042.867 上,并且不会发生在 Windows 7 上,使用相同的虚拟打印机。 png 8 或其他图像格式(例如 jpg)不会发生这种情况。

我有另一个导致相同奇怪行为的 win32 项目,似乎问题可能与 GdipCreateBitmapFromScan0 有关,当创建一个新的空 bitmap 时,它在幕后被调用。

如果您将 png24 直接渲染到打印机的图形上,一切都很好,但如果需要中间步骤(例如裁剪)并创建空白图像,则会发生泄漏。

任何帮助表示赞赏。 谢谢你。

编辑

在运行了更多测试之后,事实证明它与将 32bppARGB 图像渲染到打印机 Graphics 相关,无论其来源如何。 当您使用 argb 内容渲染内存中创建的 bitmap 时,也会发生这种情况:

Private Sub PrintPage(sender As Object, e As PrintPageEventArgs) Handles m_prtDoc.PrintPage

    Try

        ' Create in memory image 
        Using imgMemory As New Bitmap(600, 400)

            ' Fill with alpha color
            Using gphMemory As Graphics = Graphics.FromImage(imgMemory)
                gphMemory.Clear(Color.FromArgb(128, 255, 0, 0)) ' Red at 0.5 alpha
            End Using

            ' Draw in-memory image
            e.Graphics.DrawImageUnscaled(imgMemory, e.PageBounds.Location)

        End Using

        ' Increase page counter
        m_iPageCount += 1

        ' The number of rendering repetitions
        Const REPETITIONS As Integer = 20

        ' Print up to REPETITIONS pages
        e.HasMorePages = (m_iPageCount < REPETITIONS)

    Catch ex As Exception
        ' Error, Stop printing
        MsgBox(ex.Message, MsgBoxStyle.Critical)
    End Try

End Sub

对于遇到此问题的任何人,似乎问题已通过更新KB5001649解决

确保您和/或您的客户使 Windows 保持最新,此问题不会影响您的项目。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM