0% found this document useful (0 votes)
60 views9 pages

Latihan Filter Gambar

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
60 views9 pages

Latihan Filter Gambar

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

h"ps://cs50.harvard.

edu/indonesia/2023/psets/4/filter/less/

Buat Folder Filter

Buat File : bmp.h

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

Kemudian buat file : helpers.h

#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]);

Kemudian buat file : helpers.c

#include "helpers.h"
#include "math.h"

// Convert image to grayscale


void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
// Iterate through each column of pixel
for (int i = 0; i < height; i++)
{
// Iterate through each row of pixel in each column
for (int j = 0; j < width; j++)
{
// Get into 2D array and obtain value of each color
int originalred = image[i][j].rgbtRed;
int originalgreen = image[i][j].rgbtGreen;
int originalblue = image[i][j].rgbtBlue;

// Calculate the rounded avarage of each pixel


int avg = round(((float)originalred + (float)originalgreen +
(float)originalblue) / 3);

// Set the calculated value to be the new value of each pixel


image[i][j].rgbtRed = image[i][j].rgbtGreen = image[i][j].rgbtBlue = avg;
}
}
return;
}

// Convert image to sepia


void sepia(int height, int width, RGBTRIPLE image[height][width])
{
// Iterate through each column of pixel
for (int i = 0; i < height; i++)
{
// Iterate through each row of pixel in each column
for (int j = 0; j < width; j++)
{
// Get into 2D array and obtain value of each color
int originalred = image[i][j].rgbtRed;
int originalgreen = image[i][j].rgbtGreen;
int originalblue = image[i][j].rgbtBlue;

// New sepia value


int sepiaRed = round(0.393 * originalred + 0.769 * originalgreen + 0.189 *
originalblue);
int sepiaGreen = round(0.349 * originalred + 0.686 * originalgreen + 0.168
* originalblue);
int sepiaBlue = round(0.272 * originalred + 0.534 * originalgreen + 0.131
* originalblue);

if (sepiaRed > 255)


{
image[i][j].rgbtRed = 255;
}
else
{
image[i][j].rgbtRed = sepiaRed;
}

if (sepiaGreen > 255)


{
image[i][j].rgbtGreen = 255;
}
else
{
image[i][j].rgbtGreen = sepiaGreen;
}

if (sepiaBlue > 255)


{
image[i][j].rgbtBlue = 255;
}
else
{
image[i][j].rgbtBlue = sepiaBlue;
}
}
}
return;
}

// Reflect image horizontally


void reflect(int height, int width, RGBTRIPLE image[height][width])
{
// Iterate through each column of pixel
for (int i = 0; i < height; i++)
{
// iterate through the array until you get to the mid-point
for (int j = 0; j < (width / 2); j++)
{
RGBTRIPLE temp = image[i][j];
image[i][j] = image[i][width - (j + 1)];
image[i][width - (j + 1)] = temp;
}
}
return;
}

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
// Create a temporary image to implement blurred algorithm on it
RGBTRIPLE temp[height][width];
// Iterate through each column of pixel
for (int i = 0; i < height; i++)
{
// Iterate through each row of pixel in each column
for (int j = 0; j < width; j++)
{
int sumRed, sumBlue, sumGreen;
sumRed = sumBlue = sumGreen = 0;
float counter = 0.00;

// Get the neighbouring pixels


for (int c = -1; c < 2; c++)
{
for (int r = -1; r < 2; r++)
{
int currentX = i + c;
int currentY = j + r;

// Check for valid neighbouring pixels


if (currentX < 0 || currentX > (height - 1) || currentY < 0 ||
currentY > (width - 1))
{
continue;
}

// Get the image value


sumRed += image[currentX][currentY].rgbtRed;
sumGreen += image[currentX][currentY].rgbtGreen;
sumBlue += image[currentX][currentY].rgbtBlue;
counter++;
}

// Do the average of neigbhouring pixels


temp[i][j].rgbtRed = round(sumRed / counter);
temp[i][j].rgbtGreen = round(sumGreen / counter);
temp[i][j].rgbtBlue = round(sumBlue / counter);
}
}
}

// Copy the blur image to the original image


// Iterate through each column of pixel
for (int i = 0; i < height; i++)
{
// Iterate through each row of pixel in each column
for (int j = 0; j < width; j++)
{
image[i][j].rgbtRed = temp[i][j].rgbtRed;
image[i][j].rgbtGreen = temp[i][j].rgbtGreen;
image[i][j].rgbtBlue = temp[i][j].rgbtBlue;
}
}
return;
}

Terakhir buat file : filter.c

#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;
}

You might also like