jpeg解码库使用实例

2023-05-16

jpeg库下载地址:
    http://www.ijg.org/

交叉编译三部曲:
    A ./configure --host=arm-linux-gcc --prefix=/home/flying/jpeg-install
    B  make
    C  make install
jpeg库是解压jpeg/jpg图片或将图片压缩为jpeg/jpg格式所用到的库,使用起来比较简单!

jpeg/jpg解码过程:

    1. 创建jpeg对象和错误处理对象
        struct jpeg_decompress_struct cinfo;
        struct jpeg_error_mgr         jerr; 

    2. 将错误处理对象绑定到jpeg对象上
        EXTERN(struct jpeg_error_mgr *) jpeg_std_error
        JPP((struct jpeg_error_mgr * err));

    3. 初始化jpeg对象
        #define jpeg_create_compress(cinfo) \
    jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
                        (size_t) sizeof(struct jpeg_compress_struct))

    4. 指定解压数据源(有两种方式)
        a. EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, const unsigned char * inbuffer, unsigned long insize));
            参数一: jpeg对象地址
            参数二: 储存jpeg数据源缓冲区
            参数三: 缓冲区数据源大小

        b. EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile));
            参数一: jpeg对象地址
            参数二: 要解压的jpeg图片的文件指针

    5. 填充cinfo对象的缺省信息,常见的可用信息包括图像的
       宽:       cinfo.image_width,
       高:       cinfo.image_height,
       色彩空间:  cinfo.jpeg_color_space,
       颜色通道数: cinfo.num_components等。
       EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo,
                                  boolean require_image));

    6. 为解压设定参数**(依情况而定)**
        比如解压的图片与原图的缩放比例为1/2,这可以设置参数
        cinfo.scale_num   = 1
        cinfo.scale_denom = 2

    7. 开始解压
        EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo));

    在完成解压缩操作后,会将解压后的图像信息填充至cinfo结构中。比如,输出图
    像宽度cinfo.output_width,输出图像高度cinfo.output_height,每个像
    素中的颜色通道数cinfo.output_components(比如灰度为1,全彩色为3)
    等。
    一般情况下,这些参数是在jpeg_start_decompress后才被填充到cinfo中
    的,如果希望在调用jpeg_start_decompress之前就获得这些参数,可以通过
    调用jpeg_calc_output_dimensions()的方法来实现。


    8. 取数据
        解压出来的数据是按照行取出的,从左到右,从上到下的顺序,每个像
        素对应的各颜色或灰度通道数据是依次存储,24位RGB图解压后的颜色
        通道排序是R,G,B,R,G,B......

        我们可以使用此函数取出循环取出数据:
        extern JDIMENSION jpeg_read_scanlines(j_decompress_ptr, JSAMPARRAY,
                      JDIMENSION);
            参数二: 一般来说就是unsigned char *,表示保存数据的缓冲区
            参数三: 表示要读取的行数

    9. 解压完毕释放资源
        boolean jpeg_finish_decompress(j_decompress_ptr cinfo);

        后续不需要使用jpeg对象:
        void jpeg_destroy_decompress(j_decompress_ptr cinfo);

        如果在后续还需使用jpeg对象,则使用:
        void jpeg_abort_decompress(j_decompress_ptr cinfo);
实例:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdbool.h>


#include "jpeglib.h"
#include "my_err.h"



struct image_info
{
    int width;
    int height;
    int pixel_size;
};

//将图片显示到LCD屏幕上,最后两个参数指定显示的原点坐标
void write_jpeg_to_lcd(unsigned char *lcdmem, unsigned char *rgb_buffer
                        , struct fb_var_screeninfo *vinfo, struct image_info *image_info
                        , size_t xoffset, size_t yoffset)
{
    assert(lcdmem);
    assert(rgb_buffer);
    assert(vinfo);
    assert(image_info); 

    int x, y;

    size_t r_offset = vinfo->red.offset / 8;
    size_t g_offset = vinfo->green.offset / 8;
    size_t b_offset = vinfo->blue.offset / 8;

    for (y = 0; (y < vinfo->yres - yoffset) && (y < image_info->height); ++y) {

        for (x = 0; (x < vinfo->xres - xoffset) && (x < image_info->width); ++x) {

            size_t image_offset     =   (x * image_info->pixel_size) + (image_info->width * image_info->pixel_size * y);
            size_t lcd_offset       =   ((x + xoffset) * vinfo->bits_per_pixel / 8) + ((y + yoffset) * vinfo->xres * vinfo->bits_per_pixel /8);

            memcpy(lcdmem + lcd_offset + r_offset, rgb_buffer + image_offset, 1);
            memcpy(lcdmem + lcd_offset + g_offset, rgb_buffer + image_offset + 1, 1);
            memcpy(lcdmem + lcd_offset + b_offset, rgb_buffer + image_offset + 2, 1);
        }
    }
}

void read_image_from_file(int fd, unsigned char *jpeg_buffer, size_t image_size)
{
    assert(jpeg_buffer);

    int nread = 0;

    while (image_size > 0) {
        nread = read(fd, jpeg_buffer, image_size);
        if (nread < 0) {
            if (EINTR == errno) {
                continue;
            } else {
                err_sys("read error");
            }
        }

        image_size -= nread;
        jpeg_buffer += nread;
    }
}


int main(int argc, char **argv)
{
    if (2 != argc) {
        err_quit("Usage: %s <*.jpeg/jpg>\n", argv[1]);
    }

    int image_fd;
    if ((image_fd = open(argv[1], O_RDONLY)) < 0) {
        err_sys("open error");
    }

    struct stat sbuf;
    if (fstat(image_fd, &sbuf) < 0) {
        err_sys("stat error");
    }

    unsigned char *jpeg_buffer = calloc(1, sbuf.st_size);
    read_image_from_file(image_fd, jpeg_buffer, sbuf.st_size);


    struct jpeg_decompress_struct   cinfo;
    struct jpeg_error_mgr           jerr;

    cinfo.err   =   jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);

    jpeg_mem_src(&cinfo, jpeg_buffer, sbuf.st_size);

    if (JPEG_HEADER_OK != jpeg_read_header(&cinfo, true)) {
        err_sys("read head error");
    }

    jpeg_start_decompress(&cinfo);


    struct image_info *image_info   =   calloc(1, sizeof(struct image_info));
    if (image_info == NULL) {
        err_sys("calloc error for image_info");
    }

    image_info->width       =   cinfo.output_width;
    image_info->height      =   cinfo.output_height;
    image_info->pixel_size  =   cinfo.output_components;

    int row_stride  =   image_info->width * image_info->pixel_size;
    size_t rgb_size =   row_stride * image_info->height;

    unsigned char *rgb_buffer = calloc(1, rgb_size);
    if (rgb_buffer == NULL) {
        err_sys("rgb_buffer error");
    }

    //循环读取解压后的数据,cinfo.output_scanline表示当前读取的行数
    while (cinfo.output_scanline < image_info->height) {
        unsigned char *buffer_array[1];
        buffer_array[0] =   rgb_buffer + cinfo.output_scanline * row_stride;
        jpeg_read_scanlines(&cinfo, buffer_array, 1);
    }


    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    free(jpeg_buffer);


    int lcd_fd;
    if ((lcd_fd = open("/dev/fb0", O_RDWR)) < 0 ) {
        err_sys("open error");
    }   

    struct fb_var_screeninfo vinfo;
    ioctl(lcd_fd, FBIOGET_VSCREENINFO, &vinfo);

    size_t mem_size =   vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
    unsigned char *lcdmem   =   mmap(0, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0);
    if (lcdmem == MAP_FAILED) {
        err_sys("mmap error");
    }

    write_jpeg_to_lcd(lcdmem, rgb_buffer, &vinfo, image_info, 100, 100);

    free(rgb_buffer);
    munmap(lcdmem, mem_size);
    close(lcd_fd);
    close(image_fd);

    return EXIT_SUCCESS;
}
参考博客:
    http://blog.csdn.net/xipiaoyouzi/article/details/53257720
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

jpeg解码库使用实例 的相关文章

  • Tiff 中的 Jpeg(jpeg 压缩)

    如何从 JPEG 压缩的 TIFF 文件中提取图像 我已根据 StripOffests 和 StripBytesCount 字段读取字节 但无法从中加载图像 旧式 TIFF JPEG 压缩类型 6 基本上将普通 JFIF 文件填充到 TIF
  • Java - 复制 JPG 同时保留所有文件属性

    在保持文件所有属性 创建日期 日期等 的同时移动 复制文件的最佳方法是什么 谢谢 如果您使用的是 Java 7 请使用java nio file Files copy Path source Path target CopyOption o
  • 捕获错误:损坏的 JPEG 数据:数据段过早结束

    当使用损坏 不完整的 JPEG 数据创建 UIImage 时 控制台将打印出
  • 在 C# 中使用 jpegtran、jpegoptim 或其他 jpeg 优化/压缩

    我在网上商店收集了 100 种 也许是 1000 种 产品 其中每种产品都有 10 30 张图片 我需要在不损失图像质量的情况下尽可能优化图像的文件大小 我没有直接使用 jpegtran jpegoptim 或任何其他 jpeg 优化器 但
  • 如何在 Java 中从 JPEG 创建缩略图?

    有人可以帮忙编写一些用 Java 创建 JPEG 缩略图的代码吗 我对此很陌生 因此将不胜感激逐步的解释 Image img ImageIO read new File test jpg getScaledInstance 100 100
  • JPG 与 JPEG 图像格式

    我经常使用JPEG图像 我注意到有两个非常相似的文件扩展名 jpg 我手机的摄像头和Preview应用程序的使用 以及 jpeg 其中图像捕捉保存用我的扫描仪扫描的图像佳能MX455打印机 LaTeX似乎没有区别 因为我给了它一个 jpeg
  • 在我的应用程序中包含 jpeg 插件

    我制作了一个加载 jpeg 文件的 Qt GUI 应用程序 在我安装了 QtSDK 4 7 3 的开发系统 Win7 上 它可以工作 当我将应用程序和一些必需的 dll 如 QtGui4 dll 等 移动到另一个未安装 QtSDK 的系统时
  • “标准”RGB 到灰度转换

    我正在尝试编写一个转换器算法 该算法采用 JPEG 图像并返回其 PGM 便携式灰度图 版本 问题是我无法理解 官方 JPG gt PGM 转换器如何从经典 RGB 格式开始为最终像素分配什么值 我猜是 0 gt 255 一开始 我使用了这
  • Node.js:从 jpeg 图像到视频文件的实时转换

    我正在使用node js 并通过socket io 库接收实际上是jpeg 图像的数据块 这些图像是从远程网络摄像头捕获的实时视频帧 我被迫将视频作为 jpeg 帧进行流式传输 我正在寻找一种方法来动态转换视频文件 mpeg 4 或 mjp
  • 以 jpeg 格式保存色彩空间

    我有一个 servlet 来转换和缓存较小版本的照片 它是使用 java awt image javax imageio 和第三方重采样过滤器实现的 原件均使用 sRGB 颜色配置文件上传 当我重新采样并再次保存它们时 它们仍然处于 sRG
  • Http PUT 请求到 jpeg

    我收到了如下 HTTP PUT PUT photo HTTP 1 1 X Apple AssetKey F92F9B91 954E 4D63 BB9A EEC771ADE6E8 X Apple Transition Dissolve Con
  • 调整 MailItem 中粘贴的 JPEG 的大小

    我正在尝试从 Excel 工作表发送图片 但尺寸非常小 我怎样才能获得合适的尺寸 基本上是整个屏幕 这是代码 Sub send as a pic Copy range of interest Dim r As Range Set r Ran
  • 如何在 Android 中从 JPEG 创建动画 GIF(开发)

    我正在寻找一种简单的方法create本机 Android 应用程序中的动画 GIF 源文件应为 JPEG 来自相机或其他文件 输出应在设备上保存为 GIF 我不想知道如何播放动画或动画 GIF 文件 需要明确的是 我想知道如何将单个图像逐帧
  • opencv 2.3.* 读取不工作

    我无法让 imread 工作 与这个人有同样的问题 OpenCV imwrite 2 2 在 Windows 7 上导致异常 并显示消息 OpenCV 错误 未指定错误 无法找到指定扩展名的编写器 https stackoverflow c
  • DICOM 和 DICOM 叠加问题

    我有一个 DICOM 图像 我正在使用 C 读取该图像并将其转换为 16 位位图 位图已创建 但图像具有 DICOM 覆盖 我想在创建最终的 dicom 位图时将叠加层刻录到位图中 我无法做到这一点 有什么帮助吗 一种方法是创建覆盖数据的位
  • 使用 ImageMagick 和/或 GhostScript 将多页 PDF 转换为多个 JPG

    我正在尝试将多页 PDF 文件转换为一堆 JPEG PDF 中的每一页一个 我花了几个小时寻找如何做到这一点 最终我发现我需要安装 Ghostscript 所以我就这么做了 来自这个网站 http downloads ghostscript
  • 除了标准/渐进之外,第三种JPEG压缩:按通道加载?

    这个问题可能是一个 开放式问题 你们中的许多人可能渴望结束它 但请不要这样做 让我解释 众所周知 JPEG有两种压缩方式 至少在Photoshop保存对话框中 优化 图像加载有点像逐行加载 渐进式 图像首先像马赛克一样加载 逐渐更好 直到原
  • C++ OpenCV imdecode 慢

    我将图像的字节数组从 C 发送到 C 库 我使用 OpenCV 版本 3 3 1 解码图像 BMP 图像解码速度很快 但 JPEG 图像解码速度很慢 如何加快 JPEG 图像的解码时间 多线程 GPU 解码性能 Resolution For
  • 在 .NET 中旋转 JPEG,质量损失最小

    我正在尝试支持从 ASP NET MVC 旋转 JPEG 图像 以 90 度增量 我正在尝试使用System Drawing GDI 但是我遇到了问题 我尝试使用Image RotateFlip http msdn microsoft co
  • 当 Webp 可用时,Chrome 默认为 JPG。为什么?

    当 webp 文件可用时 Chrome 默认使用 jpg png 文件 我通过 Lighthouse 进行了网站审核 它建议 正确调整图像大小并使用 下一代 格式 将文件更改为 webp 并创建多个大小的文件 后 我将文件添加到图片标签下

随机推荐