Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
The content of filter.c is courtesy of Tekky, based in part on a file of the
same name from Harvard's CS50x.
The definitions of the BMP headers and RGBTRIPLE added to filter.h are
directly from CS50x's bmp.h.

N.B. This challenge and it's code have been structured in such a way that it
must not breach the academic honesty policy of CS50x.
  • Loading branch information
bolt committed Jan 12, 2025
0 parents commit 11a1531
Show file tree
Hide file tree
Showing 7 changed files with 8,216 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
filter
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
CC := clang

CFLAGS := -march=native -std=c18 -Wall -Wextra -pthread
CFLAGS_debug := -O0 -ggdb3 -gdwarf-4
CFLAGS_release := -O3

LDFLAGS := -lm

all: release

debug: CFLAGS += $(CFLAGS_debug)
debug: filter
release: CFLAGS += $(CFLAGS_release)
release: filter

filter: filter.c filter.h
$(CC) $(CFLAGS) -o $@ filter.c $(LDFLAGS)

.PHONY: release debug
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Fast Blur Challenge

Implement the `blur()` function in `blur.c`. Make it as fast as possible.

## Rules

1.

## DEADLINE

18 Jan 17:00pm UTC.
(Temporarily subject to alteration.)
9 changes: 9 additions & 0 deletions blur.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* TODO: Implement
*/
void
blur(uint32_t height, uint32_t width, RGBTRIPLE input[height][width],
RGBTRIPLE output[height][width], uint32_t size)
{
}

115 changes: 115 additions & 0 deletions filter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#define _DEFAULT_SOURCE

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/time.h>

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#include "filter.h"
#include "blur.c"

#define BLUR_SIZE 3

int main( int argc, char *argv[] )
{
BITMAPFILEHEADER bf = { 0x4D42, 0, 0, 0, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) };
BITMAPINFOHEADER bi = { sizeof(BITMAPINFOHEADER), 0, 0, 1, 24, 0, 0, 11811, 11811, 0, 0 };
int width, height, num_channels;
struct rusage before, after;
struct timeval total_before, total_after, difference;

// check for correct number of arguments
if ( argc != 3 )
{
fprintf( stderr, "Usage: %s [inputfile] [outputfile]\n", argv[0] != NULL ? argv[0] : "filter" );
exit( EXIT_FAILURE );
}

// open and decode input file
unsigned char *input = stbi_load( argv[1], &width, &height, &num_channels, 3 );
if ( input == NULL )
{
fprintf( stderr, "Error opening/decoding input file!\n" );
exit( EXIT_FAILURE );
}

// change RGB channel order to BGR
for ( int i = 0; i < width * height * 3; i += 3 )
{
unsigned char temp = input[i];
input[i] = input[i+2];
input[i+2] = temp;
}

// allocate memory output bitmap data
RGBTRIPLE(*output)[width] = calloc( height * width, sizeof(RGBTRIPLE) );
if ( output == NULL )
{
fprintf( stderr, "Error allocating memory for output image data!\n" );
exit( EXIT_FAILURE );
}

// perform the actual function call to blur
fprintf( stderr, "Calling function blur..." );
getrusage( RUSAGE_SELF, &before );
blur( height, width, (RGBTRIPLE(*)[width])input, output, BLUR_SIZE );
getrusage( RUSAGE_SELF, &after );
fprintf( stderr, "finished.\n" );

// free input image
stbi_image_free( input );

// calculate difference between starting time and ending time
timeradd( &before.ru_utime, &before.ru_stime, &total_before );
timeradd( & after.ru_utime, & after.ru_stime, &total_after );
timersub( &total_after, &total_before, &difference );

// print rusage data
fprintf
(
stderr,
"Elapsed time: %.5f seconds\n",
( difference.tv_sec * 1000 * 1000 + difference.tv_usec ) / ( 1000.0 * 1000.0)
);

// open output file
FILE *fp = fopen( argv[2], "wb" );
if ( fp == NULL )
{
fprintf( stderr, "Error opening output file!\n" );
exit( EXIT_FAILURE );
}

// calculating amount of padding
int padding = ( 4 - ( width * sizeof(RGBTRIPLE) ) % 4 ) % 4;

// write headers to output file
bf.bfSize = bf.bfOffBits + ( ( sizeof(RGBTRIPLE) * width ) + padding ) * height;
bi.biWidth = width;
bi.biHeight = -height;
fwrite( &bf, sizeof bf, 1, fp );
fwrite( &bi, sizeof bi, 1, fp );

// write bitmap data to output file
for ( int i = 0; i < height; i++ )
{
fwrite( output[i], sizeof(RGBTRIPLE), width, fp );

// add padding
for ( int j = 0; j < padding; j++ )
{
putc( 0x00, fp );
}
}

// close output file
fclose(fp);

// free output bitmap data
free( output );
}
72 changes: 72 additions & 0 deletions filter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include <stdint.h>

/* -------------------------------------------------------------------------- */

// BMP-related data types based on Microsoft's own

// 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;

/* -------------------------------------------------------------------------- */

/*
* Box-blur image and store the result in output.
*
* image is expected to point to a region of memory with pixel data for
* (height * width) RGBTRIPLE's.
* output is expected to point to a writable region of memory with a size of
* height * width * sizeof(RGBTRIPLE).
* size denotes the box blur radius.
*/
void blur(uint32_t height, uint32_t width, RGBTRIPLE input[height][width], RGBTRIPLE output[height][width], uint32_t size);
Loading

0 comments on commit 11a1531

Please sign in to comment.