add 小白课程/以openKylin看图软件为例,浅谈图片编解码库—FreeImage.md.

Signed-off-by: 魏云博 <1655476416@qq.com>
This commit is contained in:
魏云博 2023-03-03 09:11:41 +00:00 committed by Gitee
parent fe017c4f6b
commit ead243d063
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
1 changed files with 97 additions and 0 deletions

View File

@ -0,0 +1,97 @@
# 【小白课程】以openKylin看图软件为例浅谈图片编解码库—FreeImage【小白课程】以openKylin看图软件为例浅谈图片编解码库—FreeImage
看图软件是openKylin操作系统上一款开源的图像查看软件支持对图片进行基本操作,如缩放、翻转、详情查看、复制、打印、重命名等同时还可以对图片进行裁剪、存储、标注和ocr文字识别
![图片](https://www.openkylin.top/upload/202302/1675302019720987.png)
图1 看图软件界面
作为图像查看软件查看图片是其基本功能也是最重要的功能。在看图软件V1.2.0版本中新增了10种图片格式exrpsdjfijifjngwbmpxbmxpmjp2j2k的查看和保存这些格式在技术上都是通过FreeImage库实现的。下面将为大家着重介绍看图软件中所使用的图片编解码库—FreeImage。
## 1.看图软件图片编解码库介绍
openKylin系统中的看图软件目前共支持30种图片格式分别为bmpjpegjpgjpepnmpgmppmpbmsrrasdibpngapnggifwebptgasvgicotifftifexrpsdjfijifjngwbmpxbmxpmjp2j2k。为支持上述图片格式看图软件使用以下库进行图片编解码opencv库FreeImage库apng库gif库等。其中一半格式的图片使用的是大家比较熟悉的opencv库编解码个别格式的图片如svg等有自己的相关库。除此之外都是使用的FreeImage库进行图片的读写。在使用过程中我们发现对上层应用来说FreeImage库快速便捷易于使用。
## 2.FreeImage库介绍
FreeImage库是一款开源的免费的和跨平台的图片编解码库。支持对20多种流行图形格式的处理如BMP 、JPEG 、GIF 、PNG 、TIFF等。使用FreeImage库时要安装libfreeimage-dev和libfreeimageplus-dev。同时FreeImage库提供了很多获取位图信息的接口具有快速、灵活、简单易用的特点。FreeImage库中的所有函数都是以FreeImage_开头如图像文件的读写函数分别为FreeImage_Load 和FreeImage_Save 并且和opencv之间相互转换也很简单感兴趣的小伙伴可前往FreeImage官网查看更多详情。
## 3.使用FreeImage库加载图片
看图软件在加载或操作一张图片的整个过程都是以cv::mat矩阵来存储图片的。打开一张图片时看图软件使用FreeImage库加载图片的完整流程如下所示
1. 获取图片真实格式;
2. 判断图片是否支持FreeImage读入
3. FreeImage加载图片获得FIBITMAP
4. 将FIBITMAP转换为cv::mat。
5. 从内存中删除libfreeimage载入的图片防止内存泄漏。
### 3.1 获取图片真实格式
在操作图片时,图片后缀可能是.xbm,.sr等但这并不代表图片是xbm或sr格式此时需要先通过库函数来获取图片的真实格式。// 用库获取文件格式path是图片的路径。     QByteArray temp_path;     temp_path.append(path.toUtf8());     FREE_IMAGE_FORMAT format = FreeImage_GetFileType(temp_path.data());FreeImage_GetFileType由文件头拿到文件类型。参数图片路径。这个函数的返回值是FREE_IMAGE_FORMAT。可以从下图看到返回值也可能是FIF_UNKNOWMN。
![图片](https://www.openkylin.top/upload/202302/1675302047853305.png)
图2 图片类型
如果从库函数中解析出来的文件格式为FIF_UNKNOWMN我们会从文件数据的角度通过判断文件头再次解析图片格式提升拿到正确文件格式的成功率。
QFile file(path);if (!file.open(QIODevice::ReadOnly)) {      return FIF_UNKNOWN;}const QByteArray data = file.read(64);/* Check bmp file */if (data.startsWith("BM")) {    s return FIF_BMP;}//path为图片路径
### 3.2 判断是否支持读入
在拿到文件类型后加载图片之前我们还需要做一个工作判断该格式是否可以被FreeImage库读取。其中FreeImage_FIFSupportsReading用来判断是否支持该位图类型的读操作。
### 3.3 加载图片
假设我们已经拿到图片的正确格式且该格式可以被FreeImage库读取。则调用库函数FreeImage_Load 加载位图返回值为FIBITMAP。FIBITMAP数据结构保存着位图信息和像素数据是FreeImage的核心。
### 3.4 将FIBITMAP转换成mat
在看图软件中读写图片的整个流程的数据都是以cv::mat矩阵进行传递的。之所以使用cv::mat是为了之后能够对看图软件现有的功能进行扩展尤其是opencv提供的AI方向。
![图片](https://www.openkylin.top/upload/202302/1675302060527556.png)
图3 看图软件结构
因此在拿到FreeImage返回的FIBITMAP后我们需要将它转换为cv::mat。FIBITMAP转换成cv::mat时首先要看构造一个图片的mat矩阵都需要什么参数。
Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);//行数rows列数cols类型type指向用户数据的指针data每行占据的字节数。
所以接下来我们的任务就是从FIBITMAP拿到需要的所有参数。
1. int rows, int cols
对于行数和列数FreeImage有函数可以直接调用得到行列。
FIBITMAP *dib;int width = FreeImage_GetWidth(dib);int height = FreeImage_GetHeight(dib)
2. inttype对于type需要稍微做一下处理。FreeImage库提供了查看图片深度和数据类型的方法。
int bpp = FreeImage_GetBPP(src);//图片的深度FREE_IMAGE_TYPE fit = FreeImage_GetImageType(src);//返回位图的数据类型
拿到FreeImage的类型的枚举值后一一对应转为cv::mat的数据类型即可。
![图片](https://www.openkylin.top/upload/202302/1675302073529292.png)
图4 数据类型
3. void* data指向用户数据的指针data。
库中同样有可以直接调用的函数。FreeImage_GetBits(FIBITMAP *dib):返回一个指向位图的数据位的指针
4. size_t stepstep 每行占据的字节数FreeImage_GetPitch(FIBITMAP *dib)返回位深度或线宽度又叫做扫描宽度。是以字节为单位返回对齐到下一个32位字节边界的位图宽度。
FIBITMAP *dib;int step = FreeImage_GetPitch(dib)
### 3.5内存释放
FIBITMAP *dib;FreeImage_Unload(dib);//从内存中删除载入图片,防止内存泄漏
除了FreeImage库外目前还有许多优秀的图片编解码库openKylin看图软件后续会适配更多的图片库来支持更多格式并利用opencv的特性来扩展一些特色功能。各位小伙伴敬请期待吧
![图片](https://www.openkylin.top/upload/202302/1675302088630447.png)
openKylin开放麒麟社区旨在以“共创”为核心在开源、自愿、平等、协作的基础上通过开源、开放的方式与企业构建合作伙伴生态体系共同打造桌面操作系统顶级社区推动Linux开源技术及其软硬件生态繁荣发展。社区首批理事成员单位包括麒麟软件、普华基础软件、中科方德、麒麟信安、凝思软件、一铭软件、中兴新支点、元心科技、中国电科32所、技德系统、北京麟卓、先进操作系统创新中心等13家产业同仁和行业机构。
来源openKylin
审核openKylin