Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions image.c → image_mp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
#include <stdint.h>
#include <time.h>
#include <string.h>
#include "image.h"

#include <omp.h>
#include "image_mp.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

Expand Down Expand Up @@ -56,9 +55,11 @@ uint8_t getPixelValue(Image* srcImage,int x,int y,int bit,Matrix algorithm){
// destImage: A pointer to a pre-allocated (including space for the pixel array) structure to receive the convoluted image. It should be the same size as srcImage
// algorithm: The kernel matrix to use for the convolution
//Returns: Nothing

void convolute(Image* srcImage,Image* destImage,Matrix algorithm){
int row,pix,bit,span;
span=srcImage->bpp*srcImage->bpp;
#pragma omp parallel for schedule(static) private(pix, bit)
for (row=0;row<srcImage->height;row++){
for (pix=0;pix<srcImage->width;pix++){
for (bit=0;bit<srcImage->bpp;bit++){
Expand Down
File renamed without changes.
163 changes: 163 additions & 0 deletions image_pt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include "image_pt.h"

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

int thread_count;
pthread_t* thread_handles;

typedef struct {
Image* srcImage;
Image* destImage;
Matrix* algorithm;
int rank;
} ThreadArgs;
//An array of kernel matrices to be used for image convolution.
//The indexes of these match the enumeration from the header file. ie. algorithms[BLUR] returns the kernel corresponding to a box blur.
Matrix algorithms[]={
{{0,-1,0},{-1,4,-1},{0,-1,0}},
{{0,-1,0},{-1,5,-1},{0,-1,0}},
{{1/9.0,1/9.0,1/9.0},{1/9.0,1/9.0,1/9.0},{1/9.0,1/9.0,1/9.0}},
{{1.0/16,1.0/8,1.0/16},{1.0/8,1.0/4,1.0/8},{1.0/16,1.0/8,1.0/16}},
{{-2,-1,0},{-1,1,1},{0,1,2}},
{{0,0,0},{0,1,0},{0,0,0}}
};


//getPixelValue - Computes the value of a specific pixel on a specific channel using the selected convolution kernel
//Paramters: srcImage: An Image struct populated with the image being convoluted
// x: The x coordinate of the pixel
// y: The y coordinate of the pixel
// bit: The color channel being manipulated
// algorithm: The 3x3 kernel matrix to use for the convolution
//Returns: The new value for this x,y pixel and bit channel
uint8_t getPixelValue(Image* srcImage,int x,int y,int bit,Matrix algorithm){
int px,mx,py,my,i,span;
span=srcImage->width*srcImage->bpp;
// for the edge pixes, just reuse the edge pixel
px=x+1; py=y+1; mx=x-1; my=y-1;
if (mx<0) mx=0;
if (my<0) my=0;
if (px>=srcImage->width) px=srcImage->width-1;
if (py>=srcImage->height) py=srcImage->height-1;
uint8_t result=
algorithm[0][0]*srcImage->data[Index(mx,my,srcImage->width,bit,srcImage->bpp)]+
algorithm[0][1]*srcImage->data[Index(x,my,srcImage->width,bit,srcImage->bpp)]+
algorithm[0][2]*srcImage->data[Index(px,my,srcImage->width,bit,srcImage->bpp)]+
algorithm[1][0]*srcImage->data[Index(mx,y,srcImage->width,bit,srcImage->bpp)]+
algorithm[1][1]*srcImage->data[Index(x,y,srcImage->width,bit,srcImage->bpp)]+
algorithm[1][2]*srcImage->data[Index(px,y,srcImage->width,bit,srcImage->bpp)]+
algorithm[2][0]*srcImage->data[Index(mx,py,srcImage->width,bit,srcImage->bpp)]+
algorithm[2][1]*srcImage->data[Index(x,py,srcImage->width,bit,srcImage->bpp)]+
algorithm[2][2]*srcImage->data[Index(px,py,srcImage->width,bit,srcImage->bpp)];
return result;
}

//convolute: Applies a kernel matrix to an image
//Parameters: srcImage: The image being convoluted
// destImage: A pointer to a pre-allocated (including space for the pixel array) structure to receive the convoluted image. It should be the same size as srcImage
// algorithm: The kernel matrix to use for the convolution
//Returns: Nothing
void* convolute(void* rank) {
ThreadArgs* args = (ThreadArgs*) rank;
Image* srcImage = args->srcImage;
Image* destImage = args->destImage;
Matrix* algorithm = args->algorithm;
int thread_rank = args->rank;

int rows_per_thread = srcImage->height / thread_count;
int start_row = thread_rank * rows_per_thread;
int end_row = (thread_rank == thread_count - 1) ? srcImage->height : start_row + rows_per_thread;

for (int row = start_row; row < end_row; row++) {
for (int pix = 0; pix < srcImage->width; pix++) {
for (int bit = 0; bit < srcImage->bpp; bit++) {
destImage->data[Index(pix, row, srcImage->width, bit, srcImage->bpp)] = getPixelValue(srcImage, pix, row, bit, *algorithm);
}
}
}
return NULL;
}



//Usage: Prints usage information for the program
//Returns: -1
int Usage(){
printf("Usage: image <filename> <type>\n\twhere type is one of (edge,sharpen,blur,gauss,emboss,identity)\n");
return -1;
}

//GetKernelType: Converts the string name of a convolution into a value from the KernelTypes enumeration
//Parameters: type: A string representation of the type
//Returns: an appropriate entry from the KernelTypes enumeration, defaults to IDENTITY, which does nothing but copy the image.
enum KernelTypes GetKernelType(char* type){
if (!strcmp(type,"edge")) return EDGE;
else if (!strcmp(type,"sharpen")) return SHARPEN;
else if (!strcmp(type,"blur")) return BLUR;
else if (!strcmp(type,"gauss")) return GAUSE_BLUR;
else if (!strcmp(type,"emboss")) return EMBOSS;
else return IDENTITY;
}

//main:
//argv is expected to take 2 arguments. First is the source file name (can be jpg, png, bmp, tga). Second is the lower case name of the algorithm.
int main(int argc,char** argv){
long t1,t2;
t1=time(NULL);

stbi_set_flip_vertically_on_load(0);
if (argc!=3) return Usage();
char* fileName=argv[1];
if (!strcmp(argv[1],"pic4.jpg")&&!strcmp(argv[2],"gauss")){
printf("You have applied a gaussian filter to Gauss which has caused a tear in the time-space continum.\n");
}
enum KernelTypes type=GetKernelType(argv[2]);

Image srcImage,destImage,bwImage;
srcImage.data=stbi_load(fileName,&srcImage.width,&srcImage.height,&srcImage.bpp,0);
if (!srcImage.data){
printf("Error loading file %s.\n",fileName);
return -1;
}
destImage.bpp=srcImage.bpp;
destImage.height=srcImage.height;
destImage.width=srcImage.width;
destImage.data=malloc(sizeof(uint8_t)*destImage.width*destImage.bpp*destImage.height);

thread_count = 16;
thread_handles = malloc(thread_count * sizeof(pthread_t));

ThreadArgs* args = malloc(thread_count * sizeof(ThreadArgs));

for (int i = 0; i < thread_count; i++) {
args[i].srcImage = &srcImage;
args[i].destImage = &destImage;
args[i].algorithm = &algorithms[type];
args[i].rank = i;
pthread_create(&thread_handles[i], NULL, convolute, &args[i]);
}

for (int i = 0; i < thread_count; i++) {
pthread_join(thread_handles[i], NULL);
}

stbi_write_png("output.png",destImage.width,destImage.height,destImage.bpp,destImage.data,destImage.bpp*destImage.width);
stbi_image_free(srcImage.data);

free(destImage.data);
free(thread_handles);
free(args);
t2=time(NULL);
printf("Took %ld seconds\n",t2-t1);
return 0;
}
23 changes: 23 additions & 0 deletions image_pt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef ___IMAGE
#define ___IMAGE
#include <stdint.h>

#define Index(x,y,width,bit,bpp) y*width*bpp+bpp*x+bit

typedef struct{
uint8_t* data;
int width;
int height;
int bpp;
} Image;

enum KernelTypes{EDGE=0,SHARPEN=1,BLUR=2,GAUSE_BLUR=3,EMBOSS=4,IDENTITY=5};

typedef double Matrix[3][3];

uint8_t getPixelValue(Image* srcImage,int x,int y,int bit,Matrix algorithm);
void* convolute(void* rank);
int Usage();
enum KernelTypes GetKernelType(char* type);

#endif
Binary file added output.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Script started on Mon Oct 30 18:41:15 2023
^[]0;jhcoop@r1n10.darwin:~/CISC372_picProject^G^[[?1034h[jhcoop@r1n10 CISC372_picProject]$ srun ima$
Took 6 seconds
^[]0;jhcoop@r1n10.darwin:~/CISC372_picProject^G[jhcoop@r1n10 CISC372_picProject]$ srun image_pt pic$
Took 6 seconds
^[]0;jhcoop@r1n10.darwin:~/CISC372_picProject^G[jhcoop@r1n10 CISC372_picProject]$ exit
exit

Script done on Mon Oct 30 18:41:57 2023