C# 位图截图大小

C# Bitmap screenshot size

我正在尝试了解大小(以字节为单位,而不是以宽度 x 高度为单位)的计算方式。我制作了一个检查应用程序,每秒以 24bbp 状态截取当前桌面的屏幕截图,然后将其写入 MemoryStream 并使用 ImageConverter 写入 byte[],然后比较大小。每张截图的尺寸都不一样,但它不应该是 Width x Height x 3 之类的吗?这是测试代码:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;

class Check
{
    System.Timers.Timer t;
    ImageConverter converter;
    MemoryStream ms;
    byte[] arr;
    public Check()
    {
        converter = new ImageConverter();
        t = new System.Timers.Timer();
        t.Interval = 1000;
        t.Elapsed += T_Tick;
        t.Start();
    }

    private void T_Tick(object sender, EventArgs e)
    {
        var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
                               Screen.PrimaryScreen.Bounds.Height,
                               PixelFormat.Format24bppRgb);
        var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
        gfxScreenshot.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size);

        ms = new MemoryStream();
        bmpScreenshot.Save(ms, ImageFormat.Jpeg);
        arr = (byte[])converter.ConvertTo(bmpScreenshot, typeof(byte[]));
        Console.WriteLine($"MS: {ms.Length}  --- byte[]: {arr.Length}");

    }
}

class Program
{
    static void Main()
    {
        new Check();
        Console.ReadLine();
    }
}

这是输出

MS: 76638  --- byte[]: 94893
MS: 90487  --- byte[]: 107863
MS: 92424  --- byte[]: 109281
MS: 93692  --- byte[]: 110295
MS: 95222  --- byte[]: 111055
MS: 96586  --- byte[]: 112314
MS: 104584  --- byte[]: 117970
MS: 108438  --- byte[]: 120089
...and so on

因此尺寸会随着每一帧的变化而最终开始减小,但这不应该是静态的,或者有没有办法实现图像的静态尺寸?

UDP:将格式更改为 bmp,这是另一个输出:

MS: 3148854  --- byte[]: 104699
MS: 3148854  --- byte[]: 116002
MS: 3148854  --- byte[]: 121262
MS: 3148854  --- byte[]: 125048

因此 MemoryStream 现在是静态的,但 ImageConverter 结果仍在变化。

这是一个有趣的谜题。

它由三个问题组成:

  • 为什么流的数字会发生变化?
  • 为什么字节数组的数字会发生变化?
  • 为什么流和数组的数字不同?

任何压缩结果都将取决于内容;即使是轻微的变化,例如移动时钟指针或 VS 输出窗格中的附加行也会有所不同..

让我们添加另一个结果,这次是 Png 并且屏幕内容不变:

MS: 618997  --- byte[]: 618997
MS: 618997  --- byte[]: 618997
MS: 618997  --- byte[]: 618997
MS: 618997  --- byte[]: 618997

现在我们可以得出结论:

  • 只要我们不确保屏幕内容不会改变或我们使用非压缩格式(如 bmp),流编号就会不同。我们必须隐藏输出窗格,用二手手禁用任何时钟等。

  • 只要屏幕内容改变数组编号就不同

  • 当我们存储为png时,流和数组编号相同。

从这里我们可以得出结论,ImageConverterPng格式存储压缩为字节数组的图像;这很好,因为它可以节省内存。不过,MSDN 没有记录它。 (他们可能不想保证这一点..)