Simple-Format: BMP文件格式简记

这篇博文对BMP图像数据的基本数据结构做了简单的文字记录,方便供后期自己工作项目中进行查找,也希望能够帮助到其他阅读本文的读者。

图像文件的背后

不管是开发工作还是生活中,我们都会应用到图像文件。比如手机中的照片、UI开发过程当中的贴图素材等等。不知道各位小伙伴们是不是会好奇图像到底是怎样在Windows中显示的。博主在读书的时候就很好奇两件事:

  1.  WIndows是怎么知道我的图像尺寸的?我同一个手机拍的照片像素尺寸一样可文件大小不一样啊?
  2. Windows怎么知道我的图像格式的?是BMP、PNG还是JPEG?如果我改了文件后缀名,为什么图片查看器还是能显示呢?

本文将以BMP格式的图像文件为例,对Windows图像查看器是如何解析和查看图像的进行记录和介绍。

准备一张BMP图像

测试图片
测试图片

查看属性

我们通过windows的文件浏览器查看图像的详细信息,可以看到BMP文件有256x128个像素,色深是24位。

图像详细信息

修改文件拓展名再打开

为了确定属性格式到底是怎么确认的,我们尝试修改BMP文件的后缀名成为PNG,然后再上传到属性查看工具网站,发现通过工具解析出来的信息依旧是BMP。

那么此时问题就很明显了,图像的格式是根据图像的内容来识别的。由此就有了另一个问题,我给这个图像后面追加一些内容会怎么样呢?

在图像文件末尾追加一段数据

通过C#的代码对测试图片追加字符串信息,看图像尺寸是否会有变化

class Program
    {
        static readonly string assetsName = "sample_256_126.bmp";
        static readonly string copyName = "sample_256_126_append.bmp";
        static void Main(string[] args)
        {
            Console.WriteLine("Append Hello World to bmp data!");
            try
            {
                if (File.Exists(copyName))
                {
                    File.Delete(copyName);
                }
                File.Copy(assetsName, copyName);
                StreamWriter streamWriter = File.AppendText(copyName);
                for (int i = 0; i < 1000; ++i)
                    streamWriter.WriteLine("Hello World!");
                streamWriter.Close();
            } catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
                Console.WriteLine(e.Message);
            }
        }
    }
追加数据后的图像属性

追加数据后,我们发现图片的文件大小变大了,但是像素尺寸并没有任何改变。 

上述两个实验得出结论,BMP的图像信息是以一定格式存在图像文件当中,接下来我们就探秘以下BMP文件是如何存储的。

BMP图像的数据结构

BMP文件基础的数据结构如下图所示,由BMP文件头,BMP信息头和具体的像素信息所组成。本节将结合代码对数据格式进行进一步的介绍数据格式。

BMP文件数据结构框图

 BMP 文件头

 定义如下BMP文件头结构体:

    [StructLayout(LayoutKind.Sequential, Pack =1)]
    public struct BMPHeader
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
        public byte[] ID;   // BMP Identification code "BM"
        public uint FileSize;   // the size of bmp file
        public ushort AppSpec1; // reserved commonly zero
        public ushort AppSpec2; // reserved commonly zero
        public uint PixelOffset;    // offset of pixel data

        public override string ToString()
        {
            return string.Format("Identification: {0}\n" +
                "File Size: {1}\n" +
                "App Spec Reserved1: {2}\n" +
                "App Spec Reserved2: {3}\n" +
                "Pixel Offset: {4}\n",
                Encoding.UTF8.GetString(ID),
                FileSize,
                AppSpec1,
                AppSpec2,
                PixelOffset
               );
        }
    }

通过代码读取我们的测试图片信息输出如下,可以看到文件大小为96K与预想的一致

Hello Read BMP Header!
Identification: BM
File Size: 98358
App Spec Reserved1: 0
App Spec Reserved2: 0
Pixel Offset: 54

新增图像信息数据的结构体如下,并通过控制台进行读取

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct BMPInfoHeader
    {
        public uint Size;   // Size of the info header
        public int Width; // width of bitmap in pixels
        public int Height;    // height of bitmap in pixels
        public ushort Planes;   // No. of planes for the target device, always 1
        public ushort BitCount; // No. of bits per pixels
        public uint Compression;
        public uint SizeImage;    // size of the image data
        public int PixelsPerMeterInX; // ppm in x
        public int PixelsPerMeterInY; // ppm in y
        public uint ColorsUsed;   // No. color indexes in the color table. use 0 for max number
        public uint ColorsImportant;  // No. of colors used for displaying the bitmap

        public override string ToString()
        {
            return string.Format("Header Size: {0}\nPixel Width: {1}\nPixel Height: {2}\n" +
                "Planes: {3}\nBitCount: {4}\nCompression: {5}\n" +
                "Size Image: {6}\nPixelsPerMeterInX: {7}\nPixelsPerMeterInX: {8}\n" +
                "ColorsUsed: {8}\nColorsImportant: {9}",
                Size,
                Width,
                Height,
                Planes,
                BitCount,
                Compression,
                SizeImage,
                PixelsPerMeterInX,
                PixelsPerMeterInY,
                ColorsUsed,
                ColorsImportant
                );
        }
    }

输出结果如下:

Hello Read BMP Header!
Identification: BM
File Size: 98358
App Spec Reserved1: 0
App Spec Reserved2: 0
Pixel Offset: 54

Header Size: 40
Pixel Width: 256
Pixel Height: 128
Planes: 1
BitCount: 24
Compression: 0
Size Image: 98304
PixelsPerMeterInX: 0
PixelsPerMeterInX: 0
ColorsUsed: 0
ColorsImportant: 0

与我们预期的结果一致,像素高度,像素宽度均与图片查看器得到的结果一致

实验代码请见github

参考

  1. BMP file format--Wikipedia
  2. 图像属性查看工具
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值