• C文件处理之24/32位bmp图像的旋转


    用C操作的24/32位bmp图像旋转

    引入——

      写作本帖以纪念初步解锁位图bmp格式!
      本文的目的是通过程序从原有24或32位bmp位图文件生成顺时针旋转90°的新文件。由于涉及课程作业,本文不贴代码,只记录处理要点。

      主要参考资料为BMP24位位图格式总结 - 百度文库相关论坛问题下7楼cht_1988的回答

    0.背景

      bmp是一种Windows系统下通用的图片格式,我们可以通过画图软件生成(PS甚至Windows自带的"画图"就行)。
      位图的一个重要属性——位数,其更专业的名称叫色深,一般有2,8,16,24,32等。
      先来了解一下BMP图像文件,即位图的构成。

      典型的BMP图像文件由四部分组成:

      ①位图头文件数据结构,也叫文件头。它包含BMP图像文件的类型、显示内容等信息;

      ②位图信息数据结构,信息头。它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;

      ③调色板,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)和32位BMP就不需要调色板;

      ④位图数据,这部分的内容根据BMP位图使用的位数不同而有区别。
         在24位图中直接使用RGB(每个像素依次用BGR3个字节表示),而其他的小于24位的使用调色板中颜色索引值。
         32位位图每个像素用ABGR4个字节表示,A是透明度(通道),(我处理的图片里)多数情况为零。
         这些字节的排列顺序非常重要,因为文件显示时可能是按固定的格式读取的(瞎猜的x),如果搞错,在后面转换时就有可能喜提一张加滤镜的照片(真的√)。
         此处还没说清具体的顺序,先卖个关子,待后文分析。

      此外,位图一般不进行压缩,没有"加密",可以直接处理,所以占用储存空间也较大。

    1.借别人的Demo快速看懂BMP文件结构

      学习资料:相关论坛问题下7楼cht_1988的回答(代码)。
      这堆代码要干的事呢,就是根据现有的BMP,直接原模原样生成另一个copy。
      这位大哥的注释超详尽,唯恐大家看不懂BMP haha。这份代码真的对接触bmp非常有用!But……

      计划总是没有变化快,我现有的BMP图像文件里竟有一个32位图在转换后出现了缺失一种颜色的bug,比如图片白色的部分变成了黄色。
      这个问题其实直到我下载了WinHex一探文件内部究竟后才解决。且见下文分解!

    2.利用WinHex一探文件内部究竟

      学习资料:BMP24位位图格式总结 - 百度文库
      我们现在要做的就是真实面对文件里写的16进制码,即"从计算机的视角"打开BMP格式文件,有很多软件都可以做到这一点。比如WinHex,据说Visual Studio和Vscode+插件也可以。
      WinHex也算是良心软件了,居然占用空间那么小就解决了我目前的燃眉之急。(不像VS)

    3.旋转操作

      顺时针旋转90°并不难实现,关键要理解那些字节在BMP里存储的方式和顺序。我用的方法比较笨,循环遍历+单字节写入。
      存储的顺序是从一张图片的左下角到右上角,即从左到右、自下而上。
      存储方式如下图由C到B,旋转后首先图片的长宽会改变,并且先以D-B-C-A的顺序写入。


    4.Bug1——运行32位图像程序会崩溃

      这个bug发生在我看上面那篇百度文档和下载WinHex前。原因就是32位图片的信息头比24位多了84位(不一定都是84位,要根据文件的信息头的前四个字节算)。我单独读取了这些字节并写入文件就好了,此处略过。

    5.Bug2——32位颜色缺失

      这个bug主要因为我处理的32位图片的信息区域是以ABGR的顺序储存像素信息的,跟网上资料介绍的BGRA顺序不一样。
      于是我没思考那么多,立刻改了写入顺序,这张32位图也由黄色重新被洗白啦。
      于是出现下一个bug。exm???

    6.Bug3——又来颜色缺失?

      打开的下一张32位图片由白变蓝了?!再次用WinHex打开,结果让我哭笑不得……
      这张图像素的储存顺序居然是BGRA…
      我加了一个判断,即如果第一个像素点的第一个字节为0,默认它就是A通道,是按ABGR储存的;反之,是BGRA。
      其实算是有冒险成分在里面的吧(但是这是我目前最好最简便的办法了)。
      就这样解决了。

    6.Bug4——关于补齐4倍数的字节

      读取BMP的扫描行要求每行存放4的整数倍个字节。在这里我把要补的字节数忘记更新了,赶在ddl前返工的滋味可不太好受啊
      不过问题得到解决的快乐是无可比拟的,xixi[呲牙]

    结语——

      写到这里,我脑中忽然闪过一念,在bug2那里,也许是我把某个字节漏读了、导致BGRA读成了ABGR?但是这样解释不了不同图像之间的差异啊……
      困惑ing……
      所以真心希望看到这篇文章的同学们能比我更进一步,看看这个bug到底是不是bug,以及怎么解决。博主小白非常欢迎大家的评论和帮助,万分感谢!

    用代码改变世界!就是这样,喵!
  • 相关阅读:
    Silverlight实用窍门系列:52.Silverlight中的MVVM框架极速入门(以MVVM Light Toolkit为例)
    极速理解设计模式系列:3.代理模式(Proxy Pattern)
    Silverlight实用窍门系列:44.Silverlight 4.0中进行单元测试 【附带源码实例】
    Silverlight实用窍门系列:50.InkPresenter涂鸦板的基本使用,以及将效果保存为Png图片【附带源码实例】
    由浅入深CIL系列:3.通过CIL观察.NET值类型和引用类型的内存分配
    Silverlight实用窍门系列:54.详解Silverlight中的矩阵变换MatrixTransform,实现其余各种变换【附带实例源码】
    由浅入深CIL系列:5.抛砖引玉:判断string是否为空的四种方法的CIL代码看看效率如何?
    Silverlight实用窍门系列:48.DataGrid行详细信息的绑定DataGrid.RowDetailsTemplate【附带实例源码】
    极速理解设计模式系列:4.原型模式(Prototype Pattern)
    Silverlight实用窍门系列:45.Silverlight下使用WinDbg调试应用程序和查看异常情况
  • 原文地址:https://www.cnblogs.com/Song-Meow/p/12608909.html
Copyright © 2020-2023  润新知