【问题标题】:Merge large monochromatic (BW) images合并大型单色 (BW) 图像
【发布时间】:2021-09-08 14:39:05
【问题描述】:

我需要处理单色图像。我基本上需要在高分辨率(如 30000x20000px)单色图像(400dpi 的 A2+ 绘图)中添加一个横幅(框架和格式化文本)。

默认PixelFormatFormat1bppIndexed,这使得即使是那些大的图片尺寸也相对较小。但是,使用 .NET GDI+ Graphics 对象需要 unindexed 位图。

将图像转换为最低可用未索引PixelFormat.Format16bppGrayscale

bmpResized = ImgResized.Clone(New System.Drawing.Rectangle(0, 0, ImgResized.Width, ImgResized.Height),
             System.Drawing.Imaging.PixelFormat.Format16bppGrayScale)

...ImageBitmapOutOfMemoryExeption: Not enough memory - 在 32GB 机器上)处理它变得很大。 我尝试单独创建横幅并以像素方式加入图片,但是我遇到了同样的限制 - SetPixel 需要未索引的位图。

有没有办法克服这些问题?


编辑:一个可能的解决方案是创建一个字节数组并根据 [https://social.msdn.microsoft.com/Forums/vstudio/en-US/54a096ff-46f3-45ce-8560-bf5a0618ef75/how 编辑字节-to-set-pixel-into-bitmap-with-pixel-format-of-format8bppindexed-?forum=csharpgeneral][1]。但是我不确定我如何能按字节“移动”第二张图像。

【问题讨论】:

  • 使用 ImageMagick 吗?
  • ps; 32Gb 并不真正相关 - .NET 中的对象大小有上限,与安装的内存的物理量无关
  • @CaiusJard nope :-(。我知道并使用过 ImageMagic,但是在这种情况下我无法跨出 Windows 标准库。
  • @CaiusJard 你可能是对的,我不确定适用哪些限制。
  • @Oak_3260548 GDI+ 对图像大小有限制,并且错误消息的描述性不强。 System.Windows.Media.Imaging Namespace 有更强大的类。

标签: vb.net graphics marshalling pixelformat monochrome


【解决方案1】:

最后我不得不使用按位操作来完成它。效果很好,甚至表现也很好。

' Create byte array for the main ploted TIF image
Dim bmp As New Drawing.Bitmap(Img.Width, Img.Height, Drawing.Imaging.PixelFormat.Format1bppIndexed)
bmp = Img   ' getting bitmap from the default image
Dim data As System.Drawing.Imaging.BitmapData = bmp.LockBits(New Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), Drawing.Imaging.ImageLockMode.[WriteOnly], Drawing.Imaging.PixelFormat.Format1bppIndexed)
Dim bytes As Byte() = New Byte(data.Height * data.Stride - 1) {}
System.Runtime.InteropServices.Marshal.Copy(data.Scan0, bytes, 0, bytes.Length)


' Create byte array for the banner
Dim bmpB As New Drawing.Bitmap(Img.Width, Img.Height, Drawing.Imaging.PixelFormat.Format1bppIndexed)
bmpB = Img.Clone()   ' banner had to be generated in 16bppp unindexed gray scale image to be able to use graphics
Dim dataB As System.Drawing.Imaging.BitmapData = bmpB.LockBits(New Drawing.Rectangle(0, 0, BmpB.Width, BmpB.Height), Drawing.Imaging.ImageLockMode.[WriteOnly], Drawing.Imaging.PixelFormat.Format1bppIndexed)
Dim bytesB As Byte() = New Byte(dataB.Height * dataB.Stride - 1) {}
System.Runtime.InteropServices.Marshal.Copy(dataB.Scan0, bytesB, 0, bytesB.Length)


' Join byte arrays:  Resulting bitmap = plotted TIF + banner
Dim bytesResult((bytes.Length + bytesB.Length) - 1) As Byte
bytesB.CopyTo(bytesResult, 0)
bytes.CopyTo(bytesResult, bytesB.Length)


' Revert resulting byte array back to bitmap and save resulting TIF image
BmpResized = New Bitmap(Img.Width, Img.Height * 2, Drawing.Imaging.PixelFormat.Format1bppIndexed)
Dim dataResult As System.Drawing.Imaging.BitmapData = BmpResized.LockBits(New Drawing.Rectangle(0, 0, BmpResized.Width, BmpResized.Height), Drawing.Imaging.ImageLockMode.[WriteOnly], Drawing.Imaging.PixelFormat.Format1bppIndexed)
System.Runtime.InteropServices.Marshal.Copy(bytesResult, 0, dataResult.Scan0, bytes.Length + bytesB.Length - 0)
Dim exportFileName As String = filenames1(0).Replace(".tif", "_mod.tif")
exportFileName = exportFileName.Replace(".png", "_mod.tif")
BmpResized.Save(exportFileName, Drawing.Imaging.ImageFormat.Tiff)

' Unlock locked bitmaps
bmp.UnlockBits(dataResult)
BmpResized.UnlockBits(dataResult)

' dispose anything not used later...

【讨论】:

    猜你喜欢
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-14
    • 2014-08-23
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    相关资源
    最近更新 更多