此篇博客参考于:https://blog.csdn.net/lzhq28/article/details/7775957
目录
一、建立编译环境
二、bmp转jpg压缩步骤
步骤一:读取bmp文件,并将数据调整为从从上到下、从左到右、RGB顺序
1.申请并初始化jpeg压缩对象,同时要指定错误处理器
2.读取bmp文件头和位图信息
3.读取数据并调整数据的存储顺序
步骤二:对步骤一得到的数据进行jpeg压缩,将调用libjpeg库
4.对得到的数据进行设置
5.写入数据
6.释放压缩过程申请资源
完整代码
编译libjpeg库
Jpeg库下载地址:http://www.ijg.org/files/
下载好先解压,打开终端,进入解压好的目录。
【./configure --enable -shared --enable-static】
【make】
【make install】
在完成转换功能的文件中加入#include
struct jpeg_compress_struct cinfo;
// 声明错误处理器,并赋值给jcs.err域
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
FILE *fd,*outfile;
BITMAPFILEHEADER header;//存储文件头
memset(&header, 0, sizeof(header));
BITMAPINFOHEADER infoheader;//位图信息头
memset(&infoheader, 0, sizeof(infoheader));
long m_iImageWidth=0;
long m_iImageHeight=0;
WORD m_iBitsPerPixel=0;
WORD m_iBytesPerPixel=0;
int m_iLineByteCnt=0;//每行的字节数
int m_iImageDataSize=0;//图像数据的总字节数
// Read bmp image data
fd = fopen(bmp_file, "rb");
if(!fd)
{
printf("ERROR1: Can not open the image.\n");
return -1;
}
fread(&header,sizeof(unsigned char),sizeof(header),fd);//读取头文件
fread(&infoheader,sizeof(unsigned char),sizeof(infoheader),fd);//读取位图信息头
m_iImageWidth = infoheader.biWidth;
m_iImageHeight = infoheader.biHeight;
m_iBitsPerPixel = infoheader.biBitCount;
m_iBytesPerPixel = m_iBitsPerPixel/8;//每个像素点所占的字节数
m_iLineByteCnt = ((m_iImageWidth * m_iBytesPerPixel+3)>>2)<<2;//调整每行的字节数为4的整数倍
m_iImageDataSize = m_iLineByteCnt * m_iImageHeight;
data = (unsigned char*)malloc(m_iImageDataSize);//分配总空间存储图像数据
if(data == NULL)
{
printf("malloc error\r\n");
return 0;
}
Line_data = (unsigned char*)malloc(m_iLineByteCnt);//每行图像数据所需空间
if(Line_data == NULL)
{
printf("malloc error\r\n");
return 0;
}
if((3 == m_iBytesPerPixel)&&(m_iImageHeight)>0)
{
for(int scanline = 0;scanline < m_iImageHeight;scanline++)
{
ret = fread(Line_data, sizeof(unsigned char),m_iLineByteCnt,fd);
if(ret == 0)
{
if(ferror(fd))
{
printf("\nERROR2: Can not read the pixel data.\n");
free(Line_data);
fclose(fd);
return -1;
}
}
for(int tmpCol = 0;tmpColRGB,从下到上->从上到下)
}
}
需要注意的是,jpeg_set_defaults函数一定要等设置好图像宽、高、色彩通道数及色彩空间四个参数后才能调用,因为这个函数要用到这四个值,调用jpeg_set_defaults函数后,jpeglib库采用默认的设置对图像进行压缩,如果需要改变设置,如压缩质量,调用这个函数后,可以调用其它设置函数,如jpeg_set_quality函数。其实图像压缩时有好多参数可以设置,但大部分我们都用不着设置,只需调用jpeg_set_defaults函数值为默认值即可。
jpeg_create_compress(&cinfo);//初始化jpeg压缩对象
if ((outfile = fopen(jeg_file, "wb")) == NULL)
{
fprintf(stderr, "can't open %s\n", jeg_file);
return -1;
}
jpeg_stdio_dest(&cinfo, outfile); //指定压缩后的图像所存放的目标文件 ,二进制打开
cinfo.image_width = m_iImageWidth; //宽
cinfo.image_height = m_iImageHeight;//高
cinfo.input_components = depth; // 在此为3,表示彩色位图, 如果是灰度图,则为1
cinfo.in_color_space = JCS_RGB; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像
jpeg_set_defaults(&cinfo); // 调用jpeg_set_defaults函数后,jpeglib库采用默认的设置对图像进行压缩
jpeg_set_quality(&cinfo, JPEG_QUALITY, TRUE ); // jpeglib库采用默认的设置对图像进行压缩
jpeg_start_compress(&cinfo, TRUE);
row_pointer = malloc(m_iImageDataSize);
while (cinfo.next_scanline < cinfo.image_height)
{
for(int j=0;j< m_iLineByteCnt;j++)
{
Line_data[j]=data[cinfo.next_scanline*m_iLineByteCnt+j];
}
row_pointer[0]=Line_data;
jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
主要就是jpeg压缩对象及动态分配的数组,在这只介绍jpeg对象的释放,只需调用jpeg_destroy_compress这个函数即可,如下:
jpeg_destroy_compress(&cinfo);
/*********************************************************************************
* Copyright: (C) 2019 zyjin
* All rights reserved.
*
* Filename: main.c
* Description: bmp to jpg
*
* Created by zyjin on 19-7-13.
*
* Version: 1.0.0(2019年7月13日)
* Author: zyjin
* ChangeLog: 1, Release initial version on "2019年7月13日 19时18分"
*
********************************************************************************/
#include "bmptojpg.h"
int main(int argc,char *argv[])
{
int JPEG_QUALITY = 100;
const char *bmp_file = "/root/CLionProjects/BMPTOJPG/test.bmp";
const char *jpg_file = "/root/CLionProjects/BMPTOJPG/test2.jpg";
BmptoJpg(bmp_file,jpg_file, JPEG_QUALITY);
printf("BMP To JPG done\r\n");
return 1;
}
/*********************************************************************************
* Copyright: (C) 2019 zyjin
* All rights reserved.
*
* Filename: bmptojpg.c
* Description: bmp to jpg
*
* Created by zyjin on 19-7-13.
*
* Version: 1.0.0(2019年7月13日)
* Author: zyjin
* ChangeLog: 1, Release initial version on "2019年7月13日 18时55分"
*
********************************************************************************/
#include "bmptojpg.h"
#define a
#ifdef a
int BmptoJpg(const char *bmp_file, const char *jeg_file, int JPEG_QUALITY)
{
FILE *fd,*outfile;
int ret;
int i = 0;
unsigned char *data,*Line_data;
int depth = 3;
JSAMPROW * row_pointer;
//long rgb_index = 0;
struct jpeg_compress_struct cinfo;//申请并初始化jpeg压缩对象,同时要指定错误处理器
struct jpeg_error_mgr jerr;// 声明错误处理器,并赋值给jcs.err域
cinfo.err = jpeg_std_error(&jerr);
BITMAPFILEHEADER header;//存储文件头
memset(&header, 0, sizeof(header));
BITMAPINFOHEADER infoheader;//位图信息头
memset(&infoheader, 0, sizeof(infoheader));
long m_iImageWidth=0;
long m_iImageHeight=0;
WORD m_iBitsPerPixel=0;
WORD m_iBytesPerPixel=0;
int m_iLineByteCnt=0;//每行的字节数
int m_iImageDataSize=0;//图像数据的总字节数
// Read bmp image data
fd = fopen(bmp_file, "rb");
if(!fd)
{
printf("ERROR1: Can not open the image.\n");
return -1;
}
fread(&header,sizeof(unsigned char),sizeof(header),fd);//读取头文件
fread(&infoheader,sizeof(unsigned char),sizeof(infoheader),fd);//读取位图信息头
m_iImageWidth = infoheader.biWidth;
m_iImageHeight = infoheader.biHeight;
m_iBitsPerPixel = infoheader.biBitCount;
//printf("%d %d\r\n",sizeof(DWORD),sizeof(WORD));
//printf("%d %d\r\n",sizeof(header),sizeof(infoheader));
//printf("%ld %ld %d ",m_iImageWidth,m_iImageHeight,m_iBitsPerPixel);
m_iBytesPerPixel = m_iBitsPerPixel/8;//每个像素点所占的字节数
m_iLineByteCnt = (m_iImageWidth * m_iBytesPerPixel);
//m_iLineByteCnt = ((m_iImageWidth * m_iBytesPerPixel+3)>>2)<<2;//调整每行的字节数为4的整数倍
m_iImageDataSize = m_iLineByteCnt * m_iImageHeight;
data = (unsigned char*)malloc(m_iImageDataSize);
if(data == NULL)
{
printf("malloc error\r\n");
return 0;
}
Line_data = (unsigned char*)malloc(m_iLineByteCnt);
if(Line_data == NULL)
{
printf("malloc error\r\n");
return 0;
}
if((3 == m_iBytesPerPixel)&&(m_iImageHeight)>0)
{
for(int scanline = 0;scanline < m_iImageHeight;scanline++)
{
ret = fread(Line_data, sizeof(unsigned char),m_iLineByteCnt,fd);
if(ret == 0)
{
if(ferror(fd))
{
printf("\nERROR2: Can not read the pixel data.\n");
free(Line_data);
fclose(fd);
return -1;
}
}
for(int tmpCol = 0;tmpColRGB,从下到上->从上到下)
}
}
jpeg_create_compress(&cinfo);//初始化jpeg压缩对象
if ((outfile = fopen(jeg_file, "wb")) == NULL)
{
fprintf(stderr, "can't open %s\n", jeg_file);
return -1;
}
jpeg_stdio_dest(&cinfo, outfile); //指定压缩后的图像所存放的目标文件 ,二进制打开
cinfo.image_width = m_iImageWidth; //宽
cinfo.image_height = m_iImageHeight;//高
cinfo.input_components = depth; // 在此为3,表示彩色位图, 如果是灰度图,则为1
cinfo.in_color_space = JCS_RGB; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像
jpeg_set_defaults(&cinfo); // 调用jpeg_set_defaults函数后,jpeglib库采用默认的设置对图像进行压缩
jpeg_set_quality(&cinfo, JPEG_QUALITY, TRUE ); // jpeglib库采用默认的设置对图像进行压缩
jpeg_start_compress(&cinfo, TRUE);
//一次写入
row_pointer = malloc(m_iImageDataSize);
while (cinfo.next_scanline < cinfo.image_height)
{
for(int j=0;j< m_iLineByteCnt;j++)
{
Line_data[j]=data[cinfo.next_scanline*m_iLineByteCnt+j];
}
row_pointer[0]=Line_data;
jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
free(row_pointer);
free(data);
free(Line_data);
fclose(fd);
fclose(outfile);
return 0;
}
#endif
/*********************************************************************************
* Copyright: (C) 2019 zyjin
* All rights reserved.
*
* Filename: bmptojpg.h
* Description: bmp to jpg
*
* Created by zyjin on 19-7-13.
*
* Version: 1.0.0(2019年7月13日)
* Author: zyjin
* ChangeLog: 1, Release initial version on "2019年7月13日 18时45分30秒"
*
********************************************************************************/
#ifndef BMPTOJPG_BMPTOJPG_H
#define BMPTOJPG_BMPTOJPG_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DWORD unsigned int
#define WORD unsigned short
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
WORD bfReserved1;
WORD bfReserved2;
WORD bfSize;
WORD bbbb;
WORD bbba;
WORD bfOffBits;
} BITMAPFILEHEADER;// FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{
DWORD biSize;
DWORD biWidth;
DWORD biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
DWORD biXPelsPerMeter;
DWORD biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
int BmptoJpg(const char *bmp_file, const char *jeg_file, int JPEG_QUALITY);
#endif //BMPTOJPG_BMPTOJPG_H