目录
stb_image 是一个简单易用的图像解码库。这里我们采用图形库stb_image.h来读取图片。
思路:
(1)从计算机通过stb_image库函数读入一张图片,并将信息封装在Image类中。
(2)将读入的图片绘制在画布上。 Canvas::drawImage(int _x,int _y, Image _image);
(一)读取图片
首先我们想象一下这个流程,将一张图片读入,需要对图片的信息进行采集(长度,宽度,色彩信息)采集过后就要进行存储与应用。不妨我们设置一个Image类,专门用于对待绘制图片的信息管理。
(1)成员变量:长度,宽度,色彩信息。并设置函数进行进行获取信息:这里只是读操作无法进行存储。
(2)构造函数与析构函数: 颜色信息初始化时就要有存储。
(3)创建图片内存:不仅要读还要写!这里是写操作。首先创建一个RGBA类型的像素数组m_data,再把读入的信息拷贝到m_data中。
(4)工具函数:static Image* readFromFile(const char* _fileName);这个工具函数。
将图片正过来;加载图片;构造一张图片;释放内存,返回指向图片的指针。
图片路径:建议工程文件夹下在新建一个res文件夹专供资源导入使用,例:"res/x.png"
//Image.cpp中实现
Image* Image::readFromFile(const char* _fileName)
{
int _picType=0 ;
int _width= 0;
int _height=0 ;
stbi_set_flip_vertically_on_load(true);
byte* bits = stbi_load(_fileName, &_width, &_height, &_picType, STBI_rgb_alpha);
//通过名字读取图片
Image* _image = new Image(_width, _height, bits);//构造一个Image
stbi_image_free(bits);
return _image;
}
//Image.h中实现
class Image
{
private:
int m_width;
int m_height;
RGBA* m_data;
public:
int GetWidth()const
{
return m_width;
}
int GetHeight()const
{
return m_height;
}
RGBA GetColor(int x, int y)
{
if (x > m_width - 1 || y > m_height - 1 || y < 0 || x < 0)
return RGBA(0, 0, 0, 0);
return m_data[y * m_width + x];
}
Image(int _width=0, int _height=0, byte* _data= nullptr)//设置缺省值
{
m_width = _width;
m_height = _height;
if (_data)
{
m_data = new RGBA[m_width * m_height];//创建内存
memcpy(m_data, _data, sizeof(RGBA) * m_height * m_width);//目标,源头,大小
}
} //封装信息
~Image() {
if (m_data)
{
delete[]m_data;
}
}
//工具函数
static Image* readFromFile(const char* _fileName);
};
检验图片是否导入:通过打断的方式:
(二)绘制图片
而对一张图片进行绘制,我们是要将读取的信息重新画在画布上。在画布上绘制图片我们可以新建一个绘制图片的方法。如我们之前画三角形,画点,线,都是采用在画布中定义了一个方法,这些方法就如同我们画画使用的笔刷一样,想画什么类就新建一个什么笔刷。
(1)获取绘制待绘制图片的信息,长度,宽度,颜色
(2) 选取画布上绘制图片的其实像素点。
//Canvas.cpp里实现
void Canvas::drawImage(int _x, int _y, Image* _image)//这可以看成是个图片的笔刷方法
{
for (int u = 0; u < _image->GetWidth(); u ++)//获取待绘制图片总的宽度
{
for (int v = 0; v < _image->GetHeight(); v++) {
RGBA _color = _image->GetColor(u, v); //获取待绘制图片的颜色信息
drawPoint(_x + u, _y + v,_color); //将颜色信息绘制到画布上
}
}
}
但这不是我们预期的结果。
计算机存储以bgra方式,但是在图片加载函数中设置的读取方式是rgba,我们需要把b和r
byte* bits = stbi_load(_fileName, &_width, &_height, &_picType, STBI_rgb_alpha);
//RGBA读取方式
//但是计算机以RGBA方式存储
for (int i = 0; i < _width * _height * 4; i += 4)
{ 栅格数*字节
byte tmp = bits[i];
bits[i] = bits[i + 2];
bits[i + 2] = tmp;
}
TIP1:Debug:
1.类的交叉引用会导致,头文件的重复和包含。比如出现类成员未声明标识,在*缺少;等等的错误。2:提示以下原则:类.cpp文件包含.h文件。与别的类交叉引用分清先后调用关系,按先后顺序写头文件。3.另外出现bug,也要试着在编译器角度去理解,这是解决问题效率最高办法为何没声明标识?可能跳过了,或者是声明顺序问题。
(三)stb_image.h库下载与使用
stb_image.h库github下载地址:
stb_image.h:https://.com/nothings/stb/blob/master/stb_image.h