【问题标题】:C# Resizing Bitmap without changing the PixelformatC# 在不更改 Pixelformat 的情况下调整位图大小
【发布时间】:2015-02-10 14:13:54
【问题描述】:

我有一个 BGR 格式和分辨率为 1920*1200 的位图,我想在不更改像素格式的情况下对其进行缩放。

private Bitmap rescale(Size size, Bitmap origin)
{
    Bitmap scaled = new Bitmap(origin, size);
    return scaled;
}

问题是,缩放后的结果是一个 RGBA 位图(所有 alpha 为 255),这不仅对我没用,而且也让我感到困扰,因为后来我在不同的图像上做 AbsDiff(来自 EMGU)和然后,alpha值总是为零.. 有没有办法在缩放时不更改像素格式或在没有 alpha 值的情况下执行 AbsDiff?因为像这样,当我稍后加载图像时,它是不可见的..

【问题讨论】:

  • 应该有一个采用 PixelFormat 参数的构造函数重载。见msdn.microsoft.com/en-us/library/3z132tat%28v=vs.110%29.aspx
  • 您可以创建具有所需像素格式和所需大小的目标,然后使用 Graphic.DrawImage 将缩放后的版本复制到目标中。
  • 我建议使用 virusrocks 在他的回答中给出的重载。它会自动完成(至少这是 MSDN 声称的)。要手动执行此操作,您将从新位图创建一个 Graphics 对象,并使用它的 DrawImage 重载之一将原始图像绘制到新图像上。
  • virusrocks 在他的回答中使用的正是我尝试过的,但没有奏效..我现在尝试使用 Graphics 对象..

标签: c# bitmap emgucv


【解决方案1】:
   Bitmap scaled = new Bitmap(origin, size);

在构造函数调用中有很多隐含的假设。你会得到:

  • 32bppPArgb 像素格式的位图。旨在帮助程序员陷入成功的陷阱,它是现代 PC 上最优化的像素格式。兼容视频适配器帧缓冲区的像素格式,无需任何转换即可blitted。它比所有其他的快倍。
  • 分辨率设置为视频适配器 DPI。这通常不太理想,尽管很难说它应该在重新缩放后使用源图像的分辨率。您可能需要修改它。
  • 透明背景。如果源位图具有透明度或具有设置为值
  • 源图像的双线性插值。这是相当适度的,您可能会喜欢 InterpolationMode.HighQualityBicubic 以获得更好的结果,尤其是当您将其缩小 50% 以上时。或 NearestNeighbor,如果您关心的是速度,或者源图像非常小并且您放大它以保持像素按原样可见。

很明显你不开心,第一个子弹就是你抱怨的根源。写出来,所有细节都可以调整:

    public static Bitmap RescaleImage(Image source, Size size) {
        // 1st bullet, pixel format
        var bmp = new Bitmap(size.Width, size.Height, source.PixelFormat);
        // 2nd bullet, resolution
        bmp.SetResolution(source.HorizontalResolution, source.VerticalResolution);
        using (var gr = Graphics.FromImage(bmp)) {
            // 3rd bullet, background
            gr.Clear(Color.Transparent);
            // 4th bullet, interpolation
            gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            gr.DrawImage(source, new Rectangle(0, 0, size.Width, size.Height));
        }
        return bmp;
    }
    -

【讨论】:

    【解决方案2】:

    我会这样做(当然有点丑陋)的方式是创建一个具有原始 Pixelformat 和新大小的新位图,并将原始位图绘制到它上面(未经测试):

    private Bitmap rescale(Size size, Bitmap origin)
    {
        Bitmap rescaled = new Bitmap(size.Width, size.Height, origin.PixelFormat);
        using(Graphics g = Graphics.FromImage(rescaled))
        {
             g.DrawImage(origin, 0, 0, size.Width, size.Height);
        }
        return rescaled;
    }
    

    【讨论】:

    • 这一点也不丑。
    • 这太棒了!刚刚解决了我遇到的一个大问题!复制、粘贴、调用,完成!
    • 只是为了恭维,如果 PixelFormat 被索引,这将失败,如在黑白图像中。
    【解决方案3】:

    这似乎是您需要的: http://www.codeproject.com/Tips/552141/Csharp-Image-resize-convert-and-save

    Bitmap(Image, Size) constructor

    public Bitmap(
        Image original,
        Size newSize
    )
    

    这是一个采用新大小的构造函数。图像会自动调整为该大小。

    【讨论】:

      猜你喜欢
      • 2013-05-04
      • 1970-01-01
      • 1970-01-01
      • 2016-05-04
      • 2011-11-28
      • 1970-01-01
      • 1970-01-01
      • 2019-05-14
      • 1970-01-01
      相关资源
      最近更新 更多