C实现jpg转换为BMP 附源文件

基本思路:

      利用libjpeg库实现对jpg文件的解压缩,并将数据按bmp(从下到上,从左到右,BGR)存储保存)。

注意事项:

              1:bmp数据存储时是按照BGR顺序

           2:biHeight为正数时表示倒向的位图,读取的顺序为(从左->右,从下->上)

           3:Windows在进行行扫描的时候最小的单位为4个字节,所以当每行字节数不为4的正数倍时要对字节数进行调整。缺省是每行补0

           4:图像位图头信息中的高宽是实际图像的像素点的个数,与存储时需要调整对其数据使其满足4字节的倍数无关

实验内容:

步骤一:利用libjpeg库实现对jpg文件的解压缩并提取数据

	FILE *fJpeg;//目标jpeg文件的句柄
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);//声明并初始化解压缩对象
 	row_stride = cinfo.output_width * cinfo.output_components; //计算每行所需的空间,字节为单位
         while (cinfo.output_scanline < cinfo.output_height)
        {
            int line=cinfo.output_scanline;//当前行数
 
              (void) jpeg_read_scanlines(&cinfo, &jpgbuf, 1);//执行该操作读取第line行数据,cinfo.output_scanline将加一,指向下一个要扫描的行
 
              for(int i=0;i< cinfo.output_width;i++)//循环将存储在jpgbuf缓存区的数据放入data中
                      {      
                              data[line*row_stride+i*cinfo.output_components+0]=jpgbuf[i*3];
                              data[line*row_stride+i*cinfo.output_components+1]=jpgbuf[i*3+1];
                              data[line*row_stride+i*cinfo.output_components+2]=jpgbuf[i*3+2];
                       }
 
        }
         fJpeg=fopen(JpegName,"rb");//二进制模式读取jpeg文件
          jpeg_stdio_src(&cinfo, fJpeg);//指定解压对象的源文件
          jpeg_read_header(&cinfo, TRUE);//读取文件信息,将图像的缺省的信息填充到cinfo结构中比便程序使用
          jpeg_start_decompress(&cinfo);//开始接压缩
          data=(unsigned char *)malloc(cinfo.output_width* cinfo.output_components*cinfo.output_width);//动态分配数据存储内存
          memset(data,0,cinfo.output_width*cinfo.output_width*cinfo.output_components);//设置图像数据初值为0
        jpgbuf = (unsigned char *) malloc(cinfo.output_width *cinfo.output_components);//动态分配缓存内存
          memset(jpgbuf,0,cinfo.output_width*cinfo.output_components);//为缓存内存设置初值

步骤二:对将数据写入bmp文件中(必须按bmp文件存储数据的顺序进行存储)

 //填充位图信息头
        	infoheader.biSize=sizeof(infoheader);//位图信息头结构的长度,为40
       	infoheader.biBitCount=24;//设置为真彩图
        	infoheader.biHeight=cinfo.image_height;
        	infoheader.biWidth=cinfo.image_width;
        	infoheader.biCompression=BI_RGB;//一般默认为BI_RGB格式表示不压缩
        	infoheader.biPlanes=1;//表示不用考虑
        	infoheader.biXPelsPerMeter=0;
        	infoheader.biYPelsPerMeter=0;
        	infoheader.biClrUsed=0;//在MSDN中队RGB位图定义可知默认值为0
 
//将文件 头和位图信息头写入文件中
        	fNewBmp=fopen(NewBmpName,"wb");//二进制写的形式打开文件
        	if(!fNewBmp)
        	{
              cout<<"cannot open the NewBmpFile"<>2)<<2;//调整没行的字节数,使其是4的倍数
#ifdef DEBUG__
        	cout<<"((infoheader.biWidth*3+3)>>2)<<2 IS "<<(((infoheader.biWidth*3+3)>>2)<<2)<
 

 源文件:

void JpegToBmp( char *JpegName,char * NewBmpName)//将读取jpeg中的数据并保存为BMP格式的文件,生成的都是24位真彩图,不需要调色板
{
       
          FILE *fNewBmp;//存储生成的Bmp文件的句柄
        	FILE *fJpeg;//目标jpeg文件的句柄
        	unsigned char *data;   //存放解压后的数据
        	unsigned char *jpgbuf;      //存放解压后一行图像数据
        	BITMAPFILEHEADER header;//存储文件头
        	memset(&header, 0, sizeof(header));//文件头赋初始值
        	BITMAPINFOHEADER infoheader;//位图信息头
        	memset(&infoheader, 0, sizeof(infoheader));//赋初始值
 
        	int row_stride;        //定义每行的字节数
        	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
        cinfo.err = jpeg_std_error(&jerr);
        jpeg_create_decompress(&cinfo);//声明并初始化解压缩对象
 
        	fJpeg=fopen(JpegName,"rb");//二进制模式读取jpeg文件
       
        if(fJpeg==NULL) //二进制模式读取
        {
              printf("error: cannot open  the file\n");
              return ;
        }//打开jpeg图片
 
        jpeg_stdio_src(&cinfo, fJpeg);//指定解压对象的源文件
        jpeg_read_header(&cinfo, TRUE);//读取文件信息,将图像的缺省的信息填充到cinfo结构中比便程序使用
        jpeg_start_decompress(&cinfo);//开始接压缩
 
        data=(unsigned char *)malloc(cinfo.output_width* cinfo.output_components*cinfo.output_width);//动态分配数据存储内存
        memset(data,0,cinfo.output_width*cinfo.output_width*cinfo.output_components);//设置图像数据初值为0
       jpgbuf = (unsigned char *) malloc(cinfo.output_width *cinfo.output_components);//动态分配缓存内存
        memset(jpgbuf,0,cinfo.output_width*cinfo.output_components);//为缓存内存设置初值
 
        row_stride = cinfo.output_width * cinfo.output_components; //计算每行所需的空间,字节为单位
        while (cinfo.output_scanline < cinfo.output_height)
        {
              int line=cinfo.output_scanline;//当前行数
 
              (void) jpeg_read_scanlines(&cinfo, &jpgbuf, 1);//执行该操作读取第line行数据,cinfo.output_scanline将加一,指向下一个要扫描的行
 
              for(int i=0;i< cinfo.output_width;i++)//循环将存储在jpgbuf缓存区的数据放入data中
                      {      
                              data[line*row_stride+i*cinfo.output_components+0]=jpgbuf[i*3];
                              data[line*row_stride+i*cinfo.output_components+1]=jpgbuf[i*3+1];
                              data[line*row_stride+i*cinfo.output_components+2]=jpgbuf[i*3+2];
 #ifdef SHOWDATA__
        printf("(%d,%d,%d),(%d,%d)",jpgbuf[i*3],jpgbuf[i*3+1],jpgbuf[i*3+2],line,i);//打印图像数据
 #endif  
                       }
 
        }
       
        free(jpgbuf);
//填充文件头信息
        	header.bfType= 0x4D42;//设置为“BM”
        	header.bfSize=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+cinfo.output_width* cinfo.output_components*cinfo.output_width ;
        header.bfOffBits=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
 
#ifdef DEBUG__
 
        cout<<"header.bfType IS "<<(char)header.bfType<>2)<<2;//调整没行的字节数,使其是4的倍数
#ifdef DEBUG__
        cout<<"((infoheader.biWidth*3+3)>>2)<<2 IS "<<(((infoheader.biWidth*3+3)>>2)<<2)<


参考:

[置顶] 应用libjpeg提取jpeg质量因子          

C 实现BMP 转换为JPG 附源代码


 

你可能感兴趣的:(图像处理,jpeg,components,c,header,存储,struct,file)