【问题标题】:Can't return a Bitmap object in this function无法在此函数中返回位图对象
【发布时间】:2014-01-11 16:18:09
【问题描述】:

我正在尝试编写一个函数,它应该创建一个指定大小的新位图并用指定的颜色填充它,问题是我在尝试将位图分配给任何属性时总是遇到异常或以其他几种方式使用它,例如从字典类型中获取位图以读取位图属性。

例如这个,不工作:

Private Shadows Sub Shown() Handles MyBase.Shown

    PictureBox1.BackgroundImage =
        CreateSolidBitmap(New Size(16, 16), Color.Red)

End Sub

这一直有效,直到我尝试读取位图

    Private Shadows Sub Shown() Handles MyBase.Shown

        Dim dict As New Dictionary(Of Color, Bitmap) From
            {
                {Color.Red, CreateSolidBitmap(New Size(16, 16), Color.Red)}
            }

        ' This throws the same exception above:
        MsgBox(dict(Color.Red).Size.Width)

    End Sub

例外是这样说的:

System.ArgumentException 未处理 消息:未处理的异常 System.Drawing.dll 中出现“System.ArgumentException”类型 附加信息:无效参数。

这是函数,我缺少什么?

''' <summary>
''' Creates a bitmap filled with a solid color.
''' </summary>
''' <param name="FillColor">Color to fill the Bitmap.</param>
''' <returns>System.Drawing.Bitmap.</returns>
Private Function CreateSolidBitmap(ByVal Size As Size,
                                   ByVal FillColor As Color) As Bitmap

    ' Create a bitmap.
    Using bmp As New Bitmap(Size.Width, Size.Height)

        ' Create a graphics object.
        Using g As Graphics = Graphics.FromImage(bmp)

            ' Create a brush using the specified color.
            Using br As New SolidBrush(FillColor)

                ' Fill the graphics object with the brush.
                g.FillRectangle(br, 0, 0, bmp.Width, bmp.Height)

            End Using ' br

        End Using ' g

        Return bmp

    End Using ' bmp

End Function

位图是为了这个:

【问题讨论】:

  • 您正在处理您尝试存储的同一个位图。

标签: .net vb.net graphics bitmap gdi+


【解决方案1】:

改变

Using bmp As New Bitmap(Size.Width, Size.Height)

Dim bmp As New Bitmap(Size.Width, Size.Height)

End Using(bmp)被命中时,bmp 将被释放。

【讨论】:

  • 但是如果我使用 dim 那么我的函数将不会处理任何新的位图..增加内存。
  • 位图是一个类,因此是一个引用类型。如果您将其丢弃,以后将无法参考。
  • @ElektroStudios 什么?如果是这样,删除 sub 中的所有内容并返回 CType(Nothing, Bitmap)
  • 我不明白这部分...如果我不处理函数生成的对象,那么只需 10 次调用即可创建 5000px 的位图内存使用量(通过新的位图该函数创建并且不处理...)增加了 200 mb,那么我应该如何执行此操作?
  • @ElektroStudios 这是在字典中存储 X 个位图的结果。由于您具有创建它们的功能,因此请考虑根据需要创建它们并在使用完它们时将它们丢弃。\
【解决方案2】:

并非没有,但存在一种优化此类方案的方法。我有一个应用程序,可以预先存储多达 120 张大小未知的图像。我还必须创建/管理该图像的缩略图。与其存储巨大的位图,不如将图像保存到编码为 PNG 的流中:

Private Sub EncodeImage(ByVal bmp As Bitmap)
    ' raw bitmaps are HUGE - 1080p can be 8MB while JPG is 400K and PNG is 2MB

   ' optional: examine bmp and make a reasonable size thumbnail.
   ' e.g. store 1080p as a max of 1600x900 or whatever.
   'you can always restore the size

   ' a backing field in the class this procedure is in
    _MS = New MemoryStream

   bmp.Save(mMS, System.Drawing.Imaging.ImageFormat.Png)
End Sub

解码很简单:

_MS.Seek(0, SeekOrigin.Begin)

Return System.Drawing.Image.FromStream(mMS, True, False)

您可以通过这种方式节省大量内存,如果重复访问同一图像(如循环访问),性能会受到轻微影响。没有理由对 16x16 单色 位图 (OP) 使用类似的方法,在这种情况下我什至不会存储位图。但从评论 (5000px bitmap) 来看,我会根据这些内容来考虑。

编码也可能会影响质量(这是首选 PNG 而非 JPG 的原因)。对于一种颜色 bimtmap,您不会注意到。对于实际图像,您可能会这样做,但代价是在应用中存储的图像要少得多,或者使用磁盘临时文件会变得更慢。

HTH

【讨论】:

  • for 16x16 one-color bitmaps (OP), I wouldnt even store the bitmap in that case 是的,它们实际上只有 16px 大小,它用于在上下文菜单中显示一种最近使用的颜色作为下拉项,但如果你甚至不将位图存储在那么我想你是在谈论直接绘制矩形或者你的意思是什么其他想法?非常感谢您的宝贵时间!
  • 像往常一样,魔鬼在(实施)细节中:对于 MRU/CTM,是的,我可能会保存图像。从 OP 看来,您可能正在存储一大堆单色 bmp。绘制/填充矩形虽然具有不必跟踪和处理东西的优点,但它并不是那么慢。那里的所有 ColorPicker 控件都以这种方式绘制所有颜色。用 5000px 的评论很难说出你想要什么。干杯!
猜你喜欢
  • 2014-05-15
  • 2018-02-09
  • 1970-01-01
  • 2011-09-19
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
  • 2021-12-18
  • 2021-01-04
相关资源
最近更新 更多