使用EasyBMP进行BMP图片至图像数组的读取、修改与保存

本文需要达成的目的,是完成将本地的bmp图片读取到程序内的rgb图像数组,以及将rgb图像数组保存为bmp图片。这一操作虽然可以用opencv完成,但是有时需要更加轻量的库,EasyBMP提供了读写BMP图片的接口,在本文的程序中,通过调用其完成了将图像文件读入到rgb图像数组以及反向写入的过程。

目录

0 - 前期准备

1 - 代码


0 - 前期准备

下载EasyBMP库,其可以通过官方网站下载(不推荐)以及github上进行下载(推荐)

官方网站地址:http://easybmp.sourceforge.net/

Github地址:https://github.com/aburgh/EasyBMP

使用EasyBMP比较简单,只需要包含其头文件即可,其他操作可以参考EasyBMP的官方手册(http://easybmp.sourceforge.net/documentation.html

在使用前我们还需要对EasyBMP的库进行下修改。

在 EasyBMP.cpp 文件中,包含memory头文件

#include <memory>

不知为何原先的代码中没有添加,不添加此头文件则会导致无法使用 unique_ptr 智能指针,相关的issues地址(https://github.com/aburgh/EasyBMP/issues/1

1 - 代码

#include "./EasyBMP/EasyBMP.h"
#include "iostream"
#include <memory>
#include "time.h"

using namespace std;

void WritePix2PicArray(unsigned char* buffer,BMP &bmp,int pixCol,int pixRow,RGBApixel pixData)
{
    buffer[pixCol*3 + pixRow*bmp.TellWidth()*3] = pixData.Red;
    buffer[pixCol*3 + pixRow*bmp.TellWidth()*3 + 1] = pixData.Green;
    buffer[pixCol*3 + pixRow*bmp.TellWidth()*3 + 2] = pixData.Blue;
}

RGBApixel GetPixFromPicArray(unsigned char* buffer,BMP &bmp,int pixCol,int pixRow)
{
    RGBApixel _pixData;
    _pixData.Red = buffer[pixCol*3 + pixRow*bmp.TellWidth()*3];
    _pixData.Green = buffer[pixCol*3 + pixRow*bmp.TellWidth()*3 + 1];
    _pixData.Blue = buffer[pixCol*3 + pixRow*bmp.TellWidth()*3 + 2];

    return _pixData;
}

int main()
{
    clock_t _clkStart;
    BMP _InputBmp;
    _InputBmp.ReadFromFile("test.bmp");

    /*  show the inform of inputbmp */
    cout<<"BitDepth "<<_InputBmp.TellBitDepth()<<endl
        <<"NumberOfColor "<<_InputBmp.TellNumberOfColors()<<endl
        <<"Width "<<_InputBmp.TellWidth()<<endl
        <<"Height "<<_InputBmp.TellHeight()<<endl;

    /* create the picBuffer */
    int _bufferSize = _InputBmp.TellWidth() * _InputBmp.TellHeight() * 3;
    cout<<"bufferSize "<<_bufferSize<<endl;
    unsigned char* _picBuffer = new unsigned char[_bufferSize];

    /*  write bmp to picBuffer  */
    cout<<"WritePix2PicArray";
    _clkStart = clock();
    
    for(int j = 0 ; j < _InputBmp.TellHeight() ; j++)
    {
        for(int i = 0 ; i < _InputBmp.TellWidth() ; i++)
        {
            WritePix2PicArray(_picBuffer,_InputBmp,i,j,_InputBmp(i,j));
        }
    }
    cout<<" used "<<clock() - _clkStart<<" ms"<<endl;

    /*  do some changes on the picBuffer */
    cout<<"Change some pix data";
    _clkStart = clock();

    for(int j = 100 ; j < 500 ; j++)
    {
        for(int i = 10 ; i < 500 ; i++)
        {
            RGBApixel _pixData;
            _pixData.Red = 0;
            _pixData.Green = 0;
            _pixData.Blue = 255;
            WritePix2PicArray(_picBuffer,_InputBmp,i,j,_pixData);
        }
    }
    cout<<" used "<<clock() - _clkStart<<" ms"<<endl;

    RGBApixel _pix = GetPixFromPicArray(_picBuffer,_InputBmp,15,150);
    cout<<(int)_pix.Red<<" "<<(int)_pix.Green<<" "<<(int)_pix.Blue<<endl;

    /*  write picBuffer back to the bmp */
    cout<<"WritePicArrayToBMP";
    _clkStart = clock();
    
    for(int j = 0 ; j < _InputBmp.TellHeight() ; j++)
    {
        for(int i = 0 ; i < _InputBmp.TellWidth() ; i++)
        {
            _InputBmp(i,j) = GetPixFromPicArray(_picBuffer,_InputBmp,i,j);
        }
    }
    cout<<" used "<<clock() - _clkStart<<" ms"<<endl;

    _InputBmp.WriteToFile("test-out.bmp");

    delete[] _picBuffer;
    return 0;
}

使用下面的语句进行编译。program.cpp为上述源代码,.\EasyBMP 文件夹中存放了下载的EasyBMP代码文件。

 g++ -std=c++11 .\program.cpp .\EasyBMP\EasyBMP.cpp

由于使用了c++11标准里的智能指针,所以这里需要使用命令告诉编译器使用c++11标准进行编译。

这里代码主要完成的有三个功能:

  • 将图片文件读入到程序内BMP类型对象中,并通过循环转换为rgb数组
  • 在rgb数组中画一个矩形
  • 将rgb数组写回BMP对象,写出到文件

其实这里用循环转换到rgb数组有点蠢。尽管EasyBMP的代码是开源的,但是又不太好去改它的程序。

原始测试图片

修改后写出的图片

发布了38 篇原创文章 · 获赞 23 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u013662665/article/details/102643423