Linux下libpng库的运用​

PNG是一种采用无损压缩算法的位图格式,支持索引、灰度、RGB三种颜色方案以及Alpha通道等特性。 其设计目的是试图替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。PNG使用从LZ77派生的无损数据压缩算法,一般应用于JAVA程序、网页或S60程序中,原因是它压缩比高,生成文件体积小。PNG文件的扩展名为.png。这篇文章介绍libpng库来解码渲染png图片格式。

libpng库下载

下载地址: http://www.linuxfromscratch.org/blfs/view/svn/general/libpng.html

Linux下libpng库的运用​插图

1.1 在PC机上配置编译​

[wbyq@wbyq pc_work]$ tar xvf /mnt/hgfs/linux-share-dir/libpng-1.6.37.tar.xz

[wbyq@wbyq libpng-1.6.37]$ ./configure --enable-shared --enable-static --prefix=$PWD/_install

[wbyq@wbyq libpng-1.6.37]$ make && make install

[wbyq@wbyq libpng-1.6.37]$ tree _install/

_install/

├── bin

│ ├── libpng16-config

│ ├── libpng-config -> libpng16-config

│ ├── pngfix

│ └── png-fix-itxt

├── include

│ ├── libpng16

│ │ ├── pngconf.h

│ │ ├── png.h

│ │ └── pnglibconf.h

│ ├── pngconf.h -> libpng16/pngconf.h

│ ├── png.h -> libpng16/png.h

│ └── pnglibconf.h -> libpng16/pnglibconf.h

├── lib

│ ├── libpng16.a

│ ├── libpng16.la

│ ├── libpng16.so -> libpng16.so.16.37.0

│ ├── libpng16.so.16 -> libpng16.so.16.37.0

│ ├── libpng16.so.16.37.0

│ ├── libpng.a -> libpng16.a

│ ├── libpng.la -> libpng16.la

│ ├── libpng.so -> libpng16.so

│ └── pkgconfig

│ ├── libpng16.pc

│ └── libpng.pc -> libpng16.pc

└── share

man

man3

├── libpng.3

└── libpngpf.3

man5

png.5

9 directories, 23 files

1.2 交叉编译给ARM开发板使用

[wbyq@wbyq libpng-1.6.37]$ ./configure --prefix=$PWD/arm_install CC=arm-linux-gcc --host=arm-linux --enable-shared --enable-static

1.3 png应用案例(处理了透明背景)

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define LCD_DEVICE "/dev/fb0"

int lcd_fd;
struct fb_var_screeninfo vinfo;//可变参数
struct fb_fix_screeninfo finfo; //固定参数
unsigned char *lcd_mem=NULL; //LCD首地址
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;

int image_height;
int image_width;
unsigned char *image_buffer[4];
int video_fd;
void LCD_DrawPoint(u32 x,u32 y,u32 c);
u32 LCD_ReadPoint(u32 x,u32 y);


/*显示PNG文件*/
int display_png(u32 x,u32 y,char* filename)
{
FILE *fp;
png_structp png_ptr;
png_infop info_ptr;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type, number_passes;
u32 i,j;
u32 x0;
u32 rgb24,b_rgb24;
u8 r,g,b,a;
u8 b_r,b_g,b_b;
u8 R,G,B;

if((fp = fopen(filename,"rb")) == NULL)
{
printf("%s 文件打开失败.n",filename);
return -1;
}
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL, NULL, NULL);
/*需要分配/初始化内存以获取图像信息*/
info_ptr = png_create_info_struct(png_ptr);
/*设置PNG图片的文件指针*/
png_init_io(png_ptr,fp);
png_read_info(png_ptr,info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,&interlace_type, NULL, NULL);
printf("图片宽度:[%4d]n",width);
printf("图片高度:[%4d]n",height);
printf("颜色位数:[%4d]n",bit_depth);

/*读取图像的最简单方法:*/
png_bytep row_pointers[height];

/*清除指针数组*/
for(i = 0; i height; i++)
{
row_pointers[i] = NULL;
row_pointers[i] = malloc(width * 4); /* RGBA */
memset(row_pointers[i], 0, width * 4);
}
/*读取整个PNG图像*/
png_read_image(png_ptr,row_pointers);

for(i = 0; i height; i++)
{
x0=x;
for(j = 0; j width * 4; j += 4)
{
/*得到图片颜色*/
r=row_pointers[i][j + 0];
g=row_pointers[i][j + 1];
b=row_pointers[i][j + 2];
a=row_pointers[i][j + 3];

/*读取当前屏幕点的背景颜色*/
b_rgb24=LCD_ReadPoint(x0,y);
b_r=b_rgb24>>16&0xFF;
b_g=b_rgb24>>8&0xFF;
b_b=b_rgb24>>0&0xFF;

/*合成屏幕背景颜色*/
R = (unsigned char)(r * (a / 255.0) + (b_r * (255 - a)) / 255.0);
G = (unsigned char)(g * (a / 255.0) + (b_g * (255 - a)) / 255.0);
B = (unsigned char)(b * (a / 255.0) + (b_b * (255 - a)) / 255.0);

/*显示数据*/
rgb24=R16|G8|B;
LCD_DrawPoint(x0,y,rgb24);

/*坐标自增*/
x0++;
}
y++;
}
/* 读取文件的其余部分,并在info_ptr中获取其他块-必需*/
png_read_end(png_ptr, info_ptr);
/*读取后清理,并释放已分配的所有内存-必需*/
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
/* 统一释放内存 */
for(i = 0; i height; i++)
{
free(row_pointers[i]);
}
/*关闭文件*/
fclose(fp);
return 0;
}


/*
函数功能: 封装画点函数
函数参数: u32 x,u32 y,u16 c
*/
void LCD_DrawPoint(u32 x,u32 y,u32 c)
{
u32 *lcd_p=(u32*)(lcd_mem+vinfo.xres*vinfo.bits_per_pixel/8*y+x*vinfo.bits_per_pixel/8);
*lcd_p=c;
}


/*
函数功能: 封装读点函数
函数参数: u32 x,u32 y,u16 c
*/
u32 LCD_ReadPoint(u32 x,u32 y)
{
u32 *lcd_p=(u32*)(lcd_mem+vinfo.xres*vinfo.bits_per_pixel/8*y+x*vinfo.bits_per_pixel/8);
return *lcd_p;
}

int main(int argc,char **argv)
{
int err;
if(argc!=2)
{
printf("./app n");
return 0;
}

/*1. 打开设备文件*/
lcd_fd=open(LCD_DEVICE,O_RDWR);
if(lcd_fd0)
{
printf("%s 设备文件打开失败.n",LCD_DEVICE);
return 0;
}
/*2. 获取可变参数*/
ioctl(lcd_fd,FBIOGET_VSCREENINFO,&vinfo);
printf("x=%d,y=%d,pixel=%dn",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel);

/*3. 获取固定参数*/
ioctl(lcd_fd,FBIOGET_FSCREENINFO,&finfo);
printf("smem_len=%dn",finfo.smem_len);
printf("line_length=%dn",finfo.line_length);

/*4. 映射LCD地址*/
lcd_mem=mmap(NULL,finfo.smem_len,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);
if(lcd_mem==NULL)
{
printf("映射LCD地址失败.n");
return -1;
}
//memset(lcd_mem,0xFFFFFF,finfo.smem_len);

/*5. 显示PN图片*/
display_png(0,0,argv[1]);

close(lcd_fd);
return 0;
}

1.4 png应用案例(未处理透明背景)

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define LCD_DEVICE "/dev/fb0"

int lcd_fd;
struct fb_var_screeninfo vinfo;//可变参数
struct fb_fix_screeninfo finfo; //固定参数
unsigned char *lcd_mem=NULL; //LCD首地址
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;

int image_height;
int image_width;
unsigned char *image_buffer[4];
int video_fd;
void LCD_DrawPoint(u32 x,u32 y,u32 c);


/*显示PNG文件*/
int display_png(u32 x,u32 y,char* filename)
{
FILE *fp;
png_structp png_ptr;
png_infop info_ptr;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type, number_passes;
u32 i,j;
u32 x0;
u32 rgb24;
u8 r,g,b;

if((fp = fopen(filename,"rb")) == NULL)
{
printf("%s 文件打开失败.n",filename);
return -1;
}
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL, NULL, NULL);
/*需要分配/初始化内存以获取图像信息*/
info_ptr = png_create_info_struct(png_ptr);
/*设置PNG图片的文件指针*/
png_init_io(png_ptr,fp);
png_read_info(png_ptr,info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,&interlace_type, NULL, NULL);
printf("图片宽度:[%4d]n",width);
printf("图片高度:[%4d]n",height);
printf("颜色位数:[%4d]n",bit_depth);

/*读取图像的最简单方法:*/
png_bytep row_pointers[height];

/*清除指针数组*/
for(i = 0; i height; i++)
{
row_pointers[i] = NULL;
row_pointers[i] = malloc(width * 4); /* RGBA */
memset(row_pointers[i], 0, width * 4);
}
/*读取整个PNG图像*/
png_read_image(png_ptr,row_pointers);

for(i = 0; i height; i++)
{
x0=x;
for(j = 0; j width * 4; j += 4)
{
r=row_pointers[i][j + 0];
g=row_pointers[i][j + 1];
b=row_pointers[i][j + 2];
/*显示数据*/
rgb24=r16|g8|b;
LCD_DrawPoint(x0++,y,rgb24);
}
y++;
}
/* 读取文件的其余部分,并在info_ptr中获取其他块-必需*/
png_read_end(png_ptr, info_ptr);
/*读取后清理,并释放已分配的所有内存-必需*/
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
/* 统一释放内存 */
for(i = 0; i height; i++)
{
free(row_pointers[i]);
}
/*关闭文件*/
fclose(fp);
return 0;
}


/*
函数功能: 封装画点函数
函数参数: u32 x,u32 y,u16 c
*/
void LCD_DrawPoint(u32 x,u32 y,u32 c)
{
u32 *lcd_p=(u32*)(lcd_mem+vinfo.xres*vinfo.bits_per_pixel/8*y+x*vinfo.bits_per_pixel/8);
*lcd_p=c;
}


/*
函数功能: 封装读点函数
函数参数: u32 x,u32 y,u16 c
*/
u32 LCD_ReadPoint(u32 x,u32 y)
{
u32 *lcd_p=(u32*)(lcd_mem+vinfo.xres*vinfo.bits_per_pixel/8*y+x*vinfo.bits_per_pixel/8);
return *lcd_p;
}

int main(int argc,char **argv)
{
int err;
if(argc!=2)
{
printf("./app n");
return 0;
}

/*1. 打开设备文件*/
lcd_fd=open(LCD_DEVICE,O_RDWR);
if(lcd_fd0)
{
printf("%s 设备文件打开失败.n",LCD_DEVICE);
return 0;
}
/*2. 获取可变参数*/
ioctl(lcd_fd,FBIOGET_VSCREENINFO,&vinfo);
printf("x=%d,y=%d,pixel=%dn",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel);

/*3. 获取固定参数*/
ioctl(lcd_fd,FBIOGET_FSCREENINFO,&finfo);
printf("smem_len=%dn",finfo.smem_len);
printf("line_length=%dn",finfo.line_length);

/*4. 映射LCD地址*/
lcd_mem=mmap(NULL,finfo.smem_len,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);
if(lcd_mem==NULL)
{
printf("映射LCD地址失败.n");
return -1;
}
memset(lcd_mem,0xFFFFFF,finfo.smem_len);

/*5. 显示PN图片*/
display_png(0,0,argv[1]);

close(lcd_fd);
return 0;
}

下面是开发板上显示的PNG图片:

Linux下libpng库的运用​插图1

Linux下libpng库的运用​插图2

Linux下libpng库的运用​插图3

Linux下libpng库的运用​插图4

Linux下libpng库的运用​插图5

Linux下libpng库的运用​插图6

Linux下libpng库的运用​插图7

Linux下libpng库的运用​插图8

文章来源于互联网:Linux下libpng库的运用​

THE END
分享
二维码