added ws202425 courses
This commit is contained in:
@@ -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
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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]
|
||||
@@ -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]);
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "bmp.h"
|
||||
|
||||
// colorize image
|
||||
void colorize(int height, int width, RGBTRIPLE image[height][width]);
|
||||
|
||||
Reference in New Issue
Block a user