libjpeg库使用实例细节分析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: libjpeg库使用实例细节分析

这段代码是一个使用libjpeg库进行JPEG文件解析的模块。以下是代码的主要功能和结构:

MyErrorMgr结构体定义了自定义的错误管理器,用于处理libjpeg库的错误。

isJPGFormat函数用于判断给定的文件是否为JPEG格式。它使用libjpeg库的函数来读取文件头并检查是否为有效的JPEG文件。

CovertOneLine函数用于将从JPEG文件中提取的一行像素数据转换为可以在显示设备上使用的格式。根据输入和输出的像素位数,它将像素数据转换为24位、16位或32位的格式。

GetPixelDatasFrmJPG函数用于从JPEG文件中提取图像数据并转换为可以在显示设备上使用的格式。它使用libjpeg库来解压缩JPEG数据并将其转换为指定的像素位数。

FreePixelDatasForJPG函数用于释放从JPEG文件中提取的像素数据所占用的内存。

JPGParserInit函数用于注册JPEG文件解析模块,将其添加到系统中。

该模块提供了一组函数来解析JPEG文件并将其转换为可以在显示设备上使用的像素数据。它使用libjpeg库提供的函数来处理JPEG文件的解码和转换过程。

错误管理器结构体

typedef struct MyErrorMgr
{
    struct jpeg_error_mgr pub;
    jmp_buf setjmp_buffer;
}T_MyErrorMgr, *PT_MyErrorMgr;

这段代码定义了一个名为 MyErrorMgr 的结构体,并使用 typedef 关键字定义了两个类型别名 T_MyErrorMgr 和 PT_MyErrorMgr。

MyErrorMgr 结构体包含两个成员变量:

pub:类型为 struct jpeg_error_mgr,是 libjpeg 库中定义的错误管理器结构体。

setjmp_buffer:类型为 jmp_buf,用于实现跳转缓冲区,用于错误处理。

通过 typedef 关键字,将 MyErrorMgr 结构体类型别名为 T_MyErrorMgr,并将指向 MyErrorMgr 结构体的指针类型别名为 PT_MyErrorMgr。

这样做的目的是定义一个自定义的错误管理器结构体,继承了 libjpeg 库中的错误管理器结构体,并添加了额外的字段用于自定义的错误处理。通过使用类型别名,可以方便地在代码中使用 T_MyErrorMgr 和 PT_MyErrorMgr 来表示该结构体类型和指针类型。

libjpeg库出错处理函数

static void MyErrorExit(j_common_ptr ptCInfo)
{
    static char errStr[JMSG_LENGTH_MAX];
    PT_MyErrorMgr ptMyErr = (PT_MyErrorMgr)ptCInfo->err;
    /* Create the message */
    (*ptCInfo->err->format_message) (ptCInfo, errStr);
    DBG_PRINTF("%s\n", errStr);
    longjmp(ptMyErr->setjmp_buffer, 1);
}

这段代码实现了一个自定义的错误处理函数 MyErrorExit,该函数用于处理由 libjpeg 库发生的错误。以下是对该函数的逐行解析:

static void MyErrorExit(j_common_ptr ptCInfo): 函数声明,接受一个名为 ptCInfo 的 j_common_ptr 类型参数,该参数是 libjpeg 库抽象出来的通用结构体指针。

static char errStr[JMSG_LENGTH_MAX];: 定义一个静态字符数组 errStr,长度为 JMSG_LENGTH_MAX,用于存储错误消息字符串。

PT_MyErrorMgr ptMyErr = (PT_MyErrorMgr)ptCInfo->err;: 声明并初始化一个名为 ptMyErr 的指针变量,将 ptCInfo->err 强制转换为 PT_MyErrorMgr 类型,即自定义的错误管理器结构体指针。

(*ptCInfo->err->format_message) (ptCInfo, errStr);: 调用 ptCInfo->err->format_message 函数指针指向的函数,将错误消息格式化为字符串,并将其存储在 errStr 中。

DBG_PRINTF(“%s\n”, errStr);: 将错误消息打印输出到调试输出中。

longjmp(ptMyErr->setjmp_buffer, 1);: 使用 longjmp 函数跳转到 ptMyErr->setjmp_buffer 所标记的位置,同时传递参数 1。

总体而言,该函数的功能是在 libjpeg 库发生错误时,将错误消息格式化并输出到调试输出,然后通过 longjmp 函数跳转到错误处理的位置,以便进行进一步的处理或退出程序。

文件是否为JPG文件

/**********************************************************************
 * 函数名称: isJPGFormat
 * 功能描述: JPG模块是否支持该文件,即该文件是否为JPG文件
 * 输入参数: ptFileMap - 内含文件信息
 * 输出参数: 无
 * 返 回 值: 0 - 不支持, 1 - 支持
 ***********************************************************************/
static int isJPGFormat(PT_FileMap ptFileMap)
{
    struct jpeg_decompress_struct tDInfo;
    /* 默认的错误处理函数是让程序退出
     * 我们参考libjpeg里的bmp.c编写自己的错误处理函数
     */
    //struct jpeg_error_mgr tJErr;   
    T_MyErrorMgr tJerr;
    int iRet;
    fseek(ptFileMap->tFp, 0, SEEK_SET);
    // 分配和初始化一个decompression结构体
    // tDInfo.err = jpeg_std_error(&tJErr);
    tDInfo.err               = jpeg_std_error(&tJerr.pub);
    tJerr.pub.error_exit     = MyErrorExit;
    if(setjmp(tJerr.setjmp_buffer))
    {
        /* 如果程序能运行到这里, 表示JPEG解码出错 */
        jpeg_destroy_decompress(&tDInfo);
        return 0;;
    }
    jpeg_create_decompress(&tDInfo);
    // 用jpeg_read_header获得jpg信息
    jpeg_stdio_src(&tDInfo, ptFileMap->tFp);
    iRet = jpeg_read_header(&tDInfo, TRUE);
    jpeg_abort_decompress(&tDInfo);
    return (iRet == JPEG_HEADER_OK);
}

这段代码实现了一个函数 isJPGFormat,用于检查给定文件是否为 JPEG 格式。以下是对该函数的逐行解析:

static int isJPGFormat(PT_FileMap ptFileMap): 函数声明,接受一个名为 ptFileMap 的 PT_FileMap 类型参数,该参数是文件映射结构体指针。

struct jpeg_decompress_struct tDInfo;: 声明一个 jpeg_decompress_struct 结构体变量 tDInfo,用于存储 JPEG 解压缩相关的信息。

T_MyErrorMgr tJerr;: 声明一个 T_MyErrorMgr 结构体变量 tJerr,用于自定义的错误管理器。

int iRet;: 声明一个 int 类型变量 iRet,用于存储函数执行结果。

fseek(ptFileMap->tFp, 0, SEEK_SET);: 将文件指针移动到文件开头位置,以便进行后续的读取操作。

tDInfo.err = jpeg_std_error(&tJerr.pub);: 将 tJerr.pub 的错误管理器结构体赋值给 tDInfo.err,用于处理 JPEG 解压缩过程中的错误。

tJerr.pub.error_exit = MyErrorExit;: 将自定义的错误处理函数 MyErrorExit 赋值给 tJerr.pub.error_exit,以便在发生错误时执行相应的错误处理。

if (setjmp(tJerr.setjmp_buffer)): 使用 setjmp 函数设置一个跳转点,并检查跳转标记是否被设置。

jpeg_destroy_decompress(&tDInfo);: 在发生错误时,释放 JPEG 解压缩结构体 tDInfo 的资源。

return 0;: 返回 0,表示给定文件不是 JPEG 格式。

jpeg_create_decompress(&tDInfo);: 创建 JPEG 解压缩对象 tDInfo。

jpeg_stdio_src(&tDInfo, ptFileMap->tFp);: 将文件指针 ptFileMap->tFp 与 JPEG 解压缩对象 tDInfo 关联,以便从文件中读取 JPEG 数据。

iRet = jpeg_read_header(&tDInfo, TRUE);: 使用 jpeg_read_header 函数读取 JPEG 数据的头信息,并将结果存储在 iRet 变量中。

jpeg_abort_decompress(&tDInfo);: 中止 JPEG 解压缩过程,释放相关资源。

return (iRet == JPEG_HEADER_OK);: 返回比较结果 (iRet == JPEG_HEADER_OK),表示给定文件是否为有效的 JPEG 格式。

总体而言,该函数通过使用 libjpeg 库的函数来判断给定文件是否为 JPEG 格式。它首先尝试解析文件头信息,如果成功解析并返回 JPEG_HEADER_OK,则表示给定文件是有效的 JPEG 格式;否则,表示给定文件不是 JPEG 格式或解析过程中发生了错误。

取出的一行象素数据,转换为能在显示设备上使用的格式

/**********************************************************************
 * 函数名称: CovertOneLine
 * 功能描述: 把已经从JPG文件取出的一行象素数据,转换为能在显示设备上使用的格式
 * 输入参数: iWidth      - 宽度,即多少个象素
 *            iSrcBpp     - 已经从JPG文件取出的一行象素数据里面,一个象素用多少位来表示
 *            iDstBpp     - 显示设备上一个象素用多少位来表示
 *            pudSrcDatas - 已经从JPG文件取出的一行象素数所存储的位置
 *            pudDstDatas - 转换所得数据存储的位置
 * 输出参数: 无
 * 返 回 值: 0 - 成功, 其他值 - 失败
 ***********************************************************************/
static int CovertOneLine(int iWidth, int iSrcBpp, int iDstBpp, unsigned char *pudSrcDatas, unsigned char *pudDstDatas)
{
    unsigned int dwRed;
    unsigned int dwGreen;
    unsigned int dwBlue;
    unsigned int dwColor;
    unsigned short *pwDstDatas16bpp = (unsigned short *)pudDstDatas;
    unsigned int   *pwDstDatas32bpp = (unsigned int *)pudDstDatas;
    int i;
    int pos = 0;
    if (iSrcBpp != 24)
    {
        return -1;
    }
    if (iDstBpp == 24)
    {
        memcpy(pudDstDatas, pudSrcDatas, iWidth*3);
    }
    else
    {
        for (i = 0; i < iWidth; i++)
        {
            dwRed   = pudSrcDatas[pos++];
            dwGreen = pudSrcDatas[pos++];
            dwBlue  = pudSrcDatas[pos++];
            if (iDstBpp == 32)
            {
                dwColor = (dwRed << 16) | (dwGreen << 8) | dwBlue;
                *pwDstDatas32bpp = dwColor;
                pwDstDatas32bpp++;
            }
            else if (iDstBpp == 16)
            {
                /* 565 */
                dwRed   = dwRed >> 3;
                dwGreen = dwGreen >> 2;
                dwBlue  = dwBlue >> 3;
                dwColor = (dwRed << 11) | (dwGreen << 5) | (dwBlue);
                *pwDstDatas16bpp = dwColor;
                pwDstDatas16bpp++;
            }
        }
    }
    return 0;
}


目录
相关文章
|
1月前
|
关系型数据库 MySQL Linux
文章对比了编译源码安装与使用 RPM 包安装的优缺点,帮助读者根据自身需求选择最合适的安装方法
【10月更文挑战第8天】本文介绍了在 CentOS 7 中通过编译源码安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务及登录设置等。同时,文章对比了编译源码安装与使用 RPM 包安装的优缺点,帮助读者根据自身需求选择最合适的安装方法。
77 4
|
2月前
|
Perl
探索研究Perl 包和模块
【9月更文挑战第20天】
57 16
|
2月前
|
存储 计算机视觉 C++
在C++中实现Armadillo库与OpenCV库之间的数据格式转换
在C++中实现Armadillo库与OpenCV库之间的数据格式转换是一项常见且实用的技能。上述步骤提供了一种标准的方法来进行这种转换,可以帮助开发者在两个库之间高效地转移和处理数据。虽然转换过程相对直接,但开发者应留意数据类型匹配和性能优化等关键细节。
62 11
|
6月前
|
C语言
转载 - gcc/ld 动态连接库和静态连接库使用方法
本文介绍了如何在GCC中实现部分程序静态链接、部分动态链接。使用`-Wl`标志传递链接器参数,`-Bstatic`强制链接静态库,`-Bdynamic`强制链接动态库。
|
6月前
|
编译器 定位技术 C++
【CMake高级技巧】如何创建一个通用的库查找模板?
【CMake高级技巧】如何创建一个通用的库查找模板?
82 0
|
6月前
|
监控 Linux 测试技术
嵌入式硬件库的基本操作方式与分析
嵌入式硬件库的基本操作方式与分析
73 0
|
存储 Serverless
FreeType使用实例细节分析
FreeType使用实例细节分析
227 0
|
数据可视化 C++
VS2015上boost可视化图形开发库的应用和操作
VS2015上boost可视化图形开发库的应用和操作
288 0
VS2015上boost可视化图形开发库的应用和操作
|
C语言 计算机视觉 C++
ffmpeg 纯静态编译,以及添加自定义库流程摘要
需求:    1. 纯静态编译ffmpeg ,即ldd ./ffmpeg 的结果是:not a dynamic executable    2.  修改ffmpeg 项目,添加自定义功能库    3. 自定义库由c++实现,要求能被纯c的ffmpeg项目调用    4. 自定义库必须使用g++ 的一些高级特性编译,要求g++支持c++11    5. 自定义库使用了pthread库 和openmp 库    6. 自定义库使用了opencv 3.0.0库,    7. 禁用所有的图形显示库x11,xcb,声音设备avdevice等等,静态链接这些库,会很痛苦。
4939 0
|
缓存 Linux
7.16 Linux函数库(静态函数库和动态函数库)及其安装过程
Linux 系统中存在大量的函数库。简单来讲,函数库就是一些函数的集合,每个函数都具有独立的功能且能被外界调用。我们在编写代码时,有些功能根本不需要自己实现,直接调用函数库中的函数即可。
385 0
7.16 Linux函数库(静态函数库和动态函数库)及其安装过程