I am attempting to perform Median Filter with size 3 x 3 in C language. The function MedianFilter33
has been implemented as follows.
The experimental implementation
The basic structures:
typedef struct RGB { unsigned char R, G, B; } RGB; typedef struct BMPIMAGE { char FILENAME[MAX_PATH]; unsigned int XSIZE; unsigned int YSIZE; unsigned char FILLINGBYTE; unsigned char *IMAGE_DATA; } BMPIMAGE; typedef struct RGBIMAGE { unsigned int XSIZE; unsigned int YSIZE; RGB *IMAGE_DATA; } RGBIMAGE;
MedianFilter33
function implementation:RGB *MedianFilter33(const RGB *image,const int xsize,const int ysize) { RGB *output; output = (RGB*)malloc(xsize * ysize * sizeof(RGB)); if (output == NULL) { printf("Memory allocation error!"); return NULL; } for(long long int i = 0; i <(xsize * ysize); i++) { if( (i < xsize) || ( (i % xsize) == 0) || ( ((i + 1) % xsize) == 0) || (i >= (xsize*(ysize-1)))) { output[i].R = image[i].R; output[i].G = image[i].G; output[i].B = image[i].B; } else { unsigned char *sort_array; sort_array = (unsigned char*)malloc(9 * sizeof(unsigned char)); // R channel sorting sort_array[0] = image[i-xsize-1].R; sort_array[1] = image[i-xsize].R; sort_array[2] = image[i-xsize+1].R; sort_array[3] = image[i-1].R; sort_array[4] = image[i].R; sort_array[5] = image[i+1].R; sort_array[6] = image[i+xsize-1].R; sort_array[7] = image[i+xsize].R; sort_array[8] = image[i+xsize+1].R; sort_array = bubble_sort_uchar(sort_array,9,0); output[i].R = sort_array[4]; // G channel sorting sort_array[0] = image[i-xsize-1].G; sort_array[1] = image[i-xsize].G; sort_array[2] = image[i-xsize+1].G; sort_array[3] = image[i-1].G; sort_array[4] = image[i].G; sort_array[5] = image[i+1].G; sort_array[6] = image[i+xsize-1].G; sort_array[7] = image[i+xsize].G; sort_array[8] = image[i+xsize+1].G; bubble_sort_uchar(sort_array,9,0); output[i].G = sort_array[4]; // B channel sorting sort_array[0] = image[i-xsize-1].B; sort_array[1] = image[i-xsize].B; sort_array[2] = image[i-xsize+1].B; sort_array[3] = image[i-1].B; sort_array[4] = image[i].B; sort_array[5] = image[i+1].B; sort_array[6] = image[i+xsize-1].B; sort_array[7] = image[i+xsize].B; sort_array[8] = image[i+xsize+1].B; bubble_sort_uchar(sort_array,9,0); output[i].B = sort_array[4]; } } return output; }
Full Testing Code
In order to test MedianFilter33
function implementation above, a tiny bmp
image read / write framework has been performed.
/* Develop by Jimmy Hu */
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAX_PATH 256
#define FILE_ROOT_PATH "./"
#define True true
#define False false
typedef struct RGB
{
unsigned char R, G, B;
} RGB;
typedef struct BMPIMAGE
{
char FILENAME[MAX_PATH];
unsigned int XSIZE;
unsigned int YSIZE;
unsigned char FILLINGBYTE;
unsigned char *IMAGE_DATA;
} BMPIMAGE;
typedef struct RGBIMAGE
{
unsigned int XSIZE;
unsigned int YSIZE;
RGB *IMAGE_DATA;
} RGBIMAGE;
RGB *MedianFilter33(const RGB*, const int x, const int y);
RGB *raw_image_to_array(const unsigned char *image, const int xsize, const int ysize);
unsigned long bmp_read_x_size(const char *filename, const bool extension);
unsigned long bmp_read_y_size(const char *filename, const bool extension);
char bmp_read(unsigned char *image, const int xsize, const int ysize, const char *filename, const bool extension);
BMPIMAGE bmp_file_read(const char *filename, const bool extension);
int bmp_write(const unsigned char *image, const int xsize, const int ysize, const char *filename);
unsigned char *array_to_raw_image(const RGB* InputData, const int xsize, const int ysize);
unsigned char bmp_filling_byte_calc(const unsigned int xsize);
unsigned char *bubble_sort_uchar( const unsigned char *data_input,
const unsigned long long int data_input_count,
const bool mode);
int main(int argc, char** argv)
{
printf("BMP image file name:(ex:test): ");
char *FilenameString;
FilenameString = (char*)malloc( MAX_PATH * sizeof(char) );
scanf("%s",FilenameString);
BMPIMAGE BMPImage1;
BMPImage1 = bmp_file_read(FilenameString,false);
free(FilenameString);
printf("%s\n",BMPImage1.FILENAME);
if(BMPImage1.IMAGE_DATA == NULL)
{
printf("Image contents error!");
return -1;
}
RGBIMAGE RGBImage1;
RGBImage1.XSIZE = BMPImage1.XSIZE;
RGBImage1.YSIZE = BMPImage1.YSIZE;
RGBImage1.IMAGE_DATA = (RGB*)malloc(RGBImage1.XSIZE * RGBImage1.YSIZE * sizeof(RGB));
if (RGBImage1.IMAGE_DATA == NULL)
{
printf("Memory allocation error!");
return -1;
}
RGBImage1.IMAGE_DATA = raw_image_to_array(BMPImage1.IMAGE_DATA, BMPImage1.XSIZE, BMPImage1.YSIZE);
bmp_write(array_to_raw_image(MedianFilter33(RGBImage1.IMAGE_DATA,RGBImage1.XSIZE, RGBImage1.YSIZE), RGBImage1.XSIZE, RGBImage1.YSIZE), BMPImage1.XSIZE, BMPImage1.YSIZE, "MedianFilterOutput");
return 0;
}
RGB *MedianFilter33(const RGB *image,const int xsize,const int ysize)
{
RGB *output;
output = (RGB*)malloc(xsize * ysize * sizeof(RGB));
if (output == NULL)
{
printf("Memory allocation error!");
return NULL;
}
for(long long int i = 0; i <(xsize * ysize); i++)
{
if( (i < xsize) || ( (i % xsize) == 0) || ( ((i + 1) % xsize) == 0) || (i >= (xsize*(ysize-1))))
{
output[i].R = image[i].R;
output[i].G = image[i].G;
output[i].B = image[i].B;
}
else
{
unsigned char *sort_array;
sort_array = (unsigned char*)malloc(9 * sizeof(unsigned char));
// R channel sorting
sort_array[0] = image[i-xsize-1].R;
sort_array[1] = image[i-xsize].R;
sort_array[2] = image[i-xsize+1].R;
sort_array[3] = image[i-1].R;
sort_array[4] = image[i].R;
sort_array[5] = image[i+1].R;
sort_array[6] = image[i+xsize-1].R;
sort_array[7] = image[i+xsize].R;
sort_array[8] = image[i+xsize+1].R;
sort_array = bubble_sort_uchar(sort_array,9,0);
output[i].R = sort_array[4];
// G channel sorting
sort_array[0] = image[i-xsize-1].G;
sort_array[1] = image[i-xsize].G;
sort_array[2] = image[i-xsize+1].G;
sort_array[3] = image[i-1].G;
sort_array[4] = image[i].G;
sort_array[5] = image[i+1].G;
sort_array[6] = image[i+xsize-1].G;
sort_array[7] = image[i+xsize].G;
sort_array[8] = image[i+xsize+1].G;
bubble_sort_uchar(sort_array,9,0);
output[i].G = sort_array[4];
// B channel sorting
sort_array[0] = image[i-xsize-1].B;
sort_array[1] = image[i-xsize].B;
sort_array[2] = image[i-xsize+1].B;
sort_array[3] = image[i-1].B;
sort_array[4] = image[i].B;
sort_array[5] = image[i+1].B;
sort_array[6] = image[i+xsize-1].B;
sort_array[7] = image[i+xsize].B;
sort_array[8] = image[i+xsize+1].B;
bubble_sort_uchar(sort_array,9,0);
output[i].B = sort_array[4];
}
}
return output;
}
RGB *raw_image_to_array(const unsigned char *image, const int xsize, const int ysize)
{
RGB *output;
output = (RGB*)malloc(xsize * ysize * sizeof(RGB));
if(output == NULL)
{
printf("Memory allocation error!");
return NULL;
}
unsigned char FillingByte;
FillingByte = bmp_filling_byte_calc(xsize);
for(int y = 0;y<ysize;y++)
{
for(int x = 0;x<xsize;x++)
{
output[y*xsize + x].R =
image[3*(y * xsize + x) + y * FillingByte + 2];
output[y*xsize + x].G =
image[3*(y * xsize + x) + y * FillingByte + 1];
output[y*xsize + x].B =
image[3*(y * xsize + x) + y * FillingByte + 0];
}
}
return output;
}
//----bmp_read_x_size function----
unsigned long bmp_read_x_size(const char *filename, const bool extension)
{
char fname_bmp[MAX_PATH];
if(extension == false)
{
sprintf(fname_bmp, "%s.bmp", filename);
}
else
{
strcpy(fname_bmp,filename);
}
FILE *fp;
fp = fopen(fname_bmp, "rb");
if (fp == NULL)
{
printf("Fail to read file!\n");
return -1;
}
unsigned char header[54];
fread(header, sizeof(unsigned char), 54, fp);
unsigned long output;
output = header[18] + (header[19] << 8) + ( header[20] << 16) + ( header[21] << 24);
fclose(fp);
return output;
}
//---- bmp_read_y_size function ----
unsigned long bmp_read_y_size(const char *filename, const bool extension)
{
char fname_bmp[MAX_PATH];
if(extension == false)
{
sprintf(fname_bmp, "%s.bmp", filename);
}
else
{
strcpy(fname_bmp,filename);
}
FILE *fp;
fp = fopen(fname_bmp, "rb");
if (fp == NULL)
{
printf("Fail to read file!\n");
return -1;
}
unsigned char header[54];
fread(header, sizeof(unsigned char), 54, fp);
unsigned long output;
output= header[22] + (header[23] << 8) + ( header[24] << 16) + ( header[25] << 24);
fclose(fp);
return output;
}
//---- bmp_file_read function ----
char bmp_read(unsigned char *image, const int xsize, const int ysize, const char *filename, const bool extension)
{
char fname_bmp[MAX_PATH];
if(extension == false)
{
sprintf(fname_bmp, "%s.bmp", filename);
}
else
{
strcpy(fname_bmp,filename);
}
unsigned char filling_bytes;
filling_bytes = bmp_filling_byte_calc(xsize);
FILE *fp;
fp = fopen(fname_bmp, "rb");
if (fp==NULL)
{
printf("Fail to read file!\n");
return -1;
}
unsigned char header[54];
fread(header, sizeof(unsigned char), 54, fp);
fread(image, sizeof(unsigned char), (size_t)(long)(xsize * 3 + filling_bytes)*ysize, fp);
fclose(fp);
return 0;
}
BMPIMAGE bmp_file_read(const char *filename, const bool extension)
{
BMPIMAGE output;
stpcpy(output.FILENAME, "");
output.XSIZE = 0;
output.YSIZE = 0;
output.IMAGE_DATA = NULL;
if(filename == NULL)
{
printf("Path is null\n");
return output;
}
char fname_bmp[MAX_PATH];
if(extension == false)
{
sprintf(fname_bmp, "%s.bmp", filename);
}
else
{
strcpy(fname_bmp,filename);
}
FILE *fp;
fp = fopen(fname_bmp, "rb");
if (fp == NULL)
{
printf("Fail to read file!\n");
return output;
}
stpcpy(output.FILENAME, fname_bmp);
output.XSIZE = (unsigned int)bmp_read_x_size(output.FILENAME,true);
output.YSIZE = (unsigned int)bmp_read_y_size(output.FILENAME,true);
if( (output.XSIZE == -1) || (output.YSIZE == -1) )
{
printf("Fail to fetch information of image!");
return output;
}
else
{
printf("Width of the input image: %d\n",output.XSIZE);
printf("Height of the input image: %d\n",output.YSIZE);
printf("Size of the input image(Byte): %d\n",(size_t)output.XSIZE * output.YSIZE * 3);
output.FILLINGBYTE = bmp_filling_byte_calc(output.XSIZE);
output.IMAGE_DATA = (unsigned char*)malloc((output.XSIZE * 3 + output.FILLINGBYTE) * output.YSIZE * sizeof(unsigned char));
if (output.IMAGE_DATA == NULL)
{
printf("Memory allocation error!");
return output;
}
else
{
for(int i = 0; i < ((output.XSIZE * 3 + output.FILLINGBYTE) * output.YSIZE);i++)
{
output.IMAGE_DATA[i] = 255;
}
bmp_read(output.IMAGE_DATA, output.XSIZE, output.YSIZE, output.FILENAME, true);
}
}
return output;
}
//----bmp_write function----
int bmp_write(const unsigned char *image, const int xsize, const int ysize, const char *filename)
{
unsigned char FillingByte;
FillingByte = bmp_filling_byte_calc(xsize);
unsigned char header[54] =
{
0x42, 0x4d, 0, 0, 0, 0, 0, 0, 0, 0,
54, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0
};
unsigned long file_size = (long)xsize * (long)ysize * 3 + 54;
unsigned long width, height;
char fname_bmp[MAX_PATH];
header[2] = (unsigned char)(file_size &0x000000ff);
header[3] = (file_size >> 8) & 0x000000ff;
header[4] = (file_size >> 16) & 0x000000ff;
header[5] = (file_size >> 24) & 0x000000ff;
width = xsize;
header[18] = width & 0x000000ff;
header[19] = (width >> 8) &0x000000ff;
header[20] = (width >> 16) &0x000000ff;
header[21] = (width >> 24) &0x000000ff;
height = ysize;
header[22] = height &0x000000ff;
header[23] = (height >> 8) &0x000000ff;
header[24] = (height >> 16) &0x000000ff;
header[25] = (height >> 24) &0x000000ff;
sprintf(fname_bmp, "%s.bmp", filename);
FILE *fp;
if (!(fp = fopen(fname_bmp, "wb")))
{
return -1;
}
fwrite(header, sizeof(unsigned char), 54, fp);
fwrite(image, sizeof(unsigned char), (size_t)(long)(xsize * 3 + FillingByte)*ysize, fp);
fclose(fp);
return 0;
}
unsigned char *array_to_raw_image(const RGB* InputData, const int xsize, const int ysize)
{
unsigned char FillingByte;
FillingByte = bmp_filling_byte_calc(xsize);
unsigned char *output;
output = (unsigned char*)malloc((xsize * 3 + FillingByte) * ysize * sizeof(unsigned char));
if(output == NULL)
{
printf("Memory allocation error!");
return NULL;
}
for(int y = 0;y < ysize;y++)
{
for(int x = 0;x < (xsize * 3 + FillingByte);x++)
{
output[y * (xsize * 3 + FillingByte) + x] = 0;
}
}
for(int y = 0;y<ysize;y++)
{
for(int x = 0;x<xsize;x++)
{
output[3*(y * xsize + x) + y * FillingByte + 2]
= InputData[y*xsize + x].R;
output[3*(y * xsize + x) + y * FillingByte + 1]
= InputData[y*xsize + x].G;
output[3*(y * xsize + x) + y * FillingByte + 0]
= InputData[y*xsize + x].B;
}
}
return output;
}
unsigned char bmp_filling_byte_calc(const unsigned int xsize)
{
unsigned char filling_bytes;
filling_bytes = ( xsize % 4);
return filling_bytes;
}
unsigned char *bubble_sort_uchar( const unsigned char *data_input,
const unsigned long long int data_input_count,
const bool mode)
{
unsigned char *output;
output = (unsigned char*)malloc( data_input_count * sizeof(unsigned char) );
for(unsigned long long int y=0;y < data_input_count;y++)
{
output[y] = data_input[y];
}
for(unsigned long long int x = 1; x < data_input_count; x++)
{
for(unsigned long long int y = 0; y < data_input_count - x; y++)
{
if( mode == 0 )
{
if(output[y] > output[y + 1])
{
unsigned char temp;
temp = output[y];
output[y] = output[y + 1];
output[y + 1] = temp;
}
}
else if( mode == 1 )
{
if(output[y] < output[y + 1])
{
unsigned char temp;
temp = output[y];
output[y] = output[y + 1];
output[y + 1] = temp;
}
}
}
}
return output;
}
If there is any possible improvement, please let me know.