libjpeg的使用

1、基本的YUYV格式转化为RGB格式的方法

//--------------------------------------
//YUYV图像转JPG
//
//
//----------------------------------------
int convert_yuv_to_rgb_pixel(int y, int u, int v)
{
        unsigned int pixel32 = 0;
        unsigned char *pixel = (unsigned char *)&pixel32;
        int r, g, b;
        r = y + (1.370705 * (v-128));
        g = y - (0.698001 * (v-128)) - (0.337633 * (u-128));
        b = y + (1.732446 * (u-128));
        if(r > 255) r = 255;
        if(g > 255) g = 255;
        if(b > 255) b = 255;
        if(r < 0) r = 0;
        if(g < 0) g = 0;
        if(b < 0) b = 0;
        pixel[0] = r ;
        pixel[1] = g ;
        pixel[2] = b ;
        return pixel32;
}

int convert_yuv_to_rgb_buffer(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
{
        unsigned int in, out = 0;
        unsigned int pixel_16;
        unsigned char pixel_24[3];
        unsigned int pixel32;
        int y0, u, y1, v;

        for(in = 0; in < width * height * 2; in += 4)
        {
                pixel_16 =
                                yuv[in + 3] << 24 |
                                yuv[in + 2] << 16 |
                                yuv[in + 1] <<  8 |
                                yuv[in + 0];
                y0 = (pixel_16 & 0x000000ff);
                u  = (pixel_16 & 0x0000ff00) >>  8;
                y1 = (pixel_16 & 0x00ff0000) >> 16;
                v  = (pixel_16 & 0xff000000) >> 24;
                pixel32 = convert_yuv_to_rgb_pixel(y0, u, v);
                pixel_24[0] = (pixel32 & 0x000000ff);
                pixel_24[1] = (pixel32 & 0x0000ff00) >> 8;
                pixel_24[2] = (pixel32 & 0x00ff0000) >> 16;
                rgb[out++] = pixel_24[0];
                rgb[out++] = pixel_24[1];
                rgb[out++] = pixel_24[2];
                pixel32 = convert_yuv_to_rgb_pixel(y1, u, v);
                pixel_24[0] = (pixel32 & 0x000000ff);
                pixel_24[1] = (pixel32 & 0x0000ff00) >> 8;
                pixel_24[2] = (pixel32 & 0x00ff0000) >> 16;
                rgb[out++] = pixel_24[0];
                rgb[out++] = pixel_24[1];
                rgb[out++] = pixel_24[2];
        }
        return 0;

}

下面是一个完成的压缩JPEG和解压缩JPEG的程序

/*
 * hellojpeg.c
 * 
 * This program is under Omega Project 2012.
 * 
 * Copyright 2012 S O Coleman
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 * 
 * 
 */


#include <stdio.h>
#include <jpeglib.h>
#include <malloc.h>
#include "hellojpeg.h"

/*
char filename[] = "02.jpg";
char filenameout[] = "A02.jpg";

int width, height = 0;
unsigned char *data;

int main(int argc, char **argv)
{
    read_jpeg(filename, &data, &width, &height);
    unsigned char pixel[3] = {0, 0, 0};
    set_pixel_of(0, 0, pixel, &data, &width, &height);
    write_jpeg(filenameout, &data, &width, &height);
	return 0;
}
*/

void read_jpeg(char *filename, unsigned char **data, int *width, int *height)
{
    FILE * infile = fopen(filename, "rb");
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, infile);
    jpeg_read_header(&cinfo, TRUE);
    jpeg_start_decompress(&cinfo);
    *width = cinfo.output_width;
    *height = cinfo.output_height;
    *data = (unsigned char *) malloc(cinfo.output_height * cinfo.output_width * cinfo.output_components);
    unsigned char *line_pointer;
    int i = 0;
    while (cinfo.output_scanline < cinfo.image_height) {
        line_pointer = *data + i * cinfo.output_width * cinfo.output_components;
        jpeg_read_scanlines(&cinfo, &line_pointer, 1); 
        i ++;
    }
    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
}

void write_jpeg(char *filename, unsigned char **data, int *width, int *height)
{
    FILE * outfile = fopen(filename, "wb");
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, outfile);
    cinfo.image_width = *width;
    cinfo.image_height = *height;
    cinfo.in_color_space = JCS_RGB;
    cinfo.input_components = 3;
    jpeg_set_defaults(&cinfo);
    jpeg_start_compress(&cinfo, TRUE);
    unsigned char *line_pointer;
    int i = 0;
    while (cinfo.next_scanline < cinfo.image_height) {
        line_pointer = *data + i * cinfo.image_width * cinfo.input_components;
        jpeg_write_scanlines(&cinfo, &line_pointer, 1); 
        i ++;
    }
    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);
}

void get_pixel_of(int x, int y, unsigned char *dest, unsigned char **data, int *width, int *height)
{
	if ((x >= *width) || (x < 0) || (y >= *height) || (y < 0))
	{
        dest[0] = 0;
        dest[1] = 0;
        dest[2] = 0;
		return;
	}
    unsigned char *pos;
    pos = *data + (y * *width + x) * 3;
    dest[0] = pos[0];
    dest[1] = pos[1];
    dest[2] = pos[2];
}

void set_pixel_of(int x, int y, unsigned char *dest, unsigned char **data, int *width, int *height)
{
	if ((x >= *width) || (x < 0) || (y >= *height) || (y < 0))
	{
		return;
	}
    unsigned char *pos;
    pos = *data + (y * *width + x) * 3;
    pos[0] = dest[0];
    pos[1] = dest[1];
    pos[2] = dest[2];
}




使用libjpeg处理图像(libjpeg的使用压缩与解压缩jpg格式)
2009-05-04 16:21

标题:利用libjpeg处理图像
作者:赵新国
Email:zhao3728@sina.com

关键字: jpeg, 图像压缩

摘要:文章介绍了采用libjpeg处理图像的方法

前一段时间做了一个项目,项目中有一部分是关于图像采集的,相关硬件有:高速数字相机(我们采用Basler A312f),工控机,服务器。其中相机通过1394视频线连接到工控机的1394视频卡上,工控机与服务器通过百兆网连接。具体工作流程为:工控机控制相机采集图像,帧率一般为40HZ左右,采集的图像为位图数据,需要自己在程序中封装为bmp格式,然后压缩成jpg格式,压缩后的图像一方面保存到本地硬盘,同时要传输到服务器上。

  本文只介绍jpeg压缩的相关内容,刚开始我贪图省事,采用微软 的GDI Plus提供的功能,很是方便,先获取jpg图像的编码,然后根据图像的位图数据创建一个Bitmap类的对象,再保存图像为jpg格式就行了。但是我对GDI+还是很信任,总感觉不踏实(没有理由的),我们的系统一旦安装就要长期运行,我就是担心长期运行一段时间后GDI+会出问题,结果也证实了我的担心,我们实际使用的10套系统中有一套,连续运行3-5天后,GDI+就会崩溃,于是我决心采用IJG JPEG Library。您可以到www.ijg.org网站下载libjpeg的源码, IJG JPEG Library就是jpeg压缩库,是以源码的形式提供给软件开发人员的,当然在软件包里也有编译好的库文件,我们这里就只用到其中的libjpeg.lib,jconfig.h,jmorecfg.h,jpeglib.h这几个文件,下面我就介绍一下怎样在自己的程序里嵌入图像压缩功能。

  一、建立编译环境

  所谓建立编译环境,其实非常简单,就是把上面提到的4个文件拷贝到你的项目文件夹下,把libjpeg.lib添加到你的项目中,然后在你完成压缩功能的那个文件里加入#include "jpeglib.h",需要注意的是,libjpeg.lib是用c语言开发的,如果要用在你的C++程序里,需要用到extern "C",如下:

// TestLibjpeg.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "memory.h"
extern "C" {
#include "jpeglib.h"
}

  二、压缩步骤

  1、申请并初始化jpeg压缩对象,同时要指定错误处理器

struct jpeg_compress_struct jcs;

// 声明错误处理器,并赋值给jcs.err域
   struct jpeg_error_mgr jem;
   jcs.err = jpeg_std_error(&jem);

   jpeg_create_compress(&jcs);

  2、指定压缩后的图像所存放的目标文件,注意,目标文件应以二进制模式打开

f=fopen("03.jpg","wb");
   if (f==NULL)
   {
   delete [] data;
   delete [] pDataConv;
   return 0;
   }
   jpeg_stdio_dest(&jcs, f);

  3、设置压缩参数,主要参数有图像宽、高、色彩通道数(1:索引图像,3:其他),色彩空间(JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像),压缩质量等,如下:

   jcs.image_width = nWidth;    // 为图的宽和高,单位为像素
   jcs.image_height = nHeight;
   jcs.input_components = 1;   // 在此为1,表示灰度图, 如果是彩色位图,则为3
   jcs.in_color_space = JCS_GRAYSCALE; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像

   jpeg_set_defaults(&jcs);
jpeg_set_quality (&jcs, 80, true);

需要注意的是,jpeg_set_defaults函数一定要等设置好图像宽、高、色彩通道数计色彩空间四个参数后才能调用,因为这个函数要用到这四个值,调用jpeg_set_defaults函数后,jpeglib库采用默认的设置对图像进行压缩,如果需要改变设置,如压缩质量,调用这个函数后,可以调用其它设置函数,如jpeg_set_quality函数。其实图像压缩时有好多参数可以设置,但大部分我们都用不着设置,只需调用jpeg_set_defaults函数值为默认值即可。

  4、上面的工作准备完成后,就可以压缩了,压缩过程非常简单,首先调用jpeg_start_compress,然后可以对每一行进行压缩,也可以对若干行进行压缩,甚至可以对整个的图像进行一次压缩,压缩完成后,记得要调用jpeg_finish_compress函数,如下:

   jpeg_start_compress(&jcs, TRUE);

   JSAMPROW row_pointer[1];   // 一行位图
   int row_stride;      // 每一行的字节数

row_stride = jcs.image_width; // 如果不是索引图,此处需要乘以3

   // 对每一行进行压缩
   while (jcs.next_scanline < jcs.image_height) {
        row_pointer[0] = & pDataConv[jcs.next_scanline * row_stride];
        jpeg_write_scanlines(&jcs, row_pointer, 1);
   }

   jpeg_finish_compress(&jcs);

  5、最后就是释放压缩工作过程中所申请的资源了,主要就是jpeg压缩对象,由于在本例中我是直接用的局部变量,所以只需调用jpeg_destroy_compress这个函数即可,如下:

jpeg_destroy_compress(&jcs);

  三、解压缩步骤
  解压缩步骤与压缩步骤非常相似,只是解压缩对象为jpeg_decompress_struct类型,步骤如下:
  1、声明并初始化解压缩对象,同时制定错误信息管理器
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;

cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
  2、打开jpg图像文件,并指定为解压缩对象的源文件
FILE *f = fopen(strSourceFileName,"rb");
if (f==NULL)
{
   printf("Open file error!\n");
   return;
}
//
jpeg_stdio_src(&cinfo, f);
  3、读取图像信息
jpeg_read_header(&cinfo, TRUE);
  4、根据图像信息申请一个图像缓冲区
data = new BYTE cinfo.image_width*cinfo.image_height*cinfo.num_components];
  5、开始解压缩
jpeg_start_decompress(&cinfo);

JSAMPROW row_pointer[1];
while (cinfo.output_scanline < cinfo.output_height)
{
   row_pointer[0] = &data[(cinfo.output_height - cinfo.output_scanline-1)*cinfo.image_width*cinfo.num_components];
   jpeg_read_scanlines(&cinfo,row_pointer ,
      1);
}
jpeg_finish_decompress(&cinfo);
  6、释放资源
jpeg_destroy_decompress(&cinfo);

fclose(f);

  好了,利用IJG JPEG Library进行图像压缩就介绍到这里,希望对大家有所帮助,实例代码已经实现了图像的压缩和解压缩的全部功能,命令格式为:“TestLibjpeg.exe j|j24|b 源文件名 目标文件名”,其中,j选项将源文件压缩为jpg格式,不改变色彩模式,j24选项将源文件压缩为24为jpg格式,b选项将源文件解压缩为bmp格式,该实例并没有提供文件有效性的验证,如果要引入自己的代码,请自己实现文件有效性的验证。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值