bmp转jpeg文件

这篇博客详细介绍了如何使用C语言将BMP图像文件转换为JPEG格式。通过定义函数`savejpeg`和`yuv420sp_to_jpeg`,实现了从BMP到JPEG的压缩过程,涉及到了JPEG的压缩结构、错误处理、图像行的处理以及色彩空间转换等步骤。
摘要由CSDN通过智能技术生成
//===================================================================================
//function:       jpeg压缩
//input:          1:生成的文件名,2:bmp的指针,3:位图宽度,4:位图高度,5:颜色深度
//return:         int
//description:    bmp的像素格式为(RGB)
//===================================================================================
int savejpeg(char *filename, unsigned char *bits, int width, int height, int depth)
{
	struct jpeg_compress_struct jcinfo;  //申请jpeg压缩对象
	struct jpeg_error_mgr jerr;
	FILE * outfile;                 //target file 
	JSAMPROW row_pointer[1];        //pointer to JSAMPLE row[s] 一行位图 
	int     row_stride;             //每一行的字节数 
	jcinfo.err = jpeg_std_error(&jerr);   //指定错误处理器
	jpeg_create_compress(&jcinfo);      //初始化jpeg压缩对象

    //指定压缩后的图像所存放的目标文件,注意,目标文件应以二进制模式打开
	if ((outfile = fopen(filename, "wb")) == NULL)
	{
		fprintf(stderr, "can't open %s/n", filename);
		return -1;
	}
	jpeg_stdio_dest(&jcinfo, outfile);   //指定压缩后的图像所存放的目标文件
	jcinfo.image_width = width;      // 为图的宽和高,单位为像素
	jcinfo.image_height = height;
	jcinfo.input_components = 3;         // 在此为3,表示彩色位图, 如果是灰度图,则为1
	jcinfo.in_color_space = JCS_RGB;         //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像
	/*
	需要注意的是,jpeg_set_defaults函数一定要等设置好图像宽、高、色彩通道数计色彩空间四个参数后才能调用,因为这个函数要用到这四个值,调用jpeg_set_defaults函数后,jpeglib 库采用默认的设置对图像进行压缩
	如果需要改变设置,如压缩质量,调用这个函数后,可以调用其它设置函数,如jpeg_set_quality函数。其实图像压缩时有好多参数可以设置
	但大部分我们都用不着设置,只需调用jpeg_set_defaults函数值为默认值即可
	*/
	jpeg_set_defaults(&jcinfo);
	jpeg_set_quality(&jcinfo, JPEG_QUALITY, TRUE );//limit to baseline-JPEG values
	/*
	首先调用jpeg_start_compress,然后可以对每一行进行压缩,也可以对若干行进行压缩,甚至可以对整个的图像进行一次压缩,压缩完成后,记得要调用jpeg_finish_compress函数
	*/
	jpeg_start_compress(&jcinfo, TRUE);

	row_stride = width * depth; // JSAMPLEs per row in image_buffer(如果是索引图则不需要乘以3) 
	//对每一行进行压缩
	while (jcinfo.next_scanline < jcinfo.image_height) 
	{
		//这里我做过修改,由于jpg文件的图像是倒的,所以改了一下读的顺序
		//这是原代码:
		//row_pointer[0] = & bits[jcinfo.next_scanline * row_stride];
		row_pointer[0] = & bits[(jcinfo.image_height - jcinfo.next_scanline - 1) * row_stride];
		(void) jpeg_write_scanlines(&jcinfo, row_pointer, 1);
	}
	jpeg_finish_compress(&jcinfo);
	fclose(outfile);
	jpeg_destroy_compress(&jcinfo);
	return 0;
}
int yuv420sp_to_jpeg(const char * filename, char* pdata,int image_width,int image_height, int quality)  
{     
    struct jpeg_compress_struct cinfo;    
    struct jpeg_error_mgr jerr;    
    cinfo.err = jpeg_std_error(&jerr);    
    jpeg_create_compress(&cinfo);    
  
    FILE * outfile;    // target file    
    if ((outfile = fopen(filename, "wb")) == NULL) {    
        fprintf(stderr, "can't open %s\n", filename);    
        return(1);    
    }    
    jpeg_stdio_dest(&cinfo, outfile);    
  
    cinfo.image_width = image_width;  // image width and height, in pixels    
    cinfo.image_height = image_height;    
    cinfo.input_components = 3;    // # of color components per pixel    
    cinfo.in_color_space = JCS_YCbCr;  //colorspace of input image    
    jpeg_set_defaults(&cinfo);    
    jpeg_set_quality(&cinfo, quality, TRUE );    
  
    //    
    //  cinfo.raw_data_in = TRUE;    
    cinfo.jpeg_color_space = JCS_YCbCr;    
    cinfo.comp_info[0].h_samp_factor = 2;    
    cinfo.comp_info[0].v_samp_factor = 2;    
    /    
  
    jpeg_start_compress(&cinfo, TRUE);    
  
    JSAMPROW row_pointer[1];  
  
    unsigned char *yuvbuf;  
    if((yuvbuf=(unsigned char *)malloc(image_width*3))!=NULL)  
        memset(yuvbuf,0,image_width*3);  
  
    char *ybase,*ubase;  
    ybase=pdata;  
    ubase=pdata+image_width*image_height;    
    int j=0;  
    while (cinfo.next_scanline < cinfo.image_height)   
    {  
        int idx=0;  
        for(int i=0;i<image_width;i++)  
        {   
            yuvbuf[idx++]=ybase[i + j * image_width];  
            yuvbuf[idx++]=ubase[j/2 * image_width+(i/2)*2];  
            yuvbuf[idx++]=ubase[j/2 * image_width+(i/2)*2+1];      
        }  
        row_pointer[0] = yuvbuf;  
        jpeg_write_scanlines(&cinfo, row_pointer, 1);  
        j++;  
    }  
    jpeg_finish_compress(&cinfo);    
    jpeg_destroy_compress(&cinfo);    
    fclose(outfile);    
    return 0;    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值