• C++图片格式转换:BMP转JPEG


    C++方式将BMP格式转换为JPEG格式,依赖了一个第三方库,工程下载链接为:点击打开链接

    Bmp2Jpeg.h:

    #pragma once
    
    class CBmp2Jpeg
    {
    public:
    	CBmp2Jpeg();
    	~CBmp2Jpeg();
    
    public:
    	int Bmp2Jpeg(const char *bmp, const char *jpeg);
    
    private:
    	int SaveJpeg(const char *filename, unsigned char *bits, int width, int height, int depth);
    	int ReadBmp(const char *bmp, unsigned char **data,int &w, int &h, int &d);
    	void Bgra2Rgb(const unsigned char *src, int w, int h, int d, unsigned char *dst);
    	void InitFileHeader(void *pFile, void *fileHeader);
    	void InitInfoHeader(void *pFile, void *infoHeader);
    	void SaveBmp(void *fileHeader, void *infoHeader, int bitCount, unsigned char *data, const char *savename);
    private:
    	int	m_quality;	//它的大小决定jpg的质量好坏
    
    	enum{
    		JPEG_QUALITY = 100, 
    	};
    };
    
    
    

    Bmp2Jpeg.cpp:

    #include <iostream>
    #include<Windows.h>
    #include <fstream>
    //#include<stdlib.h>
    #include "Bmp2Jpeg.h"
    #include <vector>
    
    extern "C"
    {
    #include "jpeglib.h"
    };
    
    #pragma comment(lib,"libjpeg.lib")
    
    using namespace std;
    
    #pragma pack(2)  
    
    struct bmp_fileheader   //文件头,长度为14Byte固定  
    {  
    	unsigned short bfType;  
    	unsigned long bfSize;  
    	unsigned short bfReserved1;  
    	unsigned short bfReserved2;  
    	unsigned long bfOffBits;  
    };  
    
    struct bmp_infoheader  //文件信息头,长度为40Byte固定  
    {  
    	unsigned long biSize;  
    	unsigned long biWidth;  
    	unsigned long biHeight;  
    	unsigned short biPlanes;  
    	unsigned short biBitCount;  
    	unsigned long biCompression;  
    	unsigned long biSizeImage;  
    	unsigned long biXPelsPerMeter;  
    	unsigned long biYPelsPerMeter;  
    	unsigned long biClrUsed;  
    	unsigned long biClrImportant;  
    }; 
    
    struct RGBPallete
    {
    	unsigned char b;
    	unsigned char g;
    	unsigned char r;
    	unsigned char alpha;
    };
    
    CBmp2Jpeg::CBmp2Jpeg() :
    	m_quality(JPEG_QUALITY)
    {
    
    }
    
    CBmp2Jpeg::~CBmp2Jpeg()
    {
    
    }
    /*===================================================================================
    function:       jpeg压缩
    input:          1:生成的文件名,2:bmp的指针,3:位图宽度,4:位图高度,5:颜色深度
    return:         int
    description:    bmp的像素格式为(RGB)
    ===================================================================================*/
    int CBmp2Jpeg::SaveJpeg(const char *filename, unsigned char *bits, int width, int height, int depth)
    {
    	FILE * outfile;                 /* target file */
    	fopen_s(&outfile, filename, "wb");
    	if (outfile == NULL) {
    		return -1;
    	}
    
    	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;      /* image width and height, in pixels */
    	cinfo.image_height = height;
    	cinfo.input_components = 3;         /* # of color components per pixel */
    	cinfo.in_color_space = JCS_RGB;         /* colorspace of input image */
    
    	jpeg_set_defaults(&cinfo);
    	jpeg_set_quality(&cinfo, m_quality, TRUE /* limit to baseline-JPEG values */);
    
    	jpeg_start_compress(&cinfo, TRUE);
    
    	JSAMPROW row_pointer[1];        /* pointer to JSAMPLE row[s] */
    	int     row_stride;             /* physical row width in image buffer */
    	row_stride = width * depth; /* JSAMPLEs per row in image_buffer */
    
    	while (cinfo.next_scanline < cinfo.image_height) {
    		//这里我做过修改,由于jpg文件的图像是倒的,所以改了一下读的顺序
    		//row_pointer[0] = & bits[cinfo.next_scanline * row_stride];
    		row_pointer[0] = & bits[(cinfo.image_height - cinfo.next_scanline - 1) * row_stride];
    		(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
    	}
    
    	jpeg_finish_compress(&cinfo);
    	fclose(outfile);
    
    	jpeg_destroy_compress(&cinfo);
    	return 0;
    }
    
    void CBmp2Jpeg::InitFileHeader(void *pFile, void *fileHeader)
    {
    	bmp_fileheader *pfileHeader = (bmp_fileheader *)fileHeader;
    	fstream *filein = (fstream *)pFile;
    	//初始化文件头
    	pfileHeader->bfType = 0;
    	pfileHeader->bfSize=0;
    	pfileHeader->bfReserved1=0;
    	pfileHeader->bfReserved2=0;
    	pfileHeader->bfOffBits=0;
    	//读位图文件头并输出相应信息
    	filein->read((char*)fileHeader, sizeof(bmp_fileheader));
    }
    
    void CBmp2Jpeg::InitInfoHeader(void *pFile, void *infoHeader)
    {
    	bmp_infoheader *pinfoHeader = (bmp_infoheader *)infoHeader;
    	fstream *filein = (fstream *)pFile;
    	//初始化信息头
    	pinfoHeader->biSize=0;
    	pinfoHeader->biWidth=0;
    	pinfoHeader->biHeight=0;
    	pinfoHeader->biPlanes=0;
    	pinfoHeader->biBitCount=0;
    	pinfoHeader->biCompression=0;
    	pinfoHeader->biSizeImage=0;
    	pinfoHeader->biXPelsPerMeter=0;
    	pinfoHeader->biYPelsPerMeter=0;
    	pinfoHeader->biClrUsed=0;
    	pinfoHeader->biClrImportant=0;
    
    	//读位图信息头并输出相应信息
    	filein->read((char*)infoHeader, sizeof(bmp_infoheader));
    }
    
    void CBmp2Jpeg::SaveBmp(void *fileHeader, void *infoHeader, int bitCount, unsigned char *data, const char *savename)
    {
    	bmp_fileheader *pfileHeader = (bmp_fileheader *)fileHeader;
    	bmp_infoheader *pinfoHeader = (bmp_infoheader *)infoHeader;
    	//写入文件
    	std::string str(savename);
    	str.append(".bmp");
    	fstream fileout;
    	fileout.open(str, std::ios::binary | std::ios::out);
    	fileout.write((char*)fileHeader, sizeof(bmp_fileheader));
    	fileout.write((char*)infoHeader, sizeof(bmp_infoheader));
    	fileout.write((char*)data, sizeof(unsigned char) * pfileHeader->bfSize - pfileHeader->bfOffBits);
    	
    	fileout.close();
    }
    
    //读取并将图片另存为一个新文件, 转换成rgb格式
    int CBmp2Jpeg::ReadBmp(const char *bmp, unsigned char **data, int &w, int &h, int &d)
    {
    	//打开位图文件
    	fstream filein;
    	filein.open(bmp, std::ios::binary | std::ios::in);
    	if(!filein.is_open())
    	{
    		char clog[256] = {0};
    		sprintf_s(clog, sizeof(clog), "bmp转jpeg,找不到 %s
    ", bmp);
    		OutputDebugStringA(clog);
    		return -1;
    	}
    
    	//定义变量
    	long width=0;
    	long height=0;
    	long bitCount=0;
    
    	bmp_fileheader  fileHeader;
    	bmp_infoheader  infoHeader;
    
    	InitFileHeader(&filein, &fileHeader);
    
    	if (fileHeader.bfType != 0x4d42)
    	{
    		filein.close();
    		return -1;
    	}
    
    	InitInfoHeader(&filein, &infoHeader);
    
    	width=infoHeader.biWidth;
    	height=infoHeader.biHeight;
    	bitCount=infoHeader.biBitCount;
    	
    	int bitPerLine= ((width * bitCount + 31)  >> 5) << 2;
    	int imgSize = abs(height * bitPerLine);
    	int imgReal = fileHeader.bfSize - fileHeader.bfOffBits;
    	if(imgSize != imgReal)
    	{
    		char clog[256] = {0};
    		sprintf_s(clog, sizeof(clog), "bmp转jpeg,图像尺寸不对
    ");
    		OutputDebugStringA(clog);
    		filein.close();
    		return -1;
    	}
    
    	if (bitCount == 8)
    	{
    		std::vector<RGBPallete> palletes;
    		unsigned char buf[256 * sizeof(RGBPallete)];
    
    		filein.read((char*)buf, 256 * sizeof(RGBPallete));
    
    		for (int i = 0; i < 256; i++)
    		{
    			RGBPallete pallete;
    			memcpy(&pallete, buf + i * sizeof(RGBPallete), sizeof(RGBPallete));
    
    			palletes.push_back(pallete);
    		}
    
    		unsigned char* pTemp = new unsigned char[imgSize];
    		filein.read((char*)pTemp, imgSize);
    
    		*data = new unsigned char[width * abs(height) * 4];
    		for (int i = 0; i < imgSize; i++)
    		{
    			RGBPallete& p = palletes[pTemp[i]];
    			memcpy((*data) + i * sizeof(RGBPallete), &p, sizeof(RGBPallete));
    		}
    
    		bitCount = 32;
    		delete pTemp;
    	}
    	else if (bitCount == 24 || bitCount == 32)
    	{
    		*data = new unsigned char[imgSize];
    		filein.read((char*)(*data), imgSize);
    		filein.close();
    	}
    	else
    	{
    		filein.close();
    		return -1;
    	}
    
    	w = width;
    	h = height;
    	d = bitCount;
    	
    	return 0;
    } 
    
    void CBmp2Jpeg::Bgra2Rgb(const unsigned char *src, int w, int h, int d, unsigned char *dst)
    {
    	unsigned char* pTempDst = dst;
    	for (int i = 0; i < abs(h); i++)
    	{
    		const unsigned char* pTempSrc = nullptr;
    		if (h > 0)
    		{
    			pTempSrc = src + w * i * d;
    		}
    		else
    		{
    			pTempSrc = src + w * abs( i  + h + 1 ) * d;
    		}
    
    		for (int j = 0; j < w; j++)
    		{
    			*(pTempDst) = *(pTempSrc + 2);
    			*(pTempDst + 1) = *(pTempSrc + 1);
    			*(pTempDst + 2) = *(pTempSrc);
    			pTempDst += 3;
    			pTempSrc += d;
    		}
    	}
    }
    
    
    int CBmp2Jpeg::Bmp2Jpeg(const char *bmp, const char *jpeg)
    {
    	unsigned char *brga = nullptr; //指向位图buffer的全局指针,window下像素格式: BGRA(4个字节)
    	int width = 0, height = 0, depth = 0;
    
    	if(ReadBmp(bmp, &brga,width, height, depth) < 0)
    	{
    		return -1;
    	}
    
    	unsigned char *rgb = new unsigned char[width * abs(height) * depth/8];
    	Bgra2Rgb(brga, width, height, depth/8, rgb);
    
    	int ret = SaveJpeg(jpeg, rgb, width, abs(height), 3);
    
    	delete [] brga;
    	delete [] rgb;
    	brga = nullptr;
    	rgb = nullptr;
    	return ret;
    }

    调用:

    #include <iostream>
    #include <stdio.h>
    #include "Bmp2Jpeg.h"
    using namespace std;
    int main()
    {
    	CBmp2Jpeg bmp;
    	bmp.Bmp2Jpeg("111_24.bmp", "lena.jpg");
    	cout<<"good job."<<endl;
    	cin.get();
    	return 0;
    }


  • 相关阅读:
    Python randrange() 函数
    200行Python代码实现2048
    select默认下拉箭头改变、option样式清除
    图片垂直居中
    去除select边框和三角-----appearance:none
    原生 js 实现点击按钮复制文本
    This dependency was not found: * !!vue-style-loader!css-loader?……解决方案
    vue项目启动时将localhost替换成指定ip地址
    安装cnpm
    vue 项目要使用的库
  • 原文地址:https://www.cnblogs.com/SunkingYang/p/11049160.html
Copyright © 2020-2023  润新知