【问题标题】:Image occupies same number of bytes irrespective of color depth [closed]无论颜色深度如何,图像都占用相同数量的字节[关闭]
【发布时间】:2017-04-16 08:43:23
【问题描述】:

下图显示了当我们转换大小为 1x2 的 24 位彩色图像时会发生什么。

.

下图显示了当我们转换大小为 1x2 的 32 位彩色图像时会发生什么。

我想,24 位图像将占用 6 个字节。但是,两者都占用 8 个字节。

因此,我的 C# 代码失败了。因为,它假定一个像素需要(ColorDepth/8)*Width*Height 字节数。

    public static int[,] ToInteger(Bitmap bitmap)
    {
        BitmapLocker locker = new BitmapLocker(bitmap);

        locker.Lock();

        byte[] data = locker.ImageData;
        int Width = locker.Width;
        int Height = locker.Height;
        int noOfBytesPerPixel = locker.BytesPerPixel;
        int[,] integerImage = new int[Width, Height];
        int byteCounter = 0;

        for (int i = 0; i < Width; i++)
        {
            for (int j = 0; j < Height; j++)
            {
                int integer = BitConverter.ToInt32(data, byteCounter);

                integerImage[i, j] = integer;

                byteCounter += noOfBytesPerPixel;
            }
        }

        locker.Unlock();

        return integerImage;
    }

那么,到底发生了什么?

【问题讨论】:

标签: c# image-processing bitmap


【解决方案1】:

为什么图片占用相同的字节数?

我们无法确定,因为您没有展示您是如何获取它们的(也许默认情况下它们会提升到 32bpp,这是处理速度最快的,例如在WriteableBitmapEx 中?)

计算每像素字节数的正确公式:

bytesPerPixel = (bitsPerPixel + 7) / 8

这里有一个例子,它将从 8 到 32 bpp 转换为 int

private static void DoWork(Bitmap bitmap)
{
    var width = bitmap.Width;
    var height = bitmap.Height;
    var rectangle = new Rectangle(0, 0, width, height);
    var data = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);

    var bitsPerPixel = GetBitsPerPixel(bitmap.PixelFormat);
    var bytesPerPixel = (bitsPerPixel + 7) / 8;
    var stride = data.Stride;
    var length = stride * data.Height;
    var pixels = new byte[length];
    Marshal.Copy(data.Scan0, pixels, 0, length);

    for (var y = 0; y < height; y++)
    for (var x = 0; x < width; x++)
    {
        var offset = y * stride + x * bytesPerPixel;
        var value = 0;
        for (var i = 0; i < bytesPerPixel; i++)
            value |= pixels[offset + i] << i;
    }
    bitmap.UnlockBits(data);
}

private static int GetBitsPerPixel(PixelFormat format)
{
    switch (format)
    {
        case PixelFormat.Format8bppIndexed:
            return 1;
        case PixelFormat.Format16bppRgb555:
            return 2;
        case PixelFormat.Format24bppRgb:
            return 24;
        case PixelFormat.Format32bppRgb:
            return 32;
        default: // TODO
            throw new NotSupportedException();
    }
}

(但不确定是否有用)

注意:我已经“模拟”了什么是必要的,因为我没有像你那样使用 BitmapLocker 类。

【讨论】:

  • 单色和 4 位图像呢?
  • 你能说的更精确一点吗?
  • 此源代码无法处理 1 位单色图像和 4 位/16 色图像。
  • i.imgur.com/F0uxRKk.png 这是一张单色图片。
  • i.imgur.com/TeTupcN.png 这是一张 4 位(16 色)图像。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-21
  • 2016-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多