Skip to content

Commit bb34a9a

Browse files
committed
[ADD] - Jpeg to bmp
Added a function jpeg_to_bmp that converts JPEG images to BMP format. The function reads the input JPEG file, initializes a JPEG decompressor, and extracts image dimensions and pixel data. It then constructs a BMP header, calculates the BMP file size, and writes the header to the output BMP file. The JPEG pixel data is rearranged and written in RGB order to the BMP file. Padding is added as needed to align rows on a 4-byte boundary. The function ensures memory is properly managed, closes files, and provides conversion status output.
1 parent ac33f1c commit bb34a9a

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

src/converters/jpeg_to_bmp.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <jpeglib.h>
4+
5+
int jpeg_to_bmp(const char *input_filename, const char *output_filename)
6+
{
7+
FILE *input_file = fopen(input_filename, "rb");
8+
if (!input_file)
9+
{
10+
fprintf(stderr, "Error: could not open input file %s\n", input_filename);
11+
return 1;
12+
}
13+
14+
// Initialize JPEG decompressor object
15+
struct jpeg_decompress_struct cinfo;
16+
struct jpeg_error_mgr jerr;
17+
cinfo.err = jpeg_std_error(&jerr);
18+
jpeg_create_decompress(&cinfo);
19+
20+
// Specify input file for JPEG decompressor
21+
jpeg_stdio_src(&cinfo, input_file);
22+
jpeg_read_header(&cinfo, TRUE);
23+
jpeg_start_decompress(&cinfo);
24+
25+
// Get image dimensions
26+
int width = cinfo.output_width;
27+
int height = cinfo.output_height;
28+
29+
// Allocate memory for JPEG image data
30+
unsigned char *jpeg_data = (unsigned char *)malloc(width * height * cinfo.output_components);
31+
if (!jpeg_data)
32+
{
33+
fprintf(stderr, "Error: could not allocate memory for JPEG image data\n");
34+
fclose(input_file);
35+
jpeg_destroy_decompress(&cinfo);
36+
return 1;
37+
}
38+
39+
// Read JPEG image data
40+
while (cinfo.output_scanline < cinfo.output_height)
41+
{
42+
JSAMPROW row_pointer = &jpeg_data[(cinfo.output_height - cinfo.output_scanline - 1) * width * cinfo.output_components];
43+
jpeg_read_scanlines(&cinfo, &row_pointer, 1);
44+
}
45+
46+
// Finish decompression
47+
jpeg_finish_decompress(&cinfo);
48+
49+
// Close JPEG file
50+
fclose(input_file);
51+
jpeg_destroy_decompress(&cinfo);
52+
53+
// Open output BMP file for writing
54+
FILE *output_file = fopen(output_filename, "wb");
55+
if (!output_file)
56+
{
57+
fprintf(stderr, "Error: could not open output file %s\n", output_filename);
58+
free(jpeg_data);
59+
return 1;
60+
}
61+
62+
// Write BMP header
63+
unsigned char bmp_header[54] = {
64+
'B', 'M', // Signature
65+
0, 0, 0, 0, // File size (to be filled later)
66+
0, 0, 0, 0, // Reserved
67+
54, 0, 0, 0, // Offset to pixel data
68+
40, 0, 0, 0, // Header size
69+
0, 0, 0, 0, // Image width (to be filled later)
70+
0, 0, 0, 0, // Image height (to be filled later)
71+
1, 0, // Number of color planes
72+
24, 0, // Bits per pixel (3 bytes)
73+
0, 0, 0, 0, // Compression method
74+
0, 0, 0, 0, // Image size (can be 0)
75+
0, 0, 0, 0, // Horizontal resolution (can be 0)
76+
0, 0, 0, 0, // Vertical resolution (can be 0)
77+
0, 0, 0, 0, // Number of colors in palette (0 for 24-bit)
78+
0, 0, 0, 0 // Number of important colors (can be 0)
79+
};
80+
81+
int bmp_file_size = sizeof(bmp_header) + width * height * 3;
82+
bmp_header[2] = (unsigned char)(bmp_file_size);
83+
bmp_header[3] = (unsigned char)(bmp_file_size >> 8);
84+
bmp_header[4] = (unsigned char)(bmp_file_size >> 16);
85+
bmp_header[5] = (unsigned char)(bmp_file_size >> 24);
86+
bmp_header[18] = (unsigned char)(width);
87+
bmp_header[19] = (unsigned char)(width >> 8);
88+
bmp_header[20] = (unsigned char)(width >> 16);
89+
bmp_header[21] = (unsigned char)(width >> 24);
90+
bmp_header[22] = (unsigned char)(height);
91+
bmp_header[23] = (unsigned char)(height >> 8);
92+
bmp_header[24] = (unsigned char)(height >> 16);
93+
bmp_header[25] = (unsigned char)(height >> 24);
94+
95+
fwrite(bmp_header, sizeof(unsigned char), sizeof(bmp_header), output_file);
96+
97+
// Write BMP image data
98+
for (int y = height - 1; y >= 0; y--)
99+
{
100+
for (int x = 0; x < width; x++)
101+
{
102+
int jpeg_index = (height - y - 1) * width * cinfo.output_components + x * cinfo.output_components;
103+
fwrite(&jpeg_data[jpeg_index + 2], sizeof(unsigned char), 1, output_file); // Blue
104+
fwrite(&jpeg_data[jpeg_index + 1], sizeof(unsigned char), 1, output_file); // Green
105+
fwrite(&jpeg_data[jpeg_index + 0], sizeof(unsigned char), 1, output_file); // Red
106+
}
107+
108+
// Write padding if necessary (multiple of 4 bytes)
109+
for (int p = 0; p < (4 - (width * 3) % 4) % 4; p++)
110+
{
111+
fputc(0, output_file);
112+
}
113+
}
114+
115+
fclose(output_file);
116+
printf("Converted %s to %s\n", input_filename, output_filename);
117+
118+
return 0;
119+
}

src/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
//#include "converters/bmp_to_jpeg.c" // Include this line to test the bmp_to_jpeg function
33
//#include "converters/bmp_to_png.c"
44
//#include "converters/png_to_bmp.c"
5+
//#include "converters/jpeg_to_bmp.c"
56

67
int main(int argc, char **argv)
78
{
89
//Include the following line to test the bmp_to_jpeg function
910
//bmp_to_jpeg("assets/images/test_image.bmp", "assets/images/testjpg.jpg");
1011
//bmp_to_png("assets/images/test_image_negative.bmp", "assets/images/testpng.png");
1112
//png_to_bmp("assets/images/testpng.png", "assets/images/test_i.bmp");
13+
//jpeg_to_bmp("assets/images/testjpg.jpg", "assets/images/test_j.bmp");
1214

1315
GtkApplication *app;
1416
int status;

0 commit comments

Comments
 (0)