C语言bmp转JPEG不用库函数,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:

intm_quality;//它的大小决定jpg的质量好坏

enum{

JPEG_QUALITY = 100,

};

};

Bmp2Jpeg.cpp:

#include

#include

#include

//#include

#include "Bmp2Jpeg.h"

#include

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 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

#include

#include "Bmp2Jpeg.h"

using namespace std;

int main()

{

CBmp2Jpeg bmp;

bmp.Bmp2Jpeg("111_24.bmp", "lena.jpg");

cout<

cin.get();

return 0;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值