【问题标题】:Graphics on indexed image索引图像上的图形
【发布时间】:2013-06-26 06:47:42
【问题描述】:

我收到错误:

"不能从具有索引的图像创建图形对象 像素格式。”

在功能中:

public static void AdjustImage(ImageAttributes imageAttributes, Image image)
{
        Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);

        Graphics g = Graphics.FromImage(image);       
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, imageAttributes);
        g.Dispose();
}

我想问你,我该如何解决?

【问题讨论】:

    标签: c# image graphics indexed-image


    【解决方案1】:

    参考this,可以通过创建一个具有相同尺寸和正确 PixelFormat 的空白位图并在该位图上绘制来解决。

    // The original bitmap with the wrong pixel format. 
    // You can check the pixel format with originalBmp.PixelFormat
    Bitmap originalBmp = new (Bitmap)Image.FromFile("YourFileName.gif");
    
    // Create a blank bitmap with the same dimensions
    Bitmap tempBitmap = new Bitmap(originalBmp.Width, originalBmp.Height);
    
    // From this bitmap, the graphics can be obtained, because it has the right PixelFormat
    using(Graphics g = Graphics.FromImage(tempBitmap))
    {
        // Draw the original bitmap onto the graphics of the new bitmap
        g.DrawImage(originalBmp, 0, 0);
        // Use g to do whatever you like
        g.DrawLine(...);
    }
    
    // Use tempBitmap as you would have used originalBmp
    return tempBitmap;
    

    【讨论】:

    • 但它不会写在原始图像上。它将创建一个空白图像并在其上书写。所以最后数据没有写在原始图像上。
    • 这段代码后面需要更多的代码来在图形对象上绘制原始图像,比如Dim rect As New System.Drawing.Rectangle(0, 0, bm.width, bm.height) : g.DrawImage(bm, rect, 0, 0, bm.width, bm.Height, GraphicsUnit.Pixel)
    • 唯一有效的原因是它使新图像具有高色彩。这实际上不允许您在 8 位图像上绘图...
    • 当位图源是像灰度格式这样的索引格式时,我建议避免使用图形对象。最好用克隆创建新的位图。 Bitmap Clone(Rectangle rect, PixelFormat format)
    • 不幸的是,正如所指出的,这不允许在具有原始色彩空间的原始图像上使用图形。因此,如果您有一张单色 (1bpp) 高分辨率图像(如 70k x 40k 像素),那么内存大小将超过屋顶......
    【解决方案2】:

    最简单的方法是像这样创建一个新图像:

    Bitmap EditableImg = new Bitmap(IndexedImg);
    

    它创建一个与原始图像完全一样的新图像及其所有内容。

    【讨论】:

    • 什么是IndexedImg
    • 如果索引像素图像的dpi高于默认值,则嵌入在可编辑图像上角的可编辑图像要小得多
    • “及其所有内容”...除了原始调色板。这将创建一个 32bppARGB 图像。它实际上不允许编辑 8 位图像。
    • 降低tiff文件的DPI,不改变DPI可以吗?
    • @sandeepsharma 只需添加一行将新图像对象的 dpi 设置为旧图像对象的 dpi。 im2.SetResolution(im1.HorizontalResolution, im1.VerticalResolution);
    【解决方案3】:

    总的来说,如果您想使用索引图像并实际保留它们的颜色深度和调色板,这将始终意味着为它们编写明确的检查和特殊代码。 Graphics 根本无法使用它们,因为它操纵颜色,索引图像的实际像素不包含颜色,只是索引。

    对于这么多年后仍然看到这一点的任何人......将图像绘制到现有(8 位)索引图像上的有效方法是:

    • 检查您要粘贴的图像的所有像素,对于每种颜色,find the closest match on the target image's colour palette,并将其索引保存到字节数组中。
    • 使用 LockBits 打开索引图像的后备字节数组,然后通过使用高度和图像步幅遍历相关索引,将匹配的字节粘贴到所需位置。

    这不是一件容易的事,但肯定是有可能的。如果粘贴的图像也被索引,并且包含超过 256 个像素,您可以通过在调色板上而不是在实际图像数据上进行颜色匹配来加快处理速度,然后从另一个索引图像中获取支持字节,并重新映射他们使用创建的映射。

    请注意,所有这些仅适用于八位。如果您的图像是 4 位或 1 位,处理它的最简单方法是先将其转换为 8 位,这样您就可以将其处理为每个像素一个字节,然后再将其转换回来。

    有关这方面的更多信息,请参阅How can I work with 1-bit and 4-bit images?

    【讨论】:

      【解决方案4】:

      虽然接受的答案有效,但它会从索引位图创建一个新的 32bpp ARGB 图像。

      要直接操作索引位图,您可以使用this 库(警告:无耻的自我宣传)。它的GetReadWriteBitmapData 扩展允许为索引像素格式创建可写托管访问器。

      然后您可以使用与Graphics.DrawImage 类似的DrawInto 方法之一。当然,当目标位图被索引时,绘图操作必须使用目标调色板颜色量化像素,但有一种重载可以使用抖动来保留更多图像细节。

      使用示例(查看以上链接中的更多示例):

      using (IReadWriteBitmapData indexedTarget = myIndexedBitmap.GetReadWriteBitmapData())
      using (IReadableBitmapData source = someTrueColorBitmap.GetReadableBitmapData())
      {
          // or DrawIntoAsync if you want to use async-await
          source.DrawInto(indexedTarget, targetRect, OrderedDitherer.Bayer8x8);
      }
      

      图片示例:

      下面的所有图片都是使用PixelFormat.Format8bppIndexed 格式和默认调色板创建的,并且一个 256x256 的图标和一个 alpha 渐变彩虹被绘制在彼此的顶部。请注意,尽可能多地使用可用的调色板进行混合。

      Image Description
      No dithering
      Ordered Bayer8x8 dithering
      Floyd-Steinberg error diffusion dithering

      免责声明:当然,与Graphics相比,该库也有一些限制,例如没有绘制形状的方法。但在最坏的情况下,您仍然可以使用已接受的答案,如果需要生成索引结果,则最后调用 ConvertPixelFormat 方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-17
        • 1970-01-01
        • 2012-12-07
        • 1970-01-01
        • 2015-11-25
        • 1970-01-01
        • 2012-12-02
        • 2011-03-19
        相关资源
        最近更新 更多