C++图片格式转换:BMP转JPEG
生活随笔
收集整理的這篇文章主要介紹了
C++图片格式转换:BMP转JPEG
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
C++方式將BMP格式轉換為JPEG格式,依賴了一個第三方庫,工程下載鏈接為:點擊打開鏈接
Bmp2Jpeg.h:
#pragma onceclass 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\n", 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,圖像尺寸不對\n");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; }總結
以上是生活随笔為你收集整理的C++图片格式转换:BMP转JPEG的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信小程序8-云函数
- 下一篇: Day19-22 2021/10/13-