当前位置:   article > 正文

JZ2440 数码相框项目 扩展项目(一) 多文件图标 (二) 显示png_jz2440 相册项目

jz2440 相册项目

链接

  1. JZ2440 数码相框项目 扩展项目介绍
  2. JZ2440 数码相框项目 扩展项目(三) 支持鼠标
  3. JZ2440 数码相框项目 扩展项目(四) 加快显示速度
  4. JZ2440 实现截图 保存为png格式
  5. JZ2440 数码相框项目 扩展项目 1-4 源码下载

扩展项目一

1.目标

在"browse页面"里, 对不同后缀名的文件使用不同的图标

2.分析

该目标比较简单,只需要修改现有"browse页面"里用于显示文件图标的代码,这里可以发现在源码包用于显示文件图标的图片文件为"file.bmp",在代码中搜索该字符串就很容易修改。

3.实现

搜索得到该代码:

static char *g_strFileIconName = "file.bmp";
static T_PixelDatas g_tFileIconPixelDatas; // 
  • 1
  • 2

修改该变量所有使用 “g_tFileIconPixelDatas” 的位置,改成所支持的文件格式的数组即可,
重新定义声明如下:

#define ARRAYSIZE(array) (sizeof(array)/sizeof(array[0]))

typedef struct FileIconDesc {
    const char * type; // 支持的文件类型
    const char * file; // 文件类型对应的图标文件
    T_PixelDatas tPixeldatas; // 从图标文件中读取的RGB数据,在pic_operation.h中定义
}T_FileIconDesc, *PT_FileIconDesc;

#define FileIconDescItem(__type, __file) \
{\
    .type = __type , \
    .file = __file , \
}

// 每次扩展只需要增加一行
static T_FileIconDesc g_TfileIconDesc[] = {
    FileIconDescItem(".bmp", "ico_bmp.bmp"),
    FileIconDescItem(".c",   "ico_c.bmp"),
    FileIconDescItem(".h",   "ico_h.bmp"),
    FileIconDescItem(".jpg", "ico_jpg.bmp"),
    FileIconDescItem(".txt", "ico_txt.bmp"),
};
#define UNKNOW_FILETYPE_ICON "ico_unknow.bmp" // 其余不支持的文件类型的图标文件
static T_PixelDatas g_tFileIconPixelDatas; // 该变量用来存放不支持文件类型图标RGB数据
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

修改定义后,修改文件中其余使用 g_strFileIconName 变量的地方,在原来读取图标数据的地方初始化新定义的图标数组的 tPixeldatas 成员。(当然别忘了初始化不支持的文件类型的图标文件)

使用该函数来获取图标数据(根据后缀名判断)

static PT_PixelDatas GetFilePixelData(const char * filename) {
    int i, len;
    for(i = 0;i < ARRAYSIZE(g_TfileIconDesc);i++) {
        len = strlen(filename) - strlen(g_TfileIconDesc[i].type);
        if (len >= 0 && 0 == strcmp(filename + len, g_TfileIconDesc[i].type)) {
            return &g_TfileIconDesc[i].tPixeldatas; // 后缀相同,返回图标数据
        }
    }
    return &g_tFileIconPixelDatas; // 后缀不同,返回默认图标
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

4.效果

没有去找 bmp图片,手绘。(png格式是之后扩展的,只需要在数组中增加一行)
不同文件对应不同图标

扩展项目二

1.目标

支持其他格式的图片文件, 比如png

2.分析

由于 picfmt_manager.c 图像格式管理抽象类已经做好了抽象,只需要仿照其他子类写出符合该抽象类的子类就可以了,难点主要在于解析png图像。
使用 libpng 库
下载后可以按照源码中的 example.c 来仿写。

3.实现

在 render/format 文件夹下添加 png.c 文件,修改 Makefile。

a.分配注册子类结构体

typedef struct PicFileParser { // 抽象类结构体定义在 pic_operation.h
    char *name;                     /* 图片文件解析模块的名字 */
    int (*isSupport)(PT_FileMap ptFileMap);  /* 是否支持某文件 */
    int (*GetPixelDatas)(PT_FileMap ptFileMap, PT_PixelDatas ptPixelDatas);  /* 从文件中解析出图像的象素数据 */
    int (*FreePixelDatas)(PT_PixelDatas ptPixelDatas);  /* 释放图像的象素数据所占内存 */
    struct PicFileParser *ptNext;  /* 链表 */
}T_PicFileParser, *PT_PicFileParser;

//========= 分配注册子类结构体 =================================================
static T_PicFileParser g_tPNGParser = {
    .name           = "png",
    .isSupport      = isPNGFormat,            // 判断文件是否为png格式文件
    .GetPixelDatas  = GetPixelDatasFrmPNG,    // 获取png文件的数据,应保持接口一致
    .FreePixelDatas = FreePixelDatasForPNG,   // 销毁对象,清理内存
};

int PNGParserInit(void) {
    return RegisterPicFileParser(&g_tPNGParser);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

以下函数都是根据 example.c 修改出来的:

b.判断文件是否为png

返回值: 0 代表不是png, 非0 代表是png

#define PNG_BYTES_TO_CHECK 4
static int isPNGFormat(PT_FileMap ptFileMap) // 该结构体定义在 file.h 已经open的文件
{
    char buf[PNG_BYTES_TO_CHECK];
    if (fseek(ptFileMap->tFp, 0, SEEK_SET)) // 必须读取文件的头
        return 0;
    /* Read in some of the signature bytes. */ // 读取文件头
    if (fread(buf, 1, PNG_BYTES_TO_CHECK, ptFileMap->tFp) != PNG_BYTES_TO_CHECK)
        return 0;
    /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
    * Return nonzero (true) if they match. */ // 调用 libpng 库函数
    return (!png_sig_cmp((png_const_bytep)buf, 0, PNG_BYTES_TO_CHECK));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

c.获取png文件格式

    // 成功返回 0 , 失败返回 非0    // 已经打开的png文件   // 返回给调用者的RGB图像数据
static int GetPixelDatasFrmPNG(PT_FileMap ptFileMap, PT_PixelDatas ptPixelDatas)
{
    png_structp png_ptr;
    png_infop   info_ptr;
    png_uint_32 width, height;
    int bit_depth, color_type, interlace_type;
    int row;

    fseek(ptFileMap->tFp, 0, SEEK_SET); // 保证从文件头部开始读取
    // If you want to use the default stderr and longjump method, you can supply NULL for the last three parameters.
    // 创建 png 对象,使用 longjump 方法来捕获库函数中错误,后三个参数填 NULL
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) { 
        return -1; // 恭喜你,没有对象,单身狗一枚
    }
    /* Allocate/initialize the memory for image information.  REQUIRED. */
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return -1; // 恭喜你,逃不过单身狗的命运
    }

    // Set error handling if you are using the setjmp/longjmp method
    if (setjmp(png_jmpbuf(png_ptr))) // 使用 longjmp 方法
    {
        /* Free all of the memory associated with the png_ptr and info_ptr. */
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        free(ptPixelDatas->aucPixelDatas);
        /* If we get here, we had a problem reading the file. */
        return -1;
    }
    png_init_io(png_ptr, ptFileMap->tFp); // 初始化对象
    // If we have already read some of the signature
    png_set_sig_bytes(png_ptr, 0);  // 不懂就写 0 ,可能是说读取了多少字节了?
    png_read_info(png_ptr, info_ptr); // 读取 png 文件头中的信息
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
       &interlace_type, NULL, NULL); // 获取 png 文件头中的信息
    DBG_PRINTF("\twidth=%d,height=%d,bit_depth=%d\n\tcolor_type=%d,interlace_type=%d\n",
        width, height, bit_depth, color_type, interlace_type);
    // Strip alpha bytes from the input data without combining with the background (not recommended).
    png_set_strip_alpha(png_ptr); // 丢弃透明度和背景
    /* Expand paletted colors into true RGB triplets. */
    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png_ptr); // 如果是调色板颜色,转换成 RGB 颜色
    /* Invert monochrome files to have 0 as white and 1 as black. */
    //png_set_invert_mono(png_ptr); // 单色文件反转(没有使用),彩色会不会反转我也没有测试过
    png_read_update_info(png_ptr, info_ptr); // 似乎是更新上面的配置
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
       &interlace_type, NULL, NULL); // 再读取一次,会发现 color_type 的值可能不一样
    DBG_PRINTF("\twidth=%d,height=%d,bit_depth=%d\n\tcolor_type=%d,interlace_type=%d\n",
        width, height, bit_depth, color_type, interlace_type);

	// 准备数据输出给调用者
    ptPixelDatas->iWidth        = width;
    ptPixelDatas->iHeight       = height;
    //ptPixelDatas->iBpp          = 24; // 该变量被抽象类设置
    ptPixelDatas->iLineBytes    = width * (ptPixelDatas->iBpp >> 3);
    ptPixelDatas->iTotalBytes   = height * ptPixelDatas->iLineBytes;
    ptPixelDatas->aucPixelDatas = (unsigned char*)malloc(ptPixelDatas->iTotalBytes);
    printf("ptPixelDatas->iTotalBytes = %d\n",ptPixelDatas->iTotalBytes);
    if(!ptPixelDatas->aucPixelDatas) {
        DBG_PRINTF("%s malloc error!\n",ptFileMap->strFileName);
        return -1;
    }
    unsigned char* tmpbuf = (unsigned char*)malloc(width * height * 3);
    if(!tmpbuf) {
        free(ptPixelDatas->aucPixelDatas);
        return -1;
    }
    for (row = 0; row < height; row++)
    {
        png_read_row(png_ptr, tmpbuf, NULL); // 读取一行数据,读取的数据为24BPP,RGB
        // 该函数将读取到的一行数据转换为显示器所需要的BPP数据,这里不介绍
        CovertOneLine(width, 24, ptPixelDatas->iBpp, tmpbuf,
            ptPixelDatas->aucPixelDatas + row * ptPixelDatas->iLineBytes);
    }
    free(tmpbuf);
    png_read_end(png_ptr, info_ptr); // 读取结束调用 png_read_end
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL); // 销毁对象
    return 0; // 成功读取
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

4.效果

据说都用该图片测试效果,我也试试。
了解更多:lenna的故事
下载原图:lenna原图
保存的话好像是jpg格式558K,我用画图转换成png格式,大小居然有5.53M
在JZ2440中打开很慢,至少要 6、7秒左右。
lenna

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/263408?site
推荐阅读
相关标签
  

闽ICP备14008679号