写在前面
一些libpng相关的内容
一些用到的库
安装PIL
1 2
| sudo apt-get install python3-pip pip3 install pillow -i https://mirrors.aliyun.com/pypi/simple/
|
libpng安装和使用
下载地址 https://sourceforge.net/projects/libpng/files/
解压之后
1 2 3
| ./configure make check sudo make install
|
libpng好像还需要依赖zlib
zlib 走这个下载 https://zlib.net/
然后基本也是跟libpng一样的安装方式。
就装好了,要用的话就在cmake链接里面加一下就行
1 2 3 4 5
| cmake_minimum_required(VERSION 3.1) project(uxpng) set(CMAKE_CXX_STANDARD 14) add_executable(uxpng main.cpp) target_link_libraries(uxpng png)
|
jpg2png
1 2 3 4 5 6 7 8 9 10
|
from PIL import Image import sys
if __name__ == '__main__' : pg = '{}.jpg'.format(sys.argv[1]) img = Image.open(pg) img.save('{}.png'.format(sys.argv[1]))
|
这是一个把jpg文件转换成png文件的脚本,为啥要这样呢,主要是因为这里主要是在用libpng玩东西,所以有了这么个脚本
PNG基础
https://gitee.com/dxyinme/uxpng 这里是我学习libpng相关的一些操作和实践
图像类型
1 2 3 4 5 6 7 8 9 10
| #define PNG_COLOR_MASK_PALETTE 1 #define PNG_COLOR_MASK_COLOR 2 #define PNG_COLOR_MASK_ALPHA 4
#define PNG_COLOR_TYPE_GRAY 0 #define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) #define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) #define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) #define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
|
先不考虑调色板的话,PNG一共有4种格式。抛开固定格式,整个图的存储方式大致是一个二维的矩阵,矩阵的每个元素可以被看成是一个像素, 每个像素按照自己的图像类型,以某些特定的方式排列。例如RGB类型的图像,他的排列方式就是
如果是RGB-alpha(有透明通道)的图像,他的排序方式就是
灰度图和灰度透明图只有一个(两个)通道,用来表示每个像素的灰度和透明度。
图像的读写
读取png图像
1 2 3 4 5
| fp = fopen(img_path, "rb"); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); info_ptr = png_create_info_struct(png_ptr); png_init_io(png_ptr, fp); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, nullptr);
|
首先,先获取图像的基本信息
1 2 3 4 5 6
| int channels, color_type, bit_depth, width, height; channels = png_get_channels(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr);
|
其次再获取整个图像矩阵
1
| auto row_pointers = png_get_rows(png_ptr, info_ptr);
|
这里的图像矩阵的高是height,宽是 channels * width 读取像素的时候需要获取连续channels个元素。
输出png图像
1 2 3 4 5 6 7 8
| png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, png_data->Width(), png_data->Height(), png_data->BitDepth(), png_data->ColorType(), PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr);
|
按行写入图像的某个图像行,这个是按顺序的,调用一次,下一次写的行数+1。
1
| png_write_row(png_ptr, row_ptr);
|