bmp文件格式分析
Tag bmp, C语言, 二进制, 文件读取, 格式, on by view 6054

bmp格式图片文件由4部分组成:文件头(BitmapFileHeader),信息头(BitmapInfoHeader),颜色表(RGBQuad),像素矩阵(RGB)[即数据区]。

文件头(BitmapFileHeader)

typedef struct _BITMAPFILEHEADER
{
	BYTE2  bfType;  //类型标识0x4d42
	BYTE4  bfSize;  //文件大小(字节)
	BYTE2  bfReserved1;  //保留1(0)
	BYTE2  bfReserved2;  //保留2(0)
	BYTE4  bfOffBits;  //数据区偏移(字节)
} BitmapFileHeader;

信息头(BitmapInfoHeader)

typedef struct _BITMAPINFOHEADER{ 
	BYTE4  biSize;  //本结构的大小,根据不同的操作系统而不同,在Windows中,此字段的值总为0x28字节=40字节
	BYTE4  biWidth;  //图片宽度(px)
	BYTE4  biHeight;  //图片高度(px)
	BYTE2  biPlanes;  //目标设备的级别(1)
	BYTE2  biBitCount;  //每个像素所需的位数,必须是1(双色),4(16色),8(256色)或24(真彩色)之一
	BYTE4  biCompression;  //是否压缩(0不压缩)
	BYTE4  biSizeImage;  //图像数据区大小
	BYTE4  biXPelsPerMeter;  //水平分辨率,像素每米
	BYTE4  biYPelsPerMeter;  //垂直分辨率,像素每米
	BYTE4  biClrUsed;  //BMP图像使用的颜色,0表示使用全部颜色,对于256色位图来说,此值为0x100=256
	BYTE4  biClrImportant;  //重要的颜色数,此值为0时所有颜色都重要,对于使用调色板的BMP图像来说,
                                //当显卡不能够显示所有颜色时,此值将辅助驱动程序显示颜色
} BitmapInfoHeader;

颜色表(RGBQuad)

typedef struct _RGBQUAD {
	BYTE1  rgbBlue;  //蓝色分量
	BYTE1  rgbGreen;  //绿色分量
	BYTE1  rgbRed;  //红色分量
	BYTE1  rgbReserved;  //保留(0),非0则为alpha通道
} RGBQuad;

像素

typedef struct _RGBPx
{
	BYTE1  R;  //红色分量
	BYTE1  G;  //绿色分量
	BYTE1  B;  //蓝色分量
} RGBPx;

image_matrix.png

当图像颜色为24位时,即为全彩色RGB模式,无颜色表,所有颜色皆为重要色,因此biBitCount=24时文件中没有RGBQuad区域;若biBitCount为其他值,则图像为索引模式,颜色表中包含图像所用到的颜色,RGBQuad区域为RGBQuad结构体数组。文件中文件头(BitmapFileHeader),信息头(BitmapInfoHeader),颜色表(RGBQuad)三个区域之后是像素矩阵区域。

像素矩阵区中对于24位全色彩文件是RGBQuad区域为RGBQuad结构体数组,对于索引模式图像会将颜色表按照先后顺序编号,例如4位颜色,16色,将会编号0~15号颜色,如此0000b(1)表示第1种颜色,0001b(2),0010b(3),0011b(4),0100b(5)……故一字节可以表示两个像素,如0xa2=10100010b即为11号和2号色。

关于像素矩阵中还有一个问题需要注意,那就是“4字节边界”。像素矩阵的存储是遵循4字节边界存储的,也就是说每一行像素的数据字节大小必须是4的倍数,可是实际上有些图片存储后并不能保证每行的字节数是4的倍数;如一幅1366*768的24位图像,这种图像一像素24位即3字节,则每行1366*3=4098字节,而4098%4=2,余2并不是4的倍数,此时应当在最后2字节后面补充2字节(0x0)。故,在读取时应当注意每行像素后面是否有空边界。

最后,读取的像素还要进行倒置才能够正确的显示,因为原像素矩阵是上下颠倒,左右颠倒的。

paint_picture_reverse_demo.png

最后附上我自己实现的零依赖的bmp解析项目,直接读取二进制bmp文件解析,并带有基础图像变换函数https://github.com/organc/image 。


变形金刚4中的中国元素
Tag 中国元素, 变形金刚, on by view 3389

考完试和同学一起去放松了一下,看了一部3D电影——《变形金刚4绝迹重生》。第一次看3D电影,感觉还不错,只是戴两层眼镜有点不舒服,哈哈。电影的故事情节一般,各种特效的确很强大,自然少不了美国大片的打斗场景,大气磅礴的恢宏场面从一开始贯穿全片,电影中的各种建筑物自然是少不了被摧残,只是这次摧毁的不仅仅是美国的建筑物,也有中国的建筑。

网上查了一下,《变形金刚4》是派拉蒙影业、中国电影频道以及加赋公司联合制作的。既然是中国人参与制作的电影,中国的戏份自然是少不了。因此,电影中的中国元素也是众多。在这之前值得一提的是,电影中的植入广告倒是挺多,不过还好植入广告并不那么让人反感,场景刚切换到中国,李冰冰就拿着一瓶怡宝矿泉水(怪不得最近买的怡宝矿泉水上面印有变形金刚4的广告),还有那个喝伊利牛奶的美国科学家,以及写着别人厂家名字的几个大烟囱。主角们来到中国后,首先就是在北京,于是便少不了鸟巢这些标志建筑,飞船在空中飞行的时候还有万里长城的背景,后来场景切换到了香港,主角们首先是在比较古老破败的街道巷子中活动,有比较土的电梯,中国功夫,以及多一个人就超重的电梯,更有麻将以及各种熟悉的中国式的普通家庭布局;噢,对啦,还有逃亡时购买路人的摩托车时候的本地方言对话。穿过狭隘的过道时遇到的几个白发老奶奶,尽管被挡道很着急,却没有做出什么不礼貌的举动。后来的场景中还有各种中国现代化的建筑,当然这些场景都成了机器人战斗的战场。

电影全片气势恢宏,较之以前的几部又多出了恐龙机器人,还有更强悍的幕后人物,变形金刚和塞伯坦星球的创造者(尽管只出现在最后的镜头),那是一个屠杀有机生物星球并将其变为塞伯坦星球然后创造出机器人的神秘人物。那些恐龙形态的变形金刚貌似就是外星人在远古时代屠杀了恐龙之后创造的变形金刚。

现在的美国大片中出现中国元素已经是屡见不鲜的事情了,从当年的《2012》中的诺亚方舟在中国建成,到《木乃伊3龙帝之墓》,以及现在的《变形金刚4》。一方面是中国电影的积极参与,另一方面也体现出了中国逐渐受到世界的重视,逐渐的矗立于世界强国之列。


利用开源和免费资源搭建CI环境
Tag CI, 测试, on by view 7436

前段时间偶然接触到了持续集成(Continuous Integration)这一概念,并对它做了进一步的了解;说是偶然接触到是有原因的,起初我在github上的某些项目里面发现了这些东西

image.png

吸引我的注意力的正是这些绿色的徽章,点入build那个徽章一看,连接到了一个叫做Travis CI的网站,里面有类似控制台输出的信息

image1.png

这个的确是控制台输出,看里面的内容知道是通过git clone将这个项目下载到某台linux服务器,然后sudo权限执行了一些shell脚本,再后来就是./configure、make、make install之类的,这整个流程就是linux用户通过代码安装某个软件的过程。当然,部分项目里面并没有make install,而是make test,这是执行单元测试啊。

经过进一步了解后,发现Travis CI就是一个专门提供在线编译以及运行单元测试等工作的一个云平台(或者直白点说就是服务器)。阅读了一下午的Travis CI英文文档后,自己尝试着利用Travis CI为自己的项目也创建一个这样的编译测试环境。

首先,Travis  CI是可以直接与Github连接,读取项目信息的。然后只要你的项目的根目录下面有一个名为.travis.yml的文件Travis CI即可识别你的项目,并且从这个文件里面读取它所要执行的步骤。当然.travis.yml这个配置文件必须遵守文档中所定义的各种约定,在这之前.travis.yml文件的内容也必须遵守.yml文件的语法格式约定(我有一次就是因为没注意到其中的语法错误导致排错很久)。

  • yml文件语法应当注意的内容

    例如:

    env:
    global:
       # The next declration is the encrypted COVERITY_SCAN_TOKEN, created
       #   via the "travis encrypt" command using the project repo's public key
       - secure: "q5Wb1ChR5r/52zmkssky4IIM2C3b/ItLjfGRuqPgAsU6pgnrJ7GvHC44A/jvba4rTElxWKXhTyWvskdwSzgCvBs0GIRXHxSYjtcD9IzIMLX7zHfczP2ekH2xGONXhZR1AWN6/YHh1QZ2SwdrlbQv9jybZ9NxWvk9v2IPhdWr5MM="
    language: c
    compiler: 
        - "gcc"
        - "clang"
    script:
        - "chmod 777 ./coverity.sh"
        - "./coverity.sh"

           

    这其中有部分语法类似于key: value,但是要注意:后面必须有一个空格符,另外,语法还有与python类似的对齐规则,没对齐或者是伪对齐(空格与Tab符对齐)都会导致语法错误。最终的结果是Travis CI报错。

  • compiler项是设置系统编译器,上例中是使用gcc和clang编译器,因此会有两次编译,一次是gcc一次clang编译,当然多个值就会有多个编译,众多的编译构成编译矩阵,可以测试某个项目在不同的环境下面的编译结果。script项是命令Travis CI执行的具体命令,上例中我将命令全部写入到一个shell文件里面去了,script这一项的内容是执行这个shell脚本。详细的配置介绍可以自己查看Travis CI官网上的文档。

利用Travis CI你可以做些什么?首先,检测代码在语法上的正确性这是最基本的,简单来说就是检测你的项目是否能够编译通过,是否能够在不同个环境下编译通过。其次,你可以利用一些单元测试对项目进行更进一步的检测,这些根据你的测试代码可以检测出一些逻辑上的错误。

其实Travis CI是可以有其他的一些功能的,比如程序发布。例如,我现在需要将编译后的可执行文件发布到项目的官方网站上供别人下载;我可以使用curl命令将可执行文件通过我事先准备好的上传接口上传到我的网站,这样一来,你每次更新代码Travis CI会自动编译完成后直接发送到你指定的网站上,然后你的程序发布可以自动的保持最新版本。

事实上类似于Travis CI的网站还比较多,比如drone.io等,当然还有一些收费的CI服务网站,这儿就不提了。最后值得一提的是虽然大部分的免费CI是Linux环境的,但是被我发现了一个Windows环境的CI,而且它有几种环境可以选择,例如Windows Server 2008,最重要的是它也是免费的而且支持许多版本的Visual Studio,也就是说C#、.NET或者是包含Windows API的这些仅能在Windows环境下编译的代码也能够编译,https://ci.appveyor.com就是它,Windows应用程序开发者的福音。