• 使用Libpng库实现Tiny6410显示PNG图片


    Linux内核版本号:linux 2.6.39

    交叉编译工具     :arm-linux-gcc 4.5.1

    开发板             :友善之臂Tiny6410

    LCD                :友善之臂S70

    Libpng版本       :libpng-1.5.14

    Zlib版本           :zlib-1.2.8

    一、交叉编译Zlib

    Zlib是一个文件压缩库,在Libpng交叉编译的时候需要使用到它的头文件和库,所以先编译它。zlib-1.2.8.tar.gz 下载路径:http://pan.baidu.com/s/1miKXynY

    1、下载并解压zlib-1.2.8.tar.gz 

    tar xzvf zlib-1.2.8.tar.gz

    2、在zlib-1.2.8目录下新建一个tmp目录用于保存交叉编译后生成的lib和include文件

    mkdir tmp

    3、打开Makefile文件并修改CC=arm-linux-gcc

    4、执行配置命令指定生成文件存放路径

    ./configure --prefix=$PWD/tmp

    5、执行make

    6、执行make install, 并查看tmp目录有没有include、lib等目录生成

    二、交叉编译Libpng

    libpng-1.5.14.tar.gz 下载路径:http://pan.baidu.com/s/1qYgnIyC

    1、下载并解压libpng-1.5.14.tar.gz

    tar xzvf libpng-1.5.14.tar.gz

    2、同样在libpng-1.5.14目录下新建一个tmp目录用于保存交叉编译后生成的lib和include文件

    mkdir tmp

    3、执行配置命令指定生成文件存放路径和Zlib库文件目录

    ./configure --prefix=/home/ming/windowssshar/libpng-1.5.14/tmp --host=arm-linux LIBS=-L/home/ming/windowsshar/zlib-1.2.8/tmp/lib CPPFLAGS=-I/home/ming/windowsshar/zlib-1.2.8/tmp/include

    4、执行make

    5、执行make install, 并查看tmp目录有没有include、lib等目录生成

    三、使用Libpng解码图片

    int read_png(char* filename, char IsDoAlphaBlend)  
    {
        FILE *fp;
        png_structp png_ptr;
        png_infop info_ptr;
        png_uint_32 width, height;
        png_uint_32 row;
        int bit_depth, color_type, interlace_type, number_passes;
        int pass,y;
        char* cpPngDispAddr = NULL;
        char* RGB_Data = NULL;
        unsigned int x = 0;
        unsigned int pos = 0;
        unsigned int i = 0;
        int iXres = 0, iYres = 0;
    
        if ((fp = fopen(filename, "rb")) == NULL)
        {
          DEBUG_Print("open %s failed
    ",filename);
          return 0;
        }
    
        /* Create and initialize the png_struct with the desired error handler
        * functions.  If you want to use the default stderr and longjump method,
        * you can supply NULL for the last three parameters.  We also supply the
        * the compiler header file version, so that we know if the application
        * was compiled with a compatible version of the library.  REQUIRED
        */
        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
          NULL, NULL, NULL);
    
        if (png_ptr == NULL)
        {
          fclose(fp);
          return (FALSE);
        }
    
        /* Allocate/initialize the memory for image information.  REQUIRED. */
        info_ptr = png_create_info_struct(png_ptr);
        if (info_ptr == NULL)
        {
            fclose(fp);
            png_destroy_read_struct(&png_ptr, NULL, NULL);
            return (FALSE);
        }
    
    
        /* One of the following I/O initialization methods is REQUIRED */
        /* Set up the input control if you are using standard C streams */
        png_init_io(png_ptr, fp);
    
           /* 获取显存地址 */
        cpPngDispAddr = GetDispVedioMemAddr();
        GetDispResolution(&iXres,&iYres);
    
        /* OK, you're doing it the hard way, with the lower-level functions */
    
        /* The call to png_read_info() gives us all of the information from the
        * PNG file before the first IDAT (image data chunk).  REQUIRED
        */
        png_read_info(png_ptr, info_ptr);
    
        png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
           &interlace_type, NULL, NULL);
           
        DEBUG_Print("width          ---- > [%4d]
    ",width);
        DEBUG_Print("height         ---- > [%4d]
    ",height);
        DEBUG_Print("bit_depth      ---- > [%4d]
    ",bit_depth);
        DEBUG_Print("color_type     ---- > [%4d]
    ",color_type);
        DEBUG_Print("interlace_type ---- > [%4d]
    ",interlace_type);
    
        /* Turn on interlace handling.  REQUIRED if you are not using
        * png_read_image().  To see how to handle interlacing passes,
        * see the png_read_row() method below:
        */
        number_passes = png_set_interlace_handling(png_ptr);
    
        DEBUG_Print("number_passes  ---- > [%4d]
    ",number_passes);
    
        /* The easiest way to read the image: */
        png_bytep row_pointers[height];
    
        /* Clear the pointer array */
        for (row = 0; row < height; row++)
          row_pointers[row] = NULL;
    
        for (row = 0; row < height; row++)
          row_pointers[row] = malloc(width * 4);  /* RGBA */
        for (row = 0; row < height; row++)
          memset(row_pointers[row], 0, width * 4);
    
        /* 分配RGB内存空间 */
        RGB_Data = (char*)malloc(width * 3);
        memset(RGB_Data, 0, width * 3);
        DEBUG_Print("1 RGB_Data -- > [0x%x]
    ",RGB_Data);
    
        /* Now it's time to read the image.  One of these methods is REQUIRED */
        /* Read the image one or more scanlines at a time */
        /* The other way to read images - deal with interlacing: */
    
        if(width > iXres)      width = iXres;
        if(height > iYres)   height = iYres;
    
        for (pass = 0; pass < number_passes; pass++)
        {
            /* 一行一行读取并显示 */
            for (y = 0; y < height; y++)
            {
                 png_read_rows(png_ptr, &row_pointers[y], NULL, 1);
                 WriteOneLineToMem(cpPngDispAddr, (iXres - width)/2, (iXres - width)/2 + width, (iYres - height)/2 + y, &row_pointers[y][0], IsDoAlphaBlend);
            }
        }
    
        /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
        png_read_end(png_ptr, info_ptr);
    
        /* At this point you have read the entire image */
    
        /* Clean up after the read, and free any memory allocated - REQUIRED */
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    
        /* 统一释放内存 */
        for (row = 0; row < height; row++)
        {
            free(row_pointers[row]);
        }
        free(RGB_Data);
    
        /* Close the file */
        fclose(fp);
    
        /* That's it */
        return (TRUE);
    }

    这段代码基本上是从Libpng里面的example文件移植过来,在libpng_manual.txt里面有详细的解释。

    四、在显示屏上显示

    1、Alpha混合(AlphaBlend)

    为了使PNG图片显示具有透明效果,需要对前景色和背景色进行AlphaBlend

    简单AlphaBlend算法:假设前景色(要显示的PNG图片)RGBA分别为r1 g1 b1 alpha  背景色的RGB为r2 g2 b2   混合后的RGB为r g b

    r = r1 x alpha/255.0 + r2 x (255 - alpha)/255.0

    g = g1 x alpha/255.0 + g2 x (255 - alpha)/255.0

    b = b1 x alpha/255.0 + b2 x (255 - alpha)/255.0

    static unsigned int AlphaBlend(PT_PNG_INFO PngRGBA, PT_PNG_INFO PngBkRGB, char IsDoAlphaBlend)
    {
        unsigned char r = 0, g = 0, b = 0;
    
        r = (unsigned char)(PngRGBA->R * (PngRGBA->A / 255.0) + (PngBkRGB->R * (255 - PngRGBA->A)) / 255.0);
        g = (unsigned char)(PngRGBA->G * (PngRGBA->A / 255.0) + (PngBkRGB->G * (255 - PngRGBA->A)) / 255.0);
        b = (unsigned char)(PngRGBA->B * (PngRGBA->A / 255.0) + (PngBkRGB->B * (255 - PngRGBA->A)) / 255.0);
        
        return ((r << 16) | (g << 8) | (b));
    }

    PngRGBA为前景色RGBA数据结构体,PngBKRGB为背景色RGB数据结构体,返回值为混合好的RGB值。

    2、在LCD上显示图片

    static void WriteOneLineToMem(char* ptVedioMem, int iXStart, int iXEnd, int iY, unsigned char* ucpDispBuff, char IsDoAlphaBlend)
    {
        int iX = 0, iPoint = 0;
        unsigned int udwData = 0;
        int iXres, iYres;
        unsigned int location;
        T_PNG_INFO tPngRGBA = {0}; 
        T_PNG_INFO tPngBkRGB = {0};
        
        GetDispResolution(&iXres,&iYres);
    
        if(iXEnd > iXres)    return -1;
        if(iY > iYres)    return -1;
         
        for(iX = iXStart; iX < iXEnd; iX++)
        {      
            location = iX * 4 + iY * iXres* 4;
    
            /* 获取前景色RGBA */
            tPngRGBA.R = ucpDispBuff[iPoint + 0];
            tPngRGBA.G = ucpDispBuff[iPoint + 1];
            tPngRGBA.B = ucpDispBuff[iPoint + 2];
            tPngRGBA.A = ucpDispBuff[iPoint + 3];
            
            /* 获取背景色RGB */
            udwData = *((unsigned int*)(ptVedioMem + location));
            tPngBkRGB.R = (udwData >> 16) & 0xFF;
            tPngBkRGB.G = (udwData >> 8)  & 0xFF;
            tPngBkRGB.B = udwData         & 0xFF;
            
            udwData = AlphaBlend(&tPngRGBA, &tPngBkRGB, IsDoAlphaBlend);
    
            *((unsigned int*)(ptVedioMem + location)) = udwData;   
    
            iPoint += 4;  /* RGBA */
        }
        return 0;
    }

    准备两张图片:

                                                   

                                                                    背景图                                                                                                                                               前景图

    显示之后的效果:

    完整代码:http://pan.baidu.com/s/1boD7ZSr

  • 相关阅读:
    C语言文法分析
    词法分析--编程感想
    词法分析(改)
    0916词法分析
    0909关于编译
    python正则表达式
    python除法运算
    python值相等和对象相同
    Java编写程序时要考虑到所有可能的异常
    hadoop 读取文件操作
  • 原文地址:https://www.cnblogs.com/ape-ming/p/5561643.html
Copyright © 2020-2023  润新知