added ws202425 courses

This commit is contained in:
2024-11-14 13:11:04 +01:00
parent 800282c2e8
commit beb31897b1
461 changed files with 20368 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
filter:
clang -ggdb3 -gdwarf-4 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-gnu-folding-constant -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -lm -o filter filter.c helpers.c
+57
View File
@@ -0,0 +1,57 @@
// BMP-related data types based on Microsoft's own
#include <stdint.h>
// These data types are essentially aliases for C/C++ primitive data types.
// Adapted from http://msdn.microsoft.com/en-us/library/cc230309.aspx.
// See https://en.wikipedia.org/wiki/C_data_types#stdint.h for more on stdint.h.
typedef uint8_t BYTE;
typedef uint32_t DWORD;
typedef int32_t LONG;
typedef uint16_t WORD;
// The BITMAPFILEHEADER structure contains information about the type, size,
// and layout of a file that contains a DIB [device-independent bitmap].
// Adapted from http://msdn.microsoft.com/en-us/library/dd183374(VS.85).aspx.
typedef struct
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} __attribute__((__packed__))
BITMAPFILEHEADER;
// The BITMAPINFOHEADER structure contains information about the
// dimensions and color format of a DIB [device-independent bitmap].
// Adapted from http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx.
typedef struct
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} __attribute__((__packed__))
BITMAPINFOHEADER;
// The RGBTRIPLE structure describes a color consisting of relative intensities of
// red, green, and blue. Adapted from http://msdn.microsoft.com/en-us/library/aa922590.aspx.
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
+150
View File
@@ -0,0 +1,150 @@
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include "helpers.h"
int main(int argc, char *argv[])
{
// Define allowable filters
char *filters = "bgrs";
// Get filter flag and check validity
char filter = getopt(argc, argv, filters);
if (filter == '?')
{
printf("Invalid filter.\n");
return 1;
}
// Ensure only one filter
if (getopt(argc, argv, filters) != -1)
{
printf("Only one filter allowed.\n");
return 2;
}
// Ensure proper usage
if (argc != optind + 2)
{
printf("Usage: ./filter [flag] infile outfile\n");
return 3;
}
// Remember filenames
char *infile = argv[optind];
char *outfile = argv[optind + 1];
// Open input file
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("Could not open %s.\n", infile);
return 4;
}
// Open output file
FILE *outptr = fopen(outfile, "w");
if (outptr == NULL)
{
fclose(inptr);
printf("Could not create %s.\n", outfile);
return 5;
}
// Read infile's BITMAPFILEHEADER
BITMAPFILEHEADER bf;
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
// Read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bi;
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
// Ensure infile is (likely) a 24-bit uncompressed BMP 4.0
if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
bi.biBitCount != 24 || bi.biCompression != 0)
{
fclose(outptr);
fclose(inptr);
printf("Unsupported file format.\n");
return 6;
}
// Get image's dimensions
int height = abs(bi.biHeight);
int width = bi.biWidth;
// Allocate memory for image
RGBTRIPLE(*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));
if (image == NULL)
{
printf("Not enough memory to store image.\n");
fclose(outptr);
fclose(inptr);
return 7;
}
// Determine padding for scanlines
int padding = (4 - (width * sizeof(RGBTRIPLE)) % 4) % 4;
// Iterate over infile's scanlines
for (int i = 0; i < height; i++)
{
// Read row into pixel array
fread(image[i], sizeof(RGBTRIPLE), width, inptr);
// Skip over padding
fseek(inptr, padding, SEEK_CUR);
}
// Filter image
switch (filter)
{
// Blur
case 'b':
blur(height, width, image);
break;
// Grayscale
case 'g':
grayscale(height, width, image);
break;
// Reflection
case 'r':
reflect(height, width, image);
break;
// Sepia
case 's':
sepia(height, width, image);
break;
}
// Write outfile's BITMAPFILEHEADER
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// Write outfile's BITMAPINFOHEADER
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// Write new pixels to outfile
for (int i = 0; i < height; i++)
{
// Write row to outfile
fwrite(image[i], sizeof(RGBTRIPLE), width, outptr);
// Write padding at end of row
for (int k = 0; k < padding; k++)
{
fputc(0x00, outptr);
}
}
// Free memory for image
free(image);
// Close files
fclose(inptr);
fclose(outptr);
return 0;
}
+350
View File
@@ -0,0 +1,350 @@
#include "helpers.h"
#include <math.h>
#include <stdio.h>
// Convert image to grayscale
// The function grayscale takes three arguments: height and width, which are integers representing the dimensions of an image, and image, which is a two-dimensional array of type RGBTRIPLE representing the pixels of the image. The function converts the image to grayscale by setting the red, green, and blue components of each pixel to the mean of the original values. The result is stored back in the image array. The function uses nested loops to iterate over all pixels in the image. For each pixel, it calculates the mean of its red, green, and blue components using the formula (red + green + blue) / 3, and rounds the result to the nearest integer using the round function. Then it sets the red, green, and blue components of the pixel to the calculated mean. Finally, the function returns void, indicating that it does not return any value.
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int mean = (int) round((image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtBlue) / 3.0);
image[i][j].rgbtRed = mean;
image[i][j].rgbtGreen = mean;
image[i][j].rgbtBlue = mean;
}
}
return;
}
// Convert image to sepia
void sepia(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int sepiaRed = (int) round(.393 * image[i][j].rgbtRed + .769 * image[i][j].rgbtGreen + .189 * image[i][j].rgbtBlue) ;
int sepiaGreen = (int) round(.349 * image[i][j].rgbtRed + .686 * image[i][j].rgbtGreen + .168 * image[i][j].rgbtBlue);
int sepiaBlue = (int) round(.272 * image[i][j].rgbtRed + .534 * image[i][j].rgbtGreen + .131 * image[i][j].rgbtBlue);
if (sepiaRed > 255)
{
sepiaRed = 255;
}
if (sepiaGreen > 255)
{
sepiaGreen = 255;
}
if (sepiaBlue > 255)
{
sepiaBlue = 255;
}
image[i][j].rgbtRed = sepiaRed;
image[i][j].rgbtGreen = sepiaGreen;
image[i][j].rgbtBlue = sepiaBlue;
}
}
return;
}
// Reflect image horizontally
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width / 2; j++)
{
RGBTRIPLE og = image[i][j];
image[i][j] = image[i][width - 1 - j];
image[i][width - 1 - j] = og;
}
}
return;
}
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE og[height][width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
og[i][j] = image[i][j];
}
}
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
// inbetween
if (i >= 1 && i < height - 1 && j >= 1 && j < width - 1)
{
image[i][j].rgbtRed = (int) round((og[i][j].rgbtRed +
og[i - 1][j - 1].rgbtRed +
og[i - 1][j].rgbtRed +
og[i - 1][j + 1].rgbtRed +
og[i][j - 1].rgbtRed +
og[i][j + 1].rgbtRed +
og[i + 1][j - 1].rgbtRed +
og[i + 1][j].rgbtRed +
og[i + 1][j + 1].rgbtRed) / 9.0);
image[i][j].rgbtGreen = (int) round((og[i][j].rgbtGreen +
og[i - 1][j - 1].rgbtGreen +
og[i - 1][j].rgbtGreen +
og[i - 1][j + 1].rgbtGreen +
og[i][j - 1].rgbtGreen +
og[i][j + 1].rgbtGreen +
og[i + 1][j - 1].rgbtGreen +
og[i + 1][j].rgbtGreen +
og[i + 1][j + 1].rgbtGreen) / 9.0);
image[i][j].rgbtBlue = (int) round((og[i][j].rgbtBlue +
og[i - 1][j - 1].rgbtBlue +
og[i - 1][j].rgbtBlue +
og[i - 1][j + 1].rgbtBlue +
og[i][j - 1].rgbtBlue +
og[i][j + 1].rgbtBlue +
og[i + 1][j - 1].rgbtBlue +
og[i + 1][j].rgbtBlue +
og[i + 1][j + 1].rgbtBlue) / 9.0);
}
// Corners
// upper left corner
if (i == 0 && j == 0)
{
image[i][j].rgbtRed = (int) round((og[i][j].rgbtRed +
og[i][j + 1].rgbtRed +
og[i + 1][j].rgbtRed +
og[i + 1][j + 1].rgbtRed) / 4.0);
image[i][j].rgbtGreen = (int) round((og[i][j].rgbtGreen +
og[i][j + 1].rgbtGreen +
og[i + 1][j].rgbtGreen +
og[i + 1][j + 1].rgbtGreen) / 4.0);
image[i][j].rgbtBlue = (int) round((og[i][j].rgbtBlue +
og[i][j + 1].rgbtBlue +
og[i + 1][j].rgbtBlue +
og[i + 1][j + 1].rgbtBlue) / 4.0);
}
// upper right corner
if (i == 0 && j == width - 1)
{
image[i][j].rgbtRed = (int) round((og[i][j].rgbtRed +
og[i][j - 1].rgbtRed +
og[i + 1][j - 1].rgbtRed +
og[i + 1][j].rgbtRed) / 4.0);
image[i][j].rgbtGreen = (int) round((og[i][j].rgbtGreen +
og[i][j - 1].rgbtGreen +
og[i + 1][j - 1].rgbtGreen +
og[i + 1][j].rgbtGreen) / 4.0);
image[i][j].rgbtBlue = (int) round((og[i][j].rgbtBlue +
og[i][j - 1].rgbtBlue +
og[i + 1][j - 1].rgbtBlue +
og[i + 1][j].rgbtBlue) / 4.0);
}
// lower left corner
if (i == height - 1 && j == 0)
{
image[i][j].rgbtRed = (int) round((og[i][j].rgbtRed +
og[i - 1][j].rgbtRed +
og[i - 1][j + 1].rgbtRed +
og[i][j + 1].rgbtRed) / 4.0);
image[i][j].rgbtGreen = (int) round((og[i][j].rgbtGreen +
og[i - 1][j].rgbtGreen +
og[i - 1][j + 1].rgbtGreen +
og[i][j + 1].rgbtGreen) / 4.0);
image[i][j].rgbtBlue = (int) round((og[i][j].rgbtBlue +
og[i - 1][j].rgbtBlue +
og[i - 1][j + 1].rgbtBlue +
og[i][j + 1].rgbtBlue) / 4.0);
}
// lower right corner
if (i == height - 1 && j == width - 1)
{
image[i][j].rgbtRed = (int) round((og[i][j].rgbtRed +
og[i - 1][j - 1].rgbtRed +
og[i - 1][j].rgbtRed +
og[i][j - 1].rgbtRed) / 4.0);
image[i][j].rgbtGreen = (int) round((og[i][j].rgbtGreen +
og[i - 1][j - 1].rgbtGreen +
og[i - 1][j].rgbtGreen +
og[i][j - 1].rgbtGreen) / 4.0);
image[i][j].rgbtBlue = (int) round((og[i][j].rgbtBlue +
og[i - 1][j - 1].rgbtBlue +
og[i - 1][j].rgbtBlue +
og[i][j - 1].rgbtBlue) / 4.0);
}
// Sides
// Upper side
if (i == 0 && j > 0 && j < width - 1)
{
image[i][j].rgbtRed = (int) round((og[i][j].rgbtRed +
og[i][j - 1].rgbtRed +
og[i][j + 1].rgbtRed +
og[i + 1][j - 1].rgbtRed +
og[i + 1][j].rgbtRed +
og[i + 1][j + 1].rgbtRed) / 6.0);
image[i][j].rgbtGreen = (int) round((og[i][j].rgbtGreen +
og[i][j - 1].rgbtGreen +
og[i][j + 1].rgbtGreen +
og[i + 1][j - 1].rgbtGreen +
og[i + 1][j].rgbtGreen +
og[i + 1][j + 1].rgbtGreen) / 6.0);
image[i][j].rgbtBlue = (int) round((og[i][j].rgbtBlue +
og[i][j - 1].rgbtBlue +
og[i][j + 1].rgbtBlue +
og[i + 1][j - 1].rgbtBlue +
og[i + 1][j].rgbtBlue +
og[i + 1][j + 1].rgbtBlue) / 6.0);
}
// lower side
if (i == height - 1 && j > 0 && j < width - 1)
{
image[i][j].rgbtRed = (int)round((og[i][j].rgbtRed +
og[i - 1][j - 1].rgbtRed +
og[i - 1][j].rgbtRed +
og[i - 1][j + 1].rgbtRed +
og[i][j - 1].rgbtRed +
og[i][j + 1].rgbtRed) / 6.0);
image[i][j].rgbtGreen = (int)round((og[i][j].rgbtGreen +
og[i - 1][j - 1].rgbtGreen +
og[i - 1][j].rgbtGreen +
og[i - 1][j + 1].rgbtGreen +
og[i][j - 1].rgbtGreen +
og[i][j + 1].rgbtGreen) / 6.0);
image[i][j].rgbtBlue = (int) round((og[i][j].rgbtBlue +
og[i - 1][j - 1].rgbtBlue +
og[i - 1][j].rgbtBlue +
og[i - 1][j + 1].rgbtBlue +
og[i][j - 1].rgbtBlue +
og[i][j + 1].rgbtBlue) / 6.0);
}
// left side
if (i > 0 && i < height - 1 && j == 0)
{
image[i][j].rgbtRed = (int) round((og[i][j].rgbtRed +
og[i - 1][j].rgbtRed +
og[i - 1][j + 1].rgbtRed +
og[i][j + 1].rgbtRed +
og[i + 1][j].rgbtRed +
og[i + 1][j + 1].rgbtRed) / 6.0);
image[i][j].rgbtGreen = (int) round((og[i][j].rgbtGreen +
og[i - 1][j].rgbtGreen +
og[i - 1][j + 1].rgbtGreen +
og[i][j + 1].rgbtGreen +
og[i + 1][j].rgbtGreen +
og[i + 1][j + 1].rgbtGreen) / 6.0);
image[i][j].rgbtBlue = (int) round((og[i][j].rgbtBlue +
og[i - 1][j].rgbtBlue +
og[i - 1][j + 1].rgbtBlue +
og[i][j + 1].rgbtBlue +
og[i + 1][j].rgbtBlue +
og[i + 1][j + 1].rgbtBlue) / 6.0);
}
// right side
if (i > 0 && i < height - 1 && j == width - 1)
{
image[i][j].rgbtRed = (int) round((og[i][j].rgbtRed +
og[i - 1][j - 1].rgbtRed +
og[i - 1][j].rgbtRed +
og[i][j - 1].rgbtRed +
og[i + 1][j - 1].rgbtRed +
og[i + 1][j].rgbtRed) / 6.0);
image[i][j].rgbtGreen = (int) round((og[i][j].rgbtGreen +
og[i - 1][j - 1].rgbtGreen +
og[i - 1][j].rgbtGreen + og[i][j - 1].rgbtGreen +
og[i + 1][j - 1].rgbtGreen + og[i + 1][j].rgbtGreen) / 6.0);
image[i][j].rgbtBlue = (int) round((og[i][j].rgbtBlue +
og[i - 1][j - 1].rgbtBlue +
og[i - 1][j].rgbtBlue +
og[i][j - 1].rgbtBlue +
og[i + 1][j - 1].rgbtBlue +
og[i + 1][j].rgbtBlue) / 6.0);
}
}
}
return;
}
//00 = [i - 1][j - 1]
//01 = [i - 1][j]
//02 = [i - 1][j + 1]
//10 = [i][j - 1]
//12 = [i][j + 1]
//20 = [i + 1][j - 1]
//21 = [i + 1][j]
//22 = [i + 1][j + 1]
// Dazwischen
//00 = [i - 1][j - 1]
//01 = [i - 1][j]
//02 = [i - 1][j + 1]
//10 = [i][j - 1]
//12 = [i][j + 1]
//20 = [i + 1][j - 1]
//21 = [i + 1][j]
//22 = [i + 1][j + 1]
//Ecke Links oben
//12 [i][j + 1]
//21 [i + 1][j]
//22 [i + 1][j + 1]
//Ecke Rechts oben
//10 [i][j - 1]
//20 [i + 1][j - 1]
//21 [i + 1][j]
//Ecke Links unten
//01 [i - 1][j]
//02 [i - 1][j + 1]
//12 [i][j + 1]
//Ecke Rechts unten
//00 [i - 1][j - 1]
//01 [i - 1][j]
//10 [i][j - 1]
// Seite oben
//10 [i][j - 1]
//12 [i][j + 1]
//20 [i + 1][j - 1]
//21 [i + 1][j]
//22 [i + 1][j + 1]
// Seite unten
//00 [i - 1][j - 1]
//01 [i - 1][j]
//02 [i - 1][j + 1]
//10 [i][j - 1]
//12 [i][j + 1]
// Seite links
//01 [i - 1][j]
//02 [i - 1][j + 1]
//12 [i][j + 1]
//21 [i + 1][j]
//22 [i + 1][j + 1]
// Seite rechts
//00 [i - 1][j - 1]
//01 [i - 1][j]
//10 [i][j - 1]
//20 [i + 1][j - 1]
//21 [i + 1][j]
+13
View File
@@ -0,0 +1,13 @@
#include "bmp.h"
// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width]);
// Convert image to sepia
void sepia(int height, int width, RGBTRIPLE image[height][width]);
// Reflect image horizontally
void reflect(int height, int width, RGBTRIPLE image[height][width]);
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width]);
+51
View File
@@ -0,0 +1,51 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("Usage: ./recover IMAGE\n");
return 1;
}
FILE *file = fopen(argv[1], "r");
FILE *img = NULL;
BYTE buffer[512];
int img_number = 0;
char img_name[8];
while (fread(&buffer, 512, 1, file) == 1)
{
if (buffer[0] == 0xff &&
buffer[1] == 0xd8 &&
buffer[2] == 0xff &&
(buffer[3] & 0xf0) == 0xe0)
{
if (!(img_number == 0))
{
fclose(img);
}
sprintf(img_name, "%03i.jpg", img_number);
img = fopen(img_name, "w");
img_number ++;
}
if (!(img_number == 0))
{
fwrite(&buffer, 512, 1, img);
}
}
fclose(file);
fclose(img);
return 0;
}
+30
View File
@@ -0,0 +1,30 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
int BLOCK_SIZE = 512;
typedef uint8_t BYTE;
BYTE buffer[BLOCK_SIZE];
FILE *file = fopen("card.raw", "r");
if (argc != 2)
{
printf("Usage: ./recover card.raw\n");
return 1;
}
while (fread(&buffer, 1, BLOCK_SIZE, file) == BLOCK_SIZE)
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
printf("%i",buffer)
}
}
fclose(file);
return 0;
}
+2
View File
@@ -0,0 +1,2 @@
colorize:
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -o colorize colorize.c helpers.c
+75
View File
@@ -0,0 +1,75 @@
// BMP-related data types based on Microsoft's own
#include <stdint.h>
/**
* Common Data Types
*
* The data types in this section are essentially aliases for C/C++
* primitive data types.
*
* Adapted from http://msdn.microsoft.com/en-us/library/cc230309.aspx.
* See http://en.wikipedia.org/wiki/Stdint.h for more on stdint.h.
*/
typedef uint8_t BYTE;
typedef uint32_t DWORD;
typedef int32_t LONG;
typedef uint16_t WORD;
/**
* BITMAPFILEHEADER
*
* The BITMAPFILEHEADER structure contains information about the type, size,
* and layout of a file that contains a DIB [device-independent bitmap].
*
* Adapted from http://msdn.microsoft.com/en-us/library/dd183374(VS.85).aspx.
*/
typedef struct
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} __attribute__((__packed__))
BITMAPFILEHEADER;
/**
* BITMAPINFOHEADER
*
* The BITMAPINFOHEADER structure contains information about the
* dimensions and color format of a DIB [device-independent bitmap].
*
* Adapted from http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx.
*/
typedef struct
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} __attribute__((__packed__))
BITMAPINFOHEADER;
/**
* RGBTRIPLE
*
* This structure describes a color consisting of relative intensities of
* red, green, and blue.
*
* Adapted from http://msdn.microsoft.com/en-us/library/aa922590.aspx.
*/
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
+111
View File
@@ -0,0 +1,111 @@
#include <stdio.h>
#include <stdlib.h>
#include "helpers.h"
int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 3)
{
printf("Usage: colorize infile outfile\n");
return 1;
}
// remember filenames
char *infile = argv[1];
char *outfile = argv[2];
// open input file
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("Could not open %s.\n", infile);
return 4;
}
// open output file
FILE *outptr = fopen(outfile, "w");
if (outptr == NULL)
{
fclose(inptr);
printf("Could not create %s.\n", outfile);
return 5;
}
// read infile's BITMAPFILEHEADER
BITMAPFILEHEADER bf;
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
// read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bi;
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
// ensure infile is (likely) a 24-bit uncompressed BMP 4.0
if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
bi.biBitCount != 24 || bi.biCompression != 0)
{
fclose(outptr);
fclose(inptr);
printf("Unsupported file format.\n");
return 6;
}
int height = abs(bi.biHeight);
int width = bi.biWidth;
// allocate memory for image
RGBTRIPLE (*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));
if (image == NULL)
{
printf("Not enough memory to store image.\n");
fclose(outptr);
fclose(inptr);
return 7;
}
// determine padding for scanlines
int padding = (4 - (width * sizeof(RGBTRIPLE)) % 4) % 4;
// iterate over infile's scanlines
for (int i = 0; i < height; i++)
{
// read row into pixel array
fread(image[i], sizeof(RGBTRIPLE), width, inptr);
// skip over padding
fseek(inptr, padding, SEEK_CUR);
}
colorize(height, width, image);
// write outfile's BITMAPFILEHEADER
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// write new pixels to outfile
for (int i = 0; i < height; i++)
{
// write row to outfile
fwrite(image[i], sizeof(RGBTRIPLE), width, outptr);
// write padding at end of row
for (int k = 0; k < padding; k++)
{
fputc(0x00, outptr);
}
}
// free memory for image
free(image);
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
return 0;
}
+15
View File
@@ -0,0 +1,15 @@
#include "helpers.h"
void colorize(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (image[i][j].rgbtRed == 0x00 && image[i][j].rgbtGreen == 0x00 && image[i][j].rgbtBlue == 0x00)
{
image[i][j].rgbtBlue = 0xf0;
}
}
}
}
+5
View File
@@ -0,0 +1,5 @@
#include "bmp.h"
// colorize image
void colorize(int height, int width, RGBTRIPLE image[height][width]);