-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
366 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
filter: | ||
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 filter filter.c helpers.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include<stdio.h> | ||
int main() | ||
{ | ||
int i=0,j=0, k,l,box=0; | ||
for ( k = -1; k < 2; k++) | ||
{ | ||
for ( l = -1; l < 2; l++) | ||
{ | ||
printf(" %d %d ",i+k,j+l); | ||
box++; | ||
|
||
} | ||
} | ||
printf("box=%d\n",box); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
#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 == '?') | ||
{ | ||
fprintf(stderr, "Invalid filter.\n"); | ||
return 1; | ||
} | ||
|
||
// Ensure only one filter | ||
if (getopt(argc, argv, filters) != -1) | ||
{ | ||
fprintf(stderr, "Only one filter allowed.\n"); | ||
return 2; | ||
} | ||
|
||
// Ensure proper usage | ||
if (argc != optind + 2) | ||
{ | ||
fprintf(stderr, "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) | ||
{ | ||
fprintf(stderr, "Could not open %s.\n", infile); | ||
return 4; | ||
} | ||
|
||
// Open output file | ||
FILE *outptr = fopen(outfile, "w"); | ||
if (outptr == NULL) | ||
{ | ||
fclose(inptr); | ||
fprintf(stderr, "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); | ||
fprintf(stderr, "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) | ||
{ | ||
fprintf(stderr, "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 infile | ||
fclose(inptr); | ||
|
||
// Close outfile | ||
fclose(outptr); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
#include "helpers.h" | ||
#include <math.h> | ||
#include <stdio.h> | ||
// Convert image to grayscale | ||
void grayscale(int height, int width, RGBTRIPLE image[height][width]) | ||
{ | ||
for(int i=0;i<height;i++) | ||
{ | ||
for(int j=0;j<width;j++) | ||
{ | ||
BYTE sum=(image[i][j].rgbtRed+image[i][j].rgbtGreen+image[i][j].rgbtBlue)/3; | ||
image[i][j].rgbtRed=image[i][j].rgbtGreen=image[i][j].rgbtBlue=sum; | ||
} | ||
} | ||
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 Red = round(.393 * image[i][j].rgbtRed + .769 * image[i][j].rgbtGreen + .189 * image[i][j].rgbtBlue); | ||
int Green =round( .349 * image[i][j].rgbtRed + .686 * image[i][j].rgbtGreen + .168 * image[i][j].rgbtBlue); | ||
int Blue= round(.272 * image[i][j].rgbtRed + .534 * image[i][j].rgbtGreen + .131 * image[i][j].rgbtBlue); | ||
|
||
if(Red>255) | ||
image[i][j].rgbtRed=255; | ||
else image[i][j].rgbtRed=Red; | ||
if(Green>255) | ||
image[i][j].rgbtGreen=255; | ||
else image[i][j].rgbtGreen=Green; | ||
if(Blue>255) | ||
image[i][j].rgbtBlue=255; | ||
else image[i][j].rgbtBlue=Blue; | ||
|
||
} | ||
} | ||
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++) | ||
{ | ||
int k=width-1-j; | ||
BYTE tmp; | ||
tmp=image[i][k].rgbtRed; | ||
image[i][k].rgbtRed=image[i][j].rgbtRed; | ||
image[i][j].rgbtRed=tmp; | ||
|
||
tmp=image[i][k].rgbtGreen; | ||
image[i][k].rgbtGreen=image[i][j].rgbtGreen; | ||
image[i][j].rgbtGreen=tmp; | ||
|
||
tmp=image[i][k].rgbtBlue; | ||
image[i][k].rgbtBlue=image[i][j].rgbtBlue; | ||
image[i][j].rgbtBlue=tmp; | ||
} | ||
} | ||
|
||
return; | ||
} | ||
|
||
// Blur image | ||
void blur(int height, int width, RGBTRIPLE image[height][width]) | ||
{ | ||
RGBTRIPLE imagecp[height][width]; | ||
for(int i=0;i<height;i++) | ||
{ | ||
for(int j=0;j<width;j++) | ||
{ | ||
imagecp[i][j]=image[i][j]; | ||
} | ||
} | ||
|
||
for(int i=0;i<height;i++) | ||
{ | ||
for(int j=0;j<width;j++) | ||
{ | ||
int k,l,box=0; | ||
BYTE sumR=0,sumG=0,sumB=0; | ||
for ( k = -1; k < 2; k++) | ||
{ | ||
for ( l = -1; l < 2; l++) | ||
{ | ||
if (i+k>-1 && j+l>-1 && i+k<height && j+l<width) | ||
{ | ||
sumR=sumR+imagecp[i+k][j+l].rgbtRed; | ||
sumG=sumG+imagecp[i+k][j+l].rgbtGreen; | ||
sumB=sumB+imagecp[i+k][j+l].rgbtBlue; | ||
box++; | ||
} | ||
|
||
} | ||
} | ||
image[i][j].rgbtRed=round(sumR/box); | ||
image[i][j].rgbtGreen=round(sumG/box); | ||
image[i][j].rgbtBlue=round(sumB/box); | ||
} | ||
} | ||
return; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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]); |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.