Skip to content

Commit 571222f

Browse files
authored
Merge pull request #11 from VerzatileDev/main
[ADD] / [FIX] > Image Converters / Black White filter
2 parents 4c2cf38 + 2d93075 commit 571222f

File tree

8 files changed

+275
-12
lines changed

8 files changed

+275
-12
lines changed

src/assets/images/test_ima.bmp

768 KB
Binary file not shown.

src/assets/images/testpng.png

161 KB
Loading

src/converters/bmp_to_jpeg.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,21 +81,35 @@ int bmp_to_jpeg(const char *input_filename, const char *output_filename)
8181
jpeg_stdio_dest(&cinfo, output_file);
8282
// start JPEG compressor
8383
jpeg_start_compress(&cinfo, TRUE);
84+
8485
// write JPEG image data
8586
while (cinfo.next_scanline < cinfo.image_height)
8687
{
87-
JSAMPROW row_pointer = &bmp_data[(cinfo.image_height - cinfo.next_scanline - 1) * (width * 3 + padding)];
88+
// get a pointer to the current row of BMP data
89+
unsigned char *bmp_row = &bmp_data[(cinfo.image_height - cinfo.next_scanline - 1) * (width * 3 + padding)];
90+
91+
// allocate an array to hold a row of RGB data in the correct order (RGB)
92+
unsigned char *rgb_row = (unsigned char *)malloc(width * 3);
93+
94+
// extract RGB data from BGR order and store it in rgb_row
95+
for (int i = 0; i < width; i++)
96+
{
97+
rgb_row[i * 3 + 0] = bmp_row[i * 3 + 2]; // Blue
98+
rgb_row[i * 3 + 1] = bmp_row[i * 3 + 1]; // Green
99+
rgb_row[i * 3 + 2] = bmp_row[i * 3 + 0]; // Red
100+
}
101+
102+
// write the corrected RGB row to the JPEG compressor
103+
JSAMPROW row_pointer = rgb_row;
88104
jpeg_write_scanlines(&cinfo, &row_pointer, 1);
105+
106+
// free the allocated memory for the RGB row
107+
free(rgb_row);
89108
}
90-
// finish JPEG compressor
91109
jpeg_finish_compress(&cinfo);
92-
// get size of JPEG image data
93110
jpeg_size = ftell(output_file);
94-
// close output file
95111
fclose(output_file);
96-
// destroy JPEG compressor object
97112
jpeg_destroy_compress(&cinfo);
98-
// free BMP image data
99113
free(bmp_data);
100114
printf("Converted %s to %s (%lu bytes)\n", input_filename, output_filename, jpeg_size);
101115

src/converters/bmp_to_png.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,18 @@ int bmp_to_png(const char *input_filename, const char *output_filename)
9696
// write PNG header info
9797
png_write_info(png_ptr, info_ptr);
9898
// write PNG image data
99-
for (int y = 0; y < height; y++)
100-
{
101-
png_bytep row_pointer = &bmp_data[(height - y - 1) * (width * 3 + padding)];
102-
png_write_row(png_ptr, row_pointer);
99+
for (int y = 0; y < height; y++) {
100+
png_bytep row_pointer = &bmp_data[(height - y - 1) * (width * 3 + padding)];
101+
102+
// convert BGR to RGB
103+
for (int x = 0; x < width; x++) {
104+
png_bytep pixel = &row_pointer[x * 3];
105+
png_byte temp = pixel[0];
106+
pixel[0] = pixel[2];
107+
pixel[2] = temp;
108+
}
109+
110+
png_write_row(png_ptr, row_pointer);
103111
}
104112
// finish writing PNG file
105113
png_write_end(png_ptr, NULL);

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/converters/png_to_bmp.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <png.h>
4+
5+
int png_to_bmp(const char *input_filename, const char *output_filename)
6+
{
7+
// open PNG file for reading
8+
FILE *input_file = fopen(input_filename, "rb");
9+
if (!input_file)
10+
{
11+
fprintf(stderr, "Error: could not open input file %s\n", input_filename);
12+
return 1;
13+
}
14+
// create PNG read struct
15+
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
16+
if (!png_ptr)
17+
{
18+
fprintf(stderr, "Error: could not create PNG read struct\n");
19+
fclose(input_file);
20+
return 1;
21+
}
22+
// create PNG info struct
23+
png_infop info_ptr = png_create_info_struct(png_ptr);
24+
if (!info_ptr)
25+
{
26+
fprintf(stderr, "Error: could not create PNG info struct\n");
27+
png_destroy_read_struct(&png_ptr, NULL, NULL);
28+
fclose(input_file);
29+
return 1;
30+
}
31+
// set error handling
32+
if (setjmp(png_jmpbuf(png_ptr)))
33+
{
34+
fprintf(stderr, "Error: PNG error\n");
35+
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
36+
fclose(input_file);
37+
return 1;
38+
}
39+
// initialize PNG I/O
40+
png_init_io(png_ptr, input_file);
41+
// read PNG header info
42+
png_read_info(png_ptr, info_ptr);
43+
// get PNG image attributes
44+
int width = png_get_image_width(png_ptr, info_ptr);
45+
int height = png_get_image_height(png_ptr, info_ptr);
46+
int color_type = png_get_color_type(png_ptr, info_ptr);
47+
int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
48+
// Make sure it's a valid format for conversion
49+
if (color_type != PNG_COLOR_TYPE_RGB || bit_depth != 8)
50+
{
51+
fprintf(stderr, "Error: unsupported PNG format\n");
52+
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
53+
fclose(input_file);
54+
return 1;
55+
}
56+
// allocate memory for PNG image data
57+
png_bytep *row_pointers = (png_bytep *)malloc(height * sizeof(png_bytep));
58+
if (!row_pointers)
59+
{
60+
fprintf(stderr, "Error: could not allocate memory for PNG image data\n");
61+
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
62+
fclose(input_file);
63+
return 1;
64+
}
65+
for (int y = 0; y < height; y++)
66+
{
67+
row_pointers[y] = (png_byte *)malloc(png_get_rowbytes(png_ptr, info_ptr));
68+
if (!row_pointers[y])
69+
{
70+
fprintf(stderr, "Error: could not allocate memory for PNG image data\n");
71+
for (int i = 0; i < y; i++)
72+
free(row_pointers[i]);
73+
free(row_pointers);
74+
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
75+
fclose(input_file);
76+
return 1;
77+
}
78+
}
79+
// read PNG image data
80+
png_read_image(png_ptr, row_pointers);
81+
// close PNG file
82+
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
83+
fclose(input_file);
84+
// open BMP file for writing
85+
FILE *output_file = fopen(output_filename, "wb");
86+
if (!output_file)
87+
{
88+
fprintf(stderr, "Error: could not open output file %s\n", output_filename);
89+
for (int y = 0; y < height; y++)
90+
free(row_pointers[y]);
91+
free(row_pointers);
92+
return 1;
93+
}
94+
// write BMP header
95+
unsigned char header[54] = {
96+
'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 40, 0,
97+
0, 0, (unsigned char)(width), (unsigned char)(width >> 8), (unsigned char)(width >> 16), (unsigned char)(width >> 24),
98+
(unsigned char)(height), (unsigned char)(height >> 8), (unsigned char)(height >> 16), (unsigned char)(height >> 24),
99+
1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
100+
fwrite(header, sizeof(unsigned char), 54, output_file);
101+
// write BMP image data
102+
for (int y = height - 1; y >= 0; y--)
103+
{
104+
for (int x = 0; x < width; x++)
105+
{
106+
png_bytep pixel = &(row_pointers[y][x * 3]);
107+
fwrite(&pixel[2], sizeof(png_byte), 1, output_file);
108+
fwrite(&pixel[1], sizeof(png_byte), 1, output_file);
109+
fwrite(&pixel[0], sizeof(png_byte), 1, output_file);
110+
}
111+
// Add padding
112+
for (int p = 0; p < (4 - (width * 3) % 4) % 4; p++)
113+
fputc(0, output_file);
114+
}
115+
// close BMP file
116+
fclose(output_file);
117+
// free memory
118+
for (int y = 0; y < height; y++)
119+
free(row_pointers[y]);
120+
free(row_pointers);
121+
printf("Converted %s to %s\n", input_filename, output_filename);
122+
return 0;
123+
}

src/gtk_gui.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ static void black_and_white_filter_apply(GtkWidget *widget, gpointer data)
1414
{
1515
GtkWidget *image = data;
1616

17-
black_and_white_filter("assets/images/test_image.bmp", "assets/images/test_image_bright.bmp");
17+
black_and_white_filter("assets/images/test_image.bmp", "assets/images/test_image_black_and_white.bmp");
1818
gtk_image_set_from_file(GTK_IMAGE(image), "assets/images/test_image_black_and_white.bmp");
1919
g_print("Black And White Filter Has Been Applied\n");
2020
}

src/main.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ int main(int argc, char **argv)
1313
status = g_application_run(G_APPLICATION(app), argc, argv);
1414
// release application object
1515
g_object_unref(app);
16-
1716
// wait for user input before exiting
1817
getchar();
1918

0 commit comments

Comments
 (0)