图片读写
stb
在matlab中利用imread和imwrite来对图片进行读写,在c++中推荐一个很好用的库–stb,这个库只需要一个头文件,就可以对多种类型的图片进行解析和保存,并且使用方便,接口数很少。在github上下载stb_image和stb_image_write这两个文件,其中stb_image用于图片的解析,stb_image_write用于图片的保存。
注意一点,在使用stb_image和stb_image_write之前,需要进行宏定义,具体请参看这个文件的文件注释。
示例
接下来用代码说明stb的使用方法。具体代码参看这里,所有头文件在Include文件夹,对应的cpp在lib文件夹中。
Image.h图片抽象类
#pragma once
#include <assert.h>
#include <cstring>
class Image
{
protected:
unsigned int m_width;
unsigned int m_height;
unsigned int m_components;
public:
Image(int w, int h, int n);
virtual ~Image() = default;
//getter and setter
unsigned int GetWidth()const { return m_width; }
unsigned int GetHeight()const { return m_height; }
unsigned int GetComponents()const { return m_components; }
unsigned int GetSize()const { return m_width*m_height*m_components; }
};
Image.cpp
#include "Image.h"
#include <iostream>
Image::Image(int w, int h, int n):
m_width(w), m_height(h), m_components(n)
{
}
UnsignedImage.h 无符号整型图片
#pragma once
#include "Image.h"
#include <vector>
class UnsignedImage : public Image
{
private:
std::vector<unsigned char> m_data;
public:
UnsignedImage(int w, int h, int n, const unsigned char* data);
~UnsignedImage()=default;
std::vector<unsigned char> GetData()const { return m_data; }
const unsigned char& At(int row, int col, int nth)const;
unsigned char&At(int row, int col, int nth);
};
UnsignedImage.cpp 注意这里的At函数,stb将图片解析为一维数组,为了更直观对图片像素进行操作,At函数提供了一个指定行列和通道的接口。
#include "UnsignedImage.h"
UnsignedImage::UnsignedImage(int w, int h, int n, const unsigned char* data):
Image(w, h, n)
{
m_data.resize(this->GetSize());
memcpy(&m_data[0], data, sizeof(unsigned char) * this->GetSize());
}
const unsigned char & UnsignedImage::At(int row, int col, int nth)const
{
assert(row <= m_height && col <= m_width && nth <= m_components);
return m_data[row*m_width*m_components + col*m_components + nth];
}
unsigned char& UnsignedImage::At(int row, int col, int nth)
{
assert(row <= m_height && col <= m_width && nth <= m_components);
return m_data[row*m_width*m_components + col*m_components + nth];
}
ImageLWManager.h 用于图片的加载(Loading)和写入(Write),stb支持多种类型图片的读写,这里只写了一个png格式的写入。
#pragma once
#include "Image.h"
#include "UnsignedImage.h"
#include "common/common.h"
#include <cstring>
class ImageLoader
{
DISALLOW_COPY_AND_ASSIGN(ImageLoader);
public:
ImageLoader() = default;
UnsignedImage LoadImage(const std::string& filePath, int req_comp=0);
};
class ImageWriter
{
DISALLOW_COPY_AND_ASSIGN(ImageWriter);
public:
ImageWriter() = default;
int WritePNGImage(const UnsignedImage& image, const std::string& outputPath)const;
};
ImageLWManager.cpp 注意在使用stb之前需要宏定义。
#include "ImageLWManager.h"
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb/stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb/stb_image_write.h"
UnsignedImage ImageLoader::LoadImage(const std::string& filePath, int req_comp /*= 0*/)
{
int x, y, n;
auto data = stbi_load(filePath.c_str(), &x, &y, &n, req_comp);
if (req_comp != 0 && n > req_comp)
n = req_comp;
if (nullptr == data)
{
std::cerr << "Can't open the file.\n";
exit(-1);
}
UnsignedImage image(x, y, n, data);
return image;
}
int ImageWriter::WritePNGImage(const UnsignedImage& image, const std::string& outputPath)const
{
return stbi_write_png(outputPath.c_str(),
image.GetWidth(),
image.GetHeight(),
image.GetComponents(),
&(image.GetData()[0]),
0);
}