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

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

Bmp2Jpeg.h:

1#pragma once 2 3class CBmp2Jpeg 4{ 5public: 6 CBmp2Jpeg(); 7 ~CBmp2Jpeg(); 8 9public: 10 int Bmp2Jpeg(const char *bmp, const char *jpeg); 11 12private: 13 int SaveJpeg(const char *filename, unsigned char *bits, int width, int height, int depth); 14 int ReadBmp(const char *bmp, unsigned char **data,int &w, int &h, int &d); 15 void Bgra2Rgb(const unsigned char *src, int w, int h, int d, unsigned char *dst); 16 void InitFileHeader(void *pFile, void *fileHeader); 17 void InitInfoHeader(void *pFile, void *infoHeader); 18 void SaveBmp(void *fileHeader, void *infoHeader, int bitCount, unsigned char *data, const char *savename); 19private: 20 int m_quality; //它的大小决定jpg的质量好坏 21 22 enum{ 23 JPEG_QUALITY = 100, 24 }; 25}; 26 27

Bmp2Jpeg.cpp:

1#include <iostream> 2#include<Windows.h> 3#include <fstream> 4//#include<stdlib.h> 5#include "Bmp2Jpeg.h" 6#include <vector> 7 8extern "C" 9{ 10#include "jpeglib.h" 11}; 12 13#pragma comment(lib,"libjpeg.lib") 14 15using namespace std; 16 17#pragma pack(2) 18 19struct bmp_fileheader //文件头,长度为14Byte固定 20{ 21 unsigned short bfType; 22 unsigned long bfSize; 23 unsigned short bfReserved1; 24 unsigned short bfReserved2; 25 unsigned long bfOffBits; 26}; 27 28struct bmp_infoheader //文件信息头,长度为40Byte固定 29{ 30 unsigned long biSize; 31 unsigned long biWidth; 32 unsigned long biHeight; 33 unsigned short biPlanes; 34 unsigned short biBitCount; 35 unsigned long biCompression; 36 unsigned long biSizeImage; 37 unsigned long biXPelsPerMeter; 38 unsigned long biYPelsPerMeter; 39 unsigned long biClrUsed; 40 unsigned long biClrImportant; 41}; 42 43struct RGBPallete 44{ 45 unsigned char b; 46 unsigned char g; 47 unsigned char r; 48 unsigned char alpha; 49}; 50 51CBmp2Jpeg::CBmp2Jpeg() : 52 m_quality(JPEG_QUALITY) 53{ 54 55} 56 57CBmp2Jpeg::~CBmp2Jpeg() 58{ 59 60} 61/*=================================================================================== 62function: jpeg压缩 63input: 1:生成的文件名,2:bmp的指针,3:位图宽度,4:位图高度,5:颜色深度 64return: int 65description: bmp的像素格式为(RGB) 66===================================================================================*/ 67int CBmp2Jpeg::SaveJpeg(const char *filename, unsigned char *bits, int width, int height, int depth) 68{ 69 FILE * outfile; /* target file */ 70 fopen_s(&outfile, filename, "wb"); 71 if (outfile == NULL) { 72 return -1; 73 } 74 75 struct jpeg_compress_struct cinfo; 76 struct jpeg_error_mgr jerr; 77 78 cinfo.err = jpeg_std_error(&jerr); 79 jpeg_create_compress(&cinfo); 80 81 jpeg_stdio_dest(&cinfo, outfile); 82 83 cinfo.image_width = width; /* image width and height, in pixels */ 84 cinfo.image_height = height; 85 cinfo.input_components = 3; /* # of color components per pixel */ 86 cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ 87 88 jpeg_set_defaults(&cinfo); 89 jpeg_set_quality(&cinfo, m_quality, TRUE /* limit to baseline-JPEG values */); 90 91 jpeg_start_compress(&cinfo, TRUE); 92 93 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ 94 int row_stride; /* physical row width in image buffer */ 95 row_stride = width * depth; /* JSAMPLEs per row in image_buffer */ 96 97 while (cinfo.next_scanline < cinfo.image_height) { 98 //这里我做过修改,由于jpg文件的图像是倒的,所以改了一下读的顺序 99 //row_pointer[0] = & bits[cinfo.next_scanline * row_stride]; 100 row_pointer[0] = & bits[(cinfo.image_height - cinfo.next_scanline - 1) * row_stride]; 101 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); 102 } 103 104 jpeg_finish_compress(&cinfo); 105 fclose(outfile); 106 107 jpeg_destroy_compress(&cinfo); 108 return 0; 109} 110 111void CBmp2Jpeg::InitFileHeader(void *pFile, void *fileHeader) 112{ 113 bmp_fileheader *pfileHeader = (bmp_fileheader *)fileHeader; 114 fstream *filein = (fstream *)pFile; 115 //初始化文件头 116 pfileHeader->bfType = 0; 117 pfileHeader->bfSize=0; 118 pfileHeader->bfReserved1=0; 119 pfileHeader->bfReserved2=0; 120 pfileHeader->bfOffBits=0; 121 //读位图文件头并输出相应信息 122 filein->read((char*)fileHeader, sizeof(bmp_fileheader)); 123} 124 125void CBmp2Jpeg::InitInfoHeader(void *pFile, void *infoHeader) 126{ 127 bmp_infoheader *pinfoHeader = (bmp_infoheader *)infoHeader; 128 fstream *filein = (fstream *)pFile; 129 //初始化信息头 130 pinfoHeader->biSize=0; 131 pinfoHeader->biWidth=0; 132 pinfoHeader->biHeight=0; 133 pinfoHeader->biPlanes=0; 134 pinfoHeader->biBitCount=0; 135 pinfoHeader->biCompression=0; 136 pinfoHeader->biSizeImage=0; 137 pinfoHeader->biXPelsPerMeter=0; 138 pinfoHeader->biYPelsPerMeter=0; 139 pinfoHeader->biClrUsed=0; 140 pinfoHeader->biClrImportant=0; 141 142 //读位图信息头并输出相应信息 143 filein->read((char*)infoHeader, sizeof(bmp_infoheader)); 144} 145 146void CBmp2Jpeg::SaveBmp(void *fileHeader, void *infoHeader, int bitCount, unsigned char *data, const char *savename) 147{ 148 bmp_fileheader *pfileHeader = (bmp_fileheader *)fileHeader; 149 bmp_infoheader *pinfoHeader = (bmp_infoheader *)infoHeader; 150 //写入文件 151 std::string str(savename); 152 str.append(".bmp"); 153 fstream fileout; 154 fileout.open(str, std::ios::binary | std::ios::out); 155 fileout.write((char*)fileHeader, sizeof(bmp_fileheader)); 156 fileout.write((char*)infoHeader, sizeof(bmp_infoheader)); 157 fileout.write((char*)data, sizeof(unsigned char) * pfileHeader->bfSize - pfileHeader->bfOffBits); 158 159 fileout.close(); 160} 161 162//读取并将图片另存为一个新文件, 转换成rgb格式 163int CBmp2Jpeg::ReadBmp(const char *bmp, unsigned char **data, int &w, int &h, int &d) 164{ 165 //打开位图文件 166 fstream filein; 167 filein.open(bmp, std::ios::binary | std::ios::in); 168 if(!filein.is_open()) 169 { 170 char clog[256] = {0}; 171 sprintf_s(clog, sizeof(clog), "bmp转jpeg,找不到 %s\n", bmp); 172 OutputDebugStringA(clog); 173 return -1; 174 } 175 176 //定义变量 177 long width=0; 178 long height=0; 179 long bitCount=0; 180 181 bmp_fileheader fileHeader; 182 bmp_infoheader infoHeader; 183 184 InitFileHeader(&filein, &fileHeader); 185 186 if (fileHeader.bfType != 0x4d42) 187 { 188 filein.close(); 189 return -1; 190 } 191 192 InitInfoHeader(&filein, &infoHeader); 193 194 width=infoHeader.biWidth; 195 height=infoHeader.biHeight; 196 bitCount=infoHeader.biBitCount; 197 198 int bitPerLine= ((width * bitCount + 31) >> 5) << 2; 199 int imgSize = abs(height * bitPerLine); 200 int imgReal = fileHeader.bfSize - fileHeader.bfOffBits; 201 if(imgSize != imgReal) 202 { 203 char clog[256] = {0}; 204 sprintf_s(clog, sizeof(clog), "bmp转jpeg,图像尺寸不对\n"); 205 OutputDebugStringA(clog); 206 filein.close(); 207 return -1; 208 } 209 210 if (bitCount == 8) 211 { 212 std::vector<RGBPallete> palletes; 213 unsigned char buf[256 * sizeof(RGBPallete)]; 214 215 filein.read((char*)buf, 256 * sizeof(RGBPallete)); 216 217 for (int i = 0; i < 256; i++) 218 { 219 RGBPallete pallete; 220 memcpy(&pallete, buf + i * sizeof(RGBPallete), sizeof(RGBPallete)); 221 222 palletes.push_back(pallete); 223 } 224 225 unsigned char* pTemp = new unsigned char[imgSize]; 226 filein.read((char*)pTemp, imgSize); 227 228 *data = new unsigned char[width * abs(height) * 4]; 229 for (int i = 0; i < imgSize; i++) 230 { 231 RGBPallete& p = palletes[pTemp[i]]; 232 memcpy((*data) + i * sizeof(RGBPallete), &p, sizeof(RGBPallete)); 233 } 234 235 bitCount = 32; 236 delete pTemp; 237 } 238 else if (bitCount == 24 || bitCount == 32) 239 { 240 *data = new unsigned char[imgSize]; 241 filein.read((char*)(*data), imgSize); 242 filein.close(); 243 } 244 else 245 { 246 filein.close(); 247 return -1; 248 } 249 250 w = width; 251 h = height; 252 d = bitCount; 253 254 return 0; 255} 256 257void CBmp2Jpeg::Bgra2Rgb(const unsigned char *src, int w, int h, int d, unsigned char *dst) 258{ 259 unsigned char* pTempDst = dst; 260 for (int i = 0; i < abs(h); i++) 261 { 262 const unsigned char* pTempSrc = nullptr; 263 if (h > 0) 264 { 265 pTempSrc = src + w * i * d; 266 } 267 else 268 { 269 pTempSrc = src + w * abs( i + h + 1 ) * d; 270 } 271 272 for (int j = 0; j < w; j++) 273 { 274 *(pTempDst) = *(pTempSrc + 2); 275 *(pTempDst + 1) = *(pTempSrc + 1); 276 *(pTempDst + 2) = *(pTempSrc); 277 pTempDst += 3; 278 pTempSrc += d; 279 } 280 } 281} 282 283 284int CBmp2Jpeg::Bmp2Jpeg(const char *bmp, const char *jpeg) 285{ 286 unsigned char *brga = nullptr; //指向位图buffer的全局指针,window下像素格式: BGRA(4个字节) 287 int width = 0, height = 0, depth = 0; 288 289 if(ReadBmp(bmp, &brga,width, height, depth) < 0) 290 { 291 return -1; 292 } 293 294 unsigned char *rgb = new unsigned char[width * abs(height) * depth/8]; 295 Bgra2Rgb(brga, width, height, depth/8, rgb); 296 297 int ret = SaveJpeg(jpeg, rgb, width, abs(height), 3); 298 299 delete [] brga; 300 delete [] rgb; 301 brga = nullptr; 302 rgb = nullptr; 303 return ret; 304}

调用:

1#include <iostream> 2#include <stdio.h> 3#include "Bmp2Jpeg.h" 4using namespace std; 5int main() 6{ 7 CBmp2Jpeg bmp; 8 bmp.Bmp2Jpeg("111_24.bmp", "lena.jpg"); 9 cout<<"good job."<<endl; 10 cin.get(); 11 return 0; 12}
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Android So动态加载 优雅实现与原理分析

背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我