进入http://sourceforge.net/projects/libpng/files/下载一个libpng稳定版本源码包
libpng-1.2.56.tar.gz 下载地址点击这里!
tar -xzvf libpng-1.2.56.tar.gz
d libpng-1.2.56 /* 可以使用.configure --help来查看帮助信息 */
./configure --prefix=$PWD/tmp --host=arm-linux
make && make install
如果提示错误那么就需要安装zlib库文件,以前安装过现在就不安装了。
这是tmp目录下就生成bin include lib share四个目录,这里我们只用到库文件和头文件,把库文件拷贝到开发板根文件系统,把库和头文件拷贝到交叉编译环境路径下。
我交叉编译环境如下:
/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include /* 头文件路径 */
/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib /* 库文件路径 */
到现在我们就安装好了Libpng库文件,接下来我们用一个示例文件来演示。
mypng.c文件如下:
#include<stdio.h>
#include<libpng12/png.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <string.h>
#include <stdlib.h>
#define ERROR -1
#define PNG_BYTES_TO_CHECK 4
#define FB_DEVICE_NAME "/dev/fb0"
//#define DBG_PRINTF printf
#define DBG_PRINTF(...)
#define HAVE_ALPHA 1
#define NO_ALPHA 0
static int g_lcd_fd;
FILE *g_png_fd;
static struct fb_var_screeninfo g_tFBVar;
static struct fb_fix_screeninfo g_tFBFix;
static unsigned char *g_pucFBMem;
static unsigned int g_dwScreenSize;
static unsigned int g_dwLineWidth;
static unsigned int g_dwPixelWidth;
static int FBDeviceInit(void)
{
int ret;
g_lcd_fd = open(FB_DEVICE_NAME, O_RDWR);
if (0 > g_lcd_fd)
{
DBG_PRINTF("can't open %s\n", FB_DEVICE_NAME);
}
ret = ioctl(g_lcd_fd, FBIOGET_VSCREENINFO, &g_tFBVar);
if (ret < 0)
{
DBG_PRINTF("can't get fb's var\n");
return -1;
}
ret = ioctl(g_lcd_fd, FBIOGET_FSCREENINFO, &g_tFBFix);
if (ret < 0)
{
DBG_PRINTF("can't get fb's fix\n");
return -1;
}
g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8;
g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_lcd_fd, 0);
if (0 > g_pucFBMem)
{
DBG_PRINTF("can't mmap\n");
return -1;
}
g_dwLineWidth = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;
g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;
return 0;
}
static int FBShowPixel(int iX, int iY, unsigned int dwColor)
{
unsigned char *pucFB;
unsigned short *pwFB16bpp;
unsigned int *pdwFB32bpp;
unsigned short wColor16bpp; /* 565 */
int iRed;
int iGreen;
int iBlue;
if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres))
{
DBG_PRINTF("out of region\n");
return -1;
}
pucFB = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX;
pwFB16bpp = (unsigned short *)pucFB;
pdwFB32bpp = (unsigned int *)pucFB;
switch (g_tFBVar.bits_per_pixel)
{
case 8:
{
*pucFB = (unsigned char)dwColor;
break;
}
case 16:
{
iRed = (dwColor >> (16+3)) & 0x1f;
iGreen = (dwColor >> (8+2)) & 0x3f;
iBlue = (dwColor >> 3) & 0x1f;
wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;
*pwFB16bpp = wColor16bpp;
break;
}
case 32:
{
*pdwFB32bpp = dwColor;
break;
}
default :
{
DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);
return -1;
}
}
return 0;
}
static int FBCleanScreen(unsigned int dwBackColor)
{
unsigned char *pucFB;
unsigned short *pwFB16bpp;
unsigned int *pdwFB32bpp;
unsigned short wColor16bpp; /* 565 */
int iRed;
int iGreen;
int iBlue;
int i = 0;
pucFB = g_pucFBMem;
pwFB16bpp = (unsigned short *)pucFB;
pdwFB32bpp = (unsigned int *)pucFB;
switch (g_tFBVar.bits_per_pixel)
{
case 8:
{
memset(g_pucFBMem, dwBackColor, g_dwScreenSize);
break;
}
case 16:
{
iRed = (dwBackColor >> (16+3)) & 0x1f;
iGreen = (dwBackColor >> (8+2)) & 0x3f;
iBlue = (dwBackColor >> 3) & 0x1f;
wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;
while (i < g_dwScreenSize)
{
*pwFB16bpp = wColor16bpp;
pwFB16bpp++;
i += 2;
}
break;
}
case 32:
{
while (i < g_dwScreenSize)
{
*pdwFB32bpp = dwBackColor;
pdwFB32bpp++;
i += 4;
}
break;
}
default :
{
DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);
return -1;
}
}
return 0;
}
int FBShowLine(int iXStart, int iXEnd, int iY, unsigned char *pucRGBArray)
{
int i = iXStart * 3;
int iX;
unsigned int dwColor;
if (iY >= g_tFBVar.yres)
return -1;
if (iXStart >= g_tFBVar.xres)
return -1;
if (iXEnd >= g_tFBVar.xres)
{
iXEnd = g_tFBVar.xres;
}
for (iX = iXStart; iX < iXEnd; iX++)
{
/* 0xRRGGBB */
dwColor = (pucRGBArray[i]<<16) + (pucRGBArray[i+1]<<8) + (pucRGBArray[i+2]<<0);
i += 3;
FBShowPixel(iX, iY, dwColor);
}
return 0;
}
int check_if_png(char *file_name)
{
char buf[PNG_BYTES_TO_CHECK];
/* Open the prospective PNG file. */
if ((g_png_fd = fopen(file_name, "rb")) == NULL)
{
printf("open %s is fail\n",file_name);
return 0;
}
/* Read in some of the signature bytes */
if (fread(buf, 1, PNG_BYTES_TO_CHECK, g_png_fd) != PNG_BYTES_TO_CHECK)
return 0;
/* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
Return nonzero (true) if they match */
/* Close the file */
fclose(g_png_fd);
return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
}
int read_png_data(char *filepath) /* 用于解码png图片 */
{
png_bytep *row_pointers;
png_structp png_ptr;
png_infop info_ptr;
int temp;
int color_type,channels,i;
int width,height,bit_depth,flag;
g_png_fd = fopen(filepath, "rb");
if(g_png_fd == NULL) /* 文件打开失败 */
{
return -1;
}
/* 初始化各种结构 */
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
info_ptr = png_create_info_struct(png_ptr);
setjmp(png_jmpbuf(png_ptr)); // 这句很重要
rewind(g_png_fd);
/*开始读文件*/
png_init_io(png_ptr, g_png_fd);
// 读文件了
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);
/*获取宽度,高度,位深,颜色类型*/
channels = png_get_channels(png_ptr, info_ptr); /*获取通道数*/
width = png_get_image_width(png_ptr, info_ptr);
height = png_get_image_height(png_ptr, info_ptr);
bit_depth = png_get_bit_depth(png_ptr, info_ptr); /* 获取位深 */
color_type = png_get_color_type(png_ptr, info_ptr); /*颜色类型*/
/* row_pointers里边就是rgba数据 */
row_pointers = png_get_rows(png_ptr, info_ptr);
if(channels == 4 || color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{/*如果是RGB+alpha通道,或者RGB+其它字节*/
flag = HAVE_ALPHA; /* 标记 */
temp = (4 * width);/* 每行有4 * out->width个字节 */
for(i = 0; i < height; i++)
{
FBShowLine(0, temp, height, &row_pointers[i]);
}
}
else if(channels == 3 || color_type == PNG_COLOR_TYPE_RGB)
{/* 如果是RGB通道 */
flag = NO_ALPHA; /* 标记 */
printf("width=%d\n",width);
printf("height=%d\n",height);
printf("bit_depth=%d\n",bit_depth);
temp = (3 * width);/* 每行有3 * out->width个字节 */
printf("row_pointers=%d\n",sizeof(row_pointers));
int j;
for(i = 0; i <height; i++)
{
FBShowLine(0, temp, i, &row_pointers[i]);
for(j=0;j<temp;j+=3)
{
DBG_PRINTF("row_pointers[%d][%d]=0x%x\n",i,j,row_pointers[i][j]);
DBG_PRINTF("row_pointers[%d][%d]=0x%x\n",i,j+1,row_pointers[i][j+1]);
DBG_PRINTF("row_pointers[%d][%d]=0x%x\n",i,j+2,row_pointers[i][j+2]);
}
}
}
else
return -1;
/* 撤销数据占用的内存 */
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
return 0;
}
int main(int argc,char **argv)
{
int i;
if(argc!=2)
{
DBG_PRINTF("Usage: \n");
DBG_PRINTF("%s <png_file>\n", argv[0]);
return -1;
}
if (FBDeviceInit())
{
return -1;
}
FBCleanScreen(0);
i=check_if_png(argv[1]);
if(i==0)
{
DBG_PRINTF("this is not png image file\n");
}
read_png_data(argv[1]);
return 0;
}
这样就可以在LCD上显示png图片了。