c++ jpg转bmp
时间: 2023-08-08 13:07:54 浏览: 103
以下是一个简单的C++程序,可以将JPEG图像转换为BMP图像:
```cpp
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <jpeglib.h>
#include <setjmp.h>
#define BMP_HEADER_SIZE 54
const int BMP_FILE_HEADER_SIZE = 14;
const int BMP_INFO_HEADER_SIZE = 40;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef int LONG;
#pragma pack(push, 1)
typedef struct {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BMP_FILE_HEADER;
typedef struct {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BMP_INFO_HEADER;
#pragma pack(pop)
struct my_error_mgr {
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
typedef struct my_error_mgr *my_error_ptr;
METHODDEF(void) my_error_exit(j_common_ptr cinfo) {
my_error_ptr myerr = (my_error_ptr) cinfo->err;
(*cinfo->err->output_message) (cinfo);
longjmp(myerr->setjmp_buffer, 1);
}
bool read_JPEG_file(const char *filename, BYTE **image_buffer, int *image_width, int *image_height) {
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
FILE *infile;
JSAMPARRAY buffer;
int row_stride;
if ((infile = fopen(filename, "rb")) == NULL) {
printf("Can't open %s\n", filename);
return false;
}
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
if (setjmp(jerr.setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return false;
}
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
*image_width = cinfo.output_width;
*image_height = cinfo.output_height;
int num_channels = cinfo.output_components;
*image_buffer = (BYTE *) malloc((*image_width) * (*image_height) * num_channels);
row_stride = (*image_width) * num_channels;
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
BYTE *pBuf = *image_buffer;
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, buffer, 1);
memcpy(pBuf, buffer[0], row_stride);
pBuf += row_stride;
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return true;
}
bool write_BMP_file(const char *filename, BYTE *image_buffer, int image_width, int image_height) {
int image_size = image_width * image_height * 3;
int file_size = BMP_HEADER_SIZE + image_size;
FILE *f = fopen(filename, "wb");
if (!f) {
printf("Can't create %s\n", filename);
return false;
}
BMP_FILE_HEADER bmp_file_header = {0};
bmp_file_header.bfType = 0x4D42; // 'BM'
bmp_file_header.bfSize = file_size;
bmp_file_header.bfOffBits = BMP_HEADER_SIZE;
BMP_INFO_HEADER bmp_info_header = {0};
bmp_info_header.biSize = BMP_INFO_HEADER_SIZE;
bmp_info_header.biWidth = image_width;
bmp_info_header.biHeight = image_height;
bmp_info_header.biPlanes = 1;
bmp_info_header.biBitCount = 24;
bmp_info_header.biSizeImage = image_size;
fwrite(&bmp_file_header, BMP_FILE_HEADER_SIZE, 1, f);
fwrite(&bmp_info_header, BMP_INFO_HEADER_SIZE, 1, f);
// BMP图像的像素是从下往上排列的,因此需要从最后一行开始写入
BYTE *pBuf = image_buffer + (image_height - 1) * image_width * 3;
for (int i = 0; i < image_height; i++) {
for (int j = 0; j < image_width; j++) {
BYTE b = *pBuf++;
BYTE g = *pBuf++;
BYTE r = *pBuf++;
BYTE color[] = {b, g, r};
fwrite(color, 3, 1, f);
}
pBuf -= image_width * 6;
}
fclose(f);
return true;
}
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Usage: jpg2bmp input.jpg output.bmp\n");
return 0;
}
BYTE *image_buffer = NULL;
int image_width = 0, image_height = 0;
if (!read_JPEG_file(argv[1], &image_buffer, &image_width, &image_height)) {
printf("Error: failed to read JPEG file\n");
return -1;
}
if (!write_BMP_file(argv[2], image_buffer, image_width, image_height)) {
printf("Error: failed to write BMP file\n");
return -1;
}
if (image_buffer) {
free(image_buffer);
image_buffer = NULL;
}
return 0;
}
```
这个程序使用了jpeglib库来读取JPEG图像,然后将RGB数据写入BMP图像。它只支持24位真彩色图像,但可以轻松地修改以支持其他格式。