Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added src/assets/images/test_ima.bmp
Binary file not shown.
Binary file added src/assets/images/testpng.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 20 additions & 6 deletions src/converters/bmp_to_jpeg.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,35 @@ int bmp_to_jpeg(const char *input_filename, const char *output_filename)
jpeg_stdio_dest(&cinfo, output_file);
// start JPEG compressor
jpeg_start_compress(&cinfo, TRUE);

// write JPEG image data
while (cinfo.next_scanline < cinfo.image_height)
{
JSAMPROW row_pointer = &bmp_data[(cinfo.image_height - cinfo.next_scanline - 1) * (width * 3 + padding)];
// get a pointer to the current row of BMP data
unsigned char *bmp_row = &bmp_data[(cinfo.image_height - cinfo.next_scanline - 1) * (width * 3 + padding)];

// allocate an array to hold a row of RGB data in the correct order (RGB)
unsigned char *rgb_row = (unsigned char *)malloc(width * 3);

// extract RGB data from BGR order and store it in rgb_row
for (int i = 0; i < width; i++)
{
rgb_row[i * 3 + 0] = bmp_row[i * 3 + 2]; // Blue
rgb_row[i * 3 + 1] = bmp_row[i * 3 + 1]; // Green
rgb_row[i * 3 + 2] = bmp_row[i * 3 + 0]; // Red
}

// write the corrected RGB row to the JPEG compressor
JSAMPROW row_pointer = rgb_row;
jpeg_write_scanlines(&cinfo, &row_pointer, 1);

// free the allocated memory for the RGB row
free(rgb_row);
}
// finish JPEG compressor
jpeg_finish_compress(&cinfo);
// get size of JPEG image data
jpeg_size = ftell(output_file);
// close output file
fclose(output_file);
// destroy JPEG compressor object
jpeg_destroy_compress(&cinfo);
// free BMP image data
free(bmp_data);
printf("Converted %s to %s (%lu bytes)\n", input_filename, output_filename, jpeg_size);

Expand Down
16 changes: 12 additions & 4 deletions src/converters/bmp_to_png.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,18 @@ int bmp_to_png(const char *input_filename, const char *output_filename)
// write PNG header info
png_write_info(png_ptr, info_ptr);
// write PNG image data
for (int y = 0; y < height; y++)
{
png_bytep row_pointer = &bmp_data[(height - y - 1) * (width * 3 + padding)];
png_write_row(png_ptr, row_pointer);
for (int y = 0; y < height; y++) {
png_bytep row_pointer = &bmp_data[(height - y - 1) * (width * 3 + padding)];

// convert BGR to RGB
for (int x = 0; x < width; x++) {
png_bytep pixel = &row_pointer[x * 3];
png_byte temp = pixel[0];
pixel[0] = pixel[2];
pixel[2] = temp;
}

png_write_row(png_ptr, row_pointer);
}
// finish writing PNG file
png_write_end(png_ptr, NULL);
Expand Down
119 changes: 119 additions & 0 deletions src/converters/jpeg_to_bmp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#include <stdio.h>
#include <stdlib.h>
#include <jpeglib.h>

int jpeg_to_bmp(const char *input_filename, const char *output_filename)
{
FILE *input_file = fopen(input_filename, "rb");
if (!input_file)
{
fprintf(stderr, "Error: could not open input file %s\n", input_filename);
return 1;
}

// initialize JPEG decompressor object
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);

// specify input file for JPEG decompressor
jpeg_stdio_src(&cinfo, input_file);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);

// get image dimensions
int width = cinfo.output_width;
int height = cinfo.output_height;

// allocate memory for JPEG image data
unsigned char *jpeg_data = (unsigned char *)malloc(width * height * cinfo.output_components);
if (!jpeg_data)
{
fprintf(stderr, "Error: could not allocate memory for JPEG image data\n");
fclose(input_file);
jpeg_destroy_decompress(&cinfo);
return 1;
}

// read JPEG image data
while (cinfo.output_scanline < cinfo.output_height)
{
JSAMPROW row_pointer = &jpeg_data[(cinfo.output_height - cinfo.output_scanline - 1) * width * cinfo.output_components];
jpeg_read_scanlines(&cinfo, &row_pointer, 1);
}

// finish decompression
jpeg_finish_decompress(&cinfo);

// close JPEG file
fclose(input_file);
jpeg_destroy_decompress(&cinfo);

// open output BMP file for writing
FILE *output_file = fopen(output_filename, "wb");
if (!output_file)
{
fprintf(stderr, "Error: could not open output file %s\n", output_filename);
free(jpeg_data);
return 1;
}

// write BMP header
unsigned char bmp_header[54] = {
'B', 'M', // signature
0, 0, 0, 0, // file size (to be filled later)
0, 0, 0, 0, // reserved
54, 0, 0, 0, // offset to pixel data
40, 0, 0, 0, // header size
0, 0, 0, 0, // image width (to be filled later)
0, 0, 0, 0, // image height (to be filled later)
1, 0, // number of color planes
24, 0, // bits per pixel (3 bytes)
0, 0, 0, 0, // compression method
0, 0, 0, 0, // image size (can be 0)
0, 0, 0, 0, // horizontal resolution (can be 0)
0, 0, 0, 0, // vertical resolution (can be 0)
0, 0, 0, 0, // number of colors in palette (0 for 24-bit)
0, 0, 0, 0 // number of important colors (can be 0)
};

int bmp_file_size = sizeof(bmp_header) + width * height * 3;
bmp_header[2] = (unsigned char)(bmp_file_size);
bmp_header[3] = (unsigned char)(bmp_file_size >> 8);
bmp_header[4] = (unsigned char)(bmp_file_size >> 16);
bmp_header[5] = (unsigned char)(bmp_file_size >> 24);
bmp_header[18] = (unsigned char)(width);
bmp_header[19] = (unsigned char)(width >> 8);
bmp_header[20] = (unsigned char)(width >> 16);
bmp_header[21] = (unsigned char)(width >> 24);
bmp_header[22] = (unsigned char)(height);
bmp_header[23] = (unsigned char)(height >> 8);
bmp_header[24] = (unsigned char)(height >> 16);
bmp_header[25] = (unsigned char)(height >> 24);

fwrite(bmp_header, sizeof(unsigned char), sizeof(bmp_header), output_file);

// write BMP image data
for (int y = height - 1; y >= 0; y--)
{
for (int x = 0; x < width; x++)
{
int jpeg_index = (height - y - 1) * width * cinfo.output_components + x * cinfo.output_components;
fwrite(&jpeg_data[jpeg_index + 2], sizeof(unsigned char), 1, output_file); // Blue
fwrite(&jpeg_data[jpeg_index + 1], sizeof(unsigned char), 1, output_file); // Green
fwrite(&jpeg_data[jpeg_index + 0], sizeof(unsigned char), 1, output_file); // Red
}

// write padding if necessary (multiple of 4 bytes)
for (int p = 0; p < (4 - (width * 3) % 4) % 4; p++)
{
fputc(0, output_file);
}
}

fclose(output_file);
printf("Converted %s to %s\n", input_filename, output_filename);

return 0;
}
123 changes: 123 additions & 0 deletions src/converters/png_to_bmp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include <stdio.h>
#include <stdlib.h>
#include <png.h>

int png_to_bmp(const char *input_filename, const char *output_filename)
{
// open PNG file for reading
FILE *input_file = fopen(input_filename, "rb");
if (!input_file)
{
fprintf(stderr, "Error: could not open input file %s\n", input_filename);
return 1;
}
// create PNG read struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
{
fprintf(stderr, "Error: could not create PNG read struct\n");
fclose(input_file);
return 1;
}
// create PNG info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
fprintf(stderr, "Error: could not create PNG info struct\n");
png_destroy_read_struct(&png_ptr, NULL, NULL);
fclose(input_file);
return 1;
}
// set error handling
if (setjmp(png_jmpbuf(png_ptr)))
{
fprintf(stderr, "Error: PNG error\n");
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(input_file);
return 1;
}
// initialize PNG I/O
png_init_io(png_ptr, input_file);
// read PNG header info
png_read_info(png_ptr, info_ptr);
// get PNG image attributes
int width = png_get_image_width(png_ptr, info_ptr);
int height = png_get_image_height(png_ptr, info_ptr);
int color_type = png_get_color_type(png_ptr, info_ptr);
int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
// Make sure it's a valid format for conversion
if (color_type != PNG_COLOR_TYPE_RGB || bit_depth != 8)
{
fprintf(stderr, "Error: unsupported PNG format\n");
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(input_file);
return 1;
}
// allocate memory for PNG image data
png_bytep *row_pointers = (png_bytep *)malloc(height * sizeof(png_bytep));
if (!row_pointers)
{
fprintf(stderr, "Error: could not allocate memory for PNG image data\n");
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(input_file);
return 1;
}
for (int y = 0; y < height; y++)
{
row_pointers[y] = (png_byte *)malloc(png_get_rowbytes(png_ptr, info_ptr));
if (!row_pointers[y])
{
fprintf(stderr, "Error: could not allocate memory for PNG image data\n");
for (int i = 0; i < y; i++)
free(row_pointers[i]);
free(row_pointers);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(input_file);
return 1;
}
}
// read PNG image data
png_read_image(png_ptr, row_pointers);
// close PNG file
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(input_file);
// open BMP file for writing
FILE *output_file = fopen(output_filename, "wb");
if (!output_file)
{
fprintf(stderr, "Error: could not open output file %s\n", output_filename);
for (int y = 0; y < height; y++)
free(row_pointers[y]);
free(row_pointers);
return 1;
}
// write BMP header
unsigned char header[54] = {
'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 40, 0,
0, 0, (unsigned char)(width), (unsigned char)(width >> 8), (unsigned char)(width >> 16), (unsigned char)(width >> 24),
(unsigned char)(height), (unsigned char)(height >> 8), (unsigned char)(height >> 16), (unsigned char)(height >> 24),
1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
fwrite(header, sizeof(unsigned char), 54, output_file);
// write BMP image data
for (int y = height - 1; y >= 0; y--)
{
for (int x = 0; x < width; x++)
{
png_bytep pixel = &(row_pointers[y][x * 3]);
fwrite(&pixel[2], sizeof(png_byte), 1, output_file);
fwrite(&pixel[1], sizeof(png_byte), 1, output_file);
fwrite(&pixel[0], sizeof(png_byte), 1, output_file);
}
// Add padding
for (int p = 0; p < (4 - (width * 3) % 4) % 4; p++)
fputc(0, output_file);
}
// close BMP file
fclose(output_file);
// free memory
for (int y = 0; y < height; y++)
free(row_pointers[y]);
free(row_pointers);
printf("Converted %s to %s\n", input_filename, output_filename);
return 0;
}
2 changes: 1 addition & 1 deletion src/gtk_gui.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ static void black_and_white_filter_apply(GtkWidget *widget, gpointer data)
{
GtkWidget *image = data;

black_and_white_filter("assets/images/test_image.bmp", "assets/images/test_image_bright.bmp");
black_and_white_filter("assets/images/test_image.bmp", "assets/images/test_image_black_and_white.bmp");
gtk_image_set_from_file(GTK_IMAGE(image), "assets/images/test_image_black_and_white.bmp");
g_print("Black And White Filter Has Been Applied\n");
}
Expand Down
1 change: 0 additions & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ int main(int argc, char **argv)
status = g_application_run(G_APPLICATION(app), argc, argv);
// release application object
g_object_unref(app);

// wait for user input before exiting
getchar();

Expand Down