From a2e5fef55bec0a78f411cb7c857f8fd8e786b1a5 Mon Sep 17 00:00:00 2001 From: Kushal K S V S Date: Mon, 7 Aug 2017 11:30:56 -0700 Subject: [PATCH] Comments in bitmap.c --- tests/make_png/bitmap.c | 646 +++++++++++++++++++++------------------- 1 file changed, 332 insertions(+), 314 deletions(-) diff --git a/tests/make_png/bitmap.c b/tests/make_png/bitmap.c index f00618457..0f7278c06 100644 --- a/tests/make_png/bitmap.c +++ b/tests/make_png/bitmap.c @@ -1,5 +1,8 @@ #include "bitmap.h" +/* Functions to generate MurmurHash3 values of the bitmap image */ +/*data with a constant as the seed */ + HASH_128 * Generate_Hash_x64_128( FT_Bitmap * bitmap, HASH_128 * murmur) { @@ -12,7 +15,7 @@ HASH_128 * Generate_Hash_x64_128( FT_Bitmap * bitmap, return murmur; } - +/*Not used*/ HASH_128 * Generate_Hash_x86_128( FT_Bitmap * bitmap, HASH_128 * murmur) { @@ -25,7 +28,7 @@ HASH_128 * Generate_Hash_x86_128( FT_Bitmap * bitmap, return murmur; } - +/*Not used*/ HASH_32 * Generate_Hash_x86_32( FT_Bitmap * bitmap, HASH_32 * murmur) { @@ -39,11 +42,162 @@ HASH_32 * Generate_Hash_x86_32( FT_Bitmap * bitmap, return murmur; } +/* This function takes in the IMAGE data and returns the pointer */ +/* to the pixel at co-ordinates (x,y). This is used to access the */ +/* pixel data */ + PIXEL * Pixel_At (IMAGE * bitmap, int x, int y) { return bitmap->pixels + bitmap->width * y + x; } - + +/* Here we take the FT_Bitmap structure and make an IMAGE structure */ +/* with pixel data from the FT_Bitmap buffer */ + +void Make_PNG(FT_Bitmap* bitmap,IMAGE* fruit,int i,int render_mode){ + + int x; + int y; + + unsigned char value; + int p; + + switch(render_mode){ + + case 0 : fruit->width = bitmap->width; /* MONO */ + fruit->height = bitmap->rows; + /* Allocate Memory to the IMAGE structure as per the */ + /* dimensions of the FT_Bitmap image*/ + fruit->pixels = calloc ( fruit->width * fruit->height, + sizeof (PIXEL)); + + for (y = 0; y < fruit->height; y++) { + for (x = 0; x < fruit->width; x++) { + /* Access pixel by co-ordinates */ + PIXEL * pixel = Pixel_At ( fruit, x, y); + p = (y * bitmap->pitch ) + x; + + value = bitmap->buffer[p]; + /* If there is some colour, make it white */ + /* else, make it black */ + if ( value != 0x00 ){ + value = 0xff; + }else{ + value = 0x00; + } + /* Invert the colours to make the background white*/ + /* and the character black */ + pixel->red = 255- value; + pixel->green = 255- value; + pixel->blue = 255- value; + pixel->alpha = 255; + } + } + break; + case 1 : fruit->width = bitmap->width; /* GRAY */ + fruit->height = bitmap->rows; + + fruit->pixels = calloc ( fruit->width * fruit->height, + sizeof (PIXEL)); + + for (y = 0; y < fruit->height; y++) { + for (x = 0; x < fruit->width; x++) { + + PIXEL * pixel = Pixel_At ( fruit, x, y); + p = (y * bitmap->pitch ) + x; + + /* Access the image data from the buffer */ + value = bitmap->buffer[p]; + /* R=G=B for Grayscale images */ + pixel->red = 255- value; + pixel->green = 255- value; + pixel->blue = 255- value; + pixel->alpha = 255; + } + } + break; + +/********************************************************************/ +/* FT_Bitmap has 'width' three times the size of glyph in case of */ +/* LCD rendering i.e. three adjacent values in bitmap buffer row */ +/* correspond to one RGB triplet. Accessing the buffer accordingly */ +/* and filling the RGB values of the IMAGE structure */ +/********************************************************************/ + case 2 : + case 3 : fruit->width = bitmap->width / 3; /* LCD */ + fruit->height = bitmap->rows; + + fruit->pixels = calloc ( fruit->width * fruit->height, + sizeof (PIXEL)); + + for (y = 0; y < fruit->height; y++) { + for (x = 0; x < fruit->width; x++) { + + PIXEL * pixel = Pixel_At ( fruit, x, y); + p = (y * bitmap->pitch ) + (x)*3; + + value = bitmap->buffer[p]; + pixel->red = 255- value; + p++; + + value = bitmap->buffer[p]; + pixel->green = 255- value; + p++; + + value = bitmap->buffer[p]; + pixel->blue = 255- value; + + pixel->alpha = 255; + } + } + break; +/********************************************************************/ +/* FT_Bitmap has 'height' three times the size of glyph in case of */ +/* LCD_v rendering i.e. three adjacent values in bitmap buffer */ +/* column correspond to one RGB triplet. Accessing the buffer */ +/* accordingly and filling the RGB values of the IMAGE structure */ +/********************************************************************/ + case 4 : + case 5 : fruit->width = bitmap->width; /* LCD_V */ + fruit->height = bitmap->rows / 3; + + fruit->pixels = calloc ( fruit->width * fruit->height, + sizeof (PIXEL)); + + for (y = 0; y < fruit->height; y++) { + for (x = 0; x < fruit->width; x++) { + + PIXEL * pixel = Pixel_At ( fruit, x, y); + p = ((y*3) * bitmap->pitch ) + x; + + value = bitmap->buffer[p]; + pixel->red = 255- value; + p += bitmap->pitch; + + value = bitmap->buffer[p]; + pixel->green = 255- value; + p += bitmap->pitch; + + value = bitmap->buffer[p]; + pixel->blue = 255- value; + + pixel->alpha = 255; + } + } + break; + + default : fruit->width = bitmap->width; + fruit->height = bitmap->rows; + break; + } +} + +/********************************************************************/ +/* This function generates the PNG file taking the IMAGE structure */ +/* , path to the file and the render_mode. ( Using libpng ) */ +/* 32-bit RGBA images are generated. Each channel is 8-bit with */ +/* alpha channel set to 255. Transparency can be set accordingly */ +/********************************************************************/ int Generate_PNG (IMAGE *bitmap, const char *path, int render_mode) @@ -57,8 +211,8 @@ int Generate_PNG (IMAGE *bitmap, int status = -1; - int pixel_size = 4; - int depth = 8; + int pixel_size = 4; /* Each pixel is 4-byte */ + int depth = 8; /* Each colour is 8-bit*/ fp = fopen (path, "wb"); if (! fp) { @@ -106,14 +260,14 @@ int Generate_PNG (IMAGE *bitmap, PIXEL * pixel = Pixel_At (bitmap, x, y); if (render_mode == 3 || render_mode == 5) - { + { /* For BGRA images */ *row++ = pixel->blue; *row++ = pixel->green; *row++ = pixel->red; *row++ = pixel->alpha; continue; } - + /* For RGBA images */ *row++ = pixel->red; *row++ = pixel->green; *row++ = pixel->blue; @@ -151,290 +305,10 @@ int Generate_PNG (IMAGE *bitmap, return status; } -void Make_PNG(FT_Bitmap* bitmap,IMAGE* fruit,int i,int render_mode){ - - int x; - int y; - - unsigned char value; - int p; - - switch(render_mode){ - - case 0 : fruit->width = bitmap->width; /* MONO and GRAY */ - fruit->height = bitmap->rows; - - fruit->pixels = calloc ( fruit->width * fruit->height, - sizeof (PIXEL)); - - for (y = 0; y < fruit->height; y++) { - for (x = 0; x < fruit->width; x++) { - - PIXEL * pixel = Pixel_At ( fruit, x, y); - p = (y * bitmap->pitch ) + x; - - value = bitmap->buffer[p]; - - if ( value != 0x00 ){ - value = 0xff; - }else{ - value = 0x00; - } - - pixel->red = 255- value; - pixel->green = 255- value; - pixel->blue = 255- value; - pixel->alpha = 255; - } - } - break; - case 1 : fruit->width = bitmap->width; /* MONO and GRAY */ - fruit->height = bitmap->rows; - - fruit->pixels = calloc ( fruit->width * fruit->height, - sizeof (PIXEL)); - - for (y = 0; y < fruit->height; y++) { - for (x = 0; x < fruit->width; x++) { - - PIXEL * pixel = Pixel_At ( fruit, x, y); - p = (y * bitmap->pitch ) + x; - - value = bitmap->buffer[p]; - - pixel->red = 255- value; - pixel->green = 255- value; - pixel->blue = 255- value; - pixel->alpha = 255; - } - } - break; - - case 2 : - case 3 : fruit->width = bitmap->width / 3; /* LCD */ - fruit->height = bitmap->rows; - - fruit->pixels = calloc ( fruit->width * fruit->height, - sizeof (PIXEL)); - - for (y = 0; y < fruit->height; y++) { - for (x = 0; x < fruit->width; x++) { - - PIXEL * pixel = Pixel_At ( fruit, x, y); - p = (y * bitmap->pitch ) + (x)*3; - - value = bitmap->buffer[p]; - pixel->red = 255- value; - p++; - - value = bitmap->buffer[p]; - pixel->green = 255- value; - p++; - - value = bitmap->buffer[p]; - pixel->blue = 255- value; - - pixel->alpha = 255; - } - } - break; - - case 4 : - case 5 : fruit->width = bitmap->width; /* LCD_V */ - fruit->height = bitmap->rows / 3; - - fruit->pixels = calloc ( fruit->width * fruit->height, - sizeof (PIXEL)); - - for (y = 0; y < fruit->height; y++) { - for (x = 0; x < fruit->width; x++) { - - PIXEL * pixel = Pixel_At ( fruit, x, y); - p = ((y*3) * bitmap->pitch ) + x; - - value = bitmap->buffer[p]; - pixel->red = 255- value; - p += bitmap->pitch; - - value = bitmap->buffer[p]; - pixel->green = 255- value; - p += bitmap->pitch; - - value = bitmap->buffer[p]; - pixel->blue = 255- value; - - pixel->alpha = 255; - } - } - break; - - default : fruit->width = bitmap->width; - fruit->height = bitmap->rows; - break; - } -} - -void Read_PNG(char *filename, IMAGE * after_effect) { - - int width, height, x, y; - png_bytep *row_pointers; - - FILE *fp = fopen(filename, "rb"); - - png_structp png = png_create_read_struct( PNG_LIBPNG_VER_STRING, - NULL, - NULL, - NULL); - if(!png) abort(); - - png_infop info = png_create_info_struct(png); - if(!info) abort(); - - if(setjmp(png_jmpbuf(png))) abort(); - - png_init_io(png, fp); - - png_set_user_limits(png, 0x7fffffffL, 0x7fffffffL); - - png_read_info(png, info); - - width = png_get_image_width(png, info); - height = png_get_image_height(png, info); - - after_effect->width = width; - after_effect->height = height; - - row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height); - for( y = 0; y < height; y++) { - row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png,info)); - } - - png_read_image(png, row_pointers); - - after_effect->pixels = - (PIXEL*) malloc( width * height * sizeof(PIXEL)); - - for( y = 0; y < height; y++) { - - png_bytep row = row_pointers[y]; - - for( x = 0; x < width; x++ ) { - - png_bytep px = &(row[x * 4]); - - PIXEL * pixel = Pixel_At ( after_effect, x, y); - - pixel->red = px[0]; - pixel->green = px[1]; - pixel->blue = px[2]; - pixel->alpha = px[3]; - } - } - - fclose(fp); -} - -int Add_effect(IMAGE* base, IMAGE* test, IMAGE* out, int Effect_ID) -{ - int pixel_diff = 0; - int x,y; - - out->width = base->width; - out->height = base->height; - out->pixels = - (PIXEL*)malloc(base->width * base->height * sizeof(PIXEL)); - - for( y = 0; y < base->height; y++) { - for( x = 0; x < base->width; x++ ) { - - PIXEL * pixel_base = Pixel_At ( base, x, y); - PIXEL * pixel_test = Pixel_At ( test, x, y); - PIXEL * pixel_out = Pixel_At ( out, x, y); - - if (Effect_ID == 1) - { - if (pixel_base->red == 255 && - pixel_base->green == 255 && - pixel_base->blue == 255 && - pixel_base->alpha == 255 ) - { - pixel_out->red = 255; - pixel_out->green = 255; - pixel_out->blue = 255; - pixel_out->alpha = 255; - }else{ - pixel_out->red = 127; - pixel_out->green = 127; - pixel_out->blue = 127; - pixel_out->alpha = 255; - } - } - - if (pixel_base->red != pixel_test->red || - pixel_base->green != pixel_test->green || - pixel_base->blue != pixel_test->blue || - pixel_base->alpha != pixel_test->alpha ) - { - pixel_out->red = 255; - pixel_out->green = 0; - pixel_out->blue = 0; - pixel_out->alpha = 255; - - pixel_diff++; - - }else{ - if (Effect_ID == 2) - { - pixel_out->red = pixel_base->red; - pixel_out->green = pixel_base->green; - pixel_out->blue = pixel_base->blue; - pixel_out->alpha = pixel_base->alpha; - } - } - } - } - return pixel_diff; -} - -void Stitch(IMAGE* left, IMAGE* right, IMAGE* result){ - - int x, y; - - result->width = left->width + right->width; - result->height = MAX(left->height, right->height); - - result->pixels = - (PIXEL*)calloc(result->width * result->height, sizeof(PIXEL)); - - for ( y = 0; y < left->height; ++y) - { - for ( x = 0; x < left->width; ++x) - { - PIXEL * pixel_left = Pixel_At ( left, x, y); - PIXEL * pixel_result = Pixel_At ( result, x, y); - - pixel_result->red = pixel_left->red; - pixel_result->green = pixel_left->green; - pixel_result->blue = pixel_left->blue; - pixel_result->alpha = pixel_left->alpha; - } - } - - for ( y = 0; y < right->height; ++y) - { - for ( x = left->width; x < result->width; ++x) - { - PIXEL * pixel_right = Pixel_At ( right, x - left->width, y); - PIXEL * pixel_result = Pixel_At ( result, x, y); - - pixel_result->red = pixel_right->red; - pixel_result->green = pixel_right->green; - pixel_result->blue = pixel_right->blue; - pixel_result->alpha = pixel_right->alpha; - } - } -} - +/********************************************************************/ +/* Compare the MurmurHash3 values ( x64_128 bit implemented ) */ +/* Returns 1 if they are different and 0 if identical. */ +/********************************************************************/ int Compare_Hash(HASH_128* hash_b, HASH_128* hash_t){ if (hash_b->hash[0] != hash_t->hash[0] || hash_b->hash[1] != hash_t->hash[1] || @@ -446,17 +320,11 @@ int Compare_Hash(HASH_128* hash_b, HASH_128* hash_t){ return 0; } -void Print_Row( FILE* fp, int index, char* name, int diff ) -{ - fprintf(fp, - "\n\ - %04d\n\ - %s\n\ - %04d\n\ - \n\ - \n", index, name, diff, name); -} - +/********************************************************************/ +/* Returns the index of the first-column to have a coloured pixel. */ +/* 'Coloured' means the pixel isn't in the background */ +/* Background Colour RGB = ( 255,255,255 ) */ +/********************************************************************/ int First_Column(IMAGE* input){ int x, y; @@ -481,6 +349,7 @@ int First_Column(IMAGE* input){ return input->width; } +/* Returns the index of the first-row to have a coloured pixel. */ int First_Row(IMAGE* input){ int x, y; @@ -505,8 +374,16 @@ int First_Row(IMAGE* input){ return input->height; } +/********************************************************************/ +/* The following two functions takes two IMAGES with different */ +/* dimensions and aligns the two images based on the first pixel */ +/* that isn't in the background i.e. RGB != ( 255,255,255 ). */ +/* The first argument is the one which has smaller height/width. */ +/* Columns/Rows are appended to the smaller image to match the */ +/* dimensions. */ +/********************************************************************/ IMAGE* Append_Columns(IMAGE* small, IMAGE* big){ - + /* small->width < big->width */ int x, y; IMAGE* result = (IMAGE*)malloc(sizeof(IMAGE)); @@ -518,12 +395,12 @@ IMAGE* Append_Columns(IMAGE* small, IMAGE* big){ int first_col = First_Column(big); - for ( x = 0; x < first_col; ++x) + for ( x = 0; x < first_col; ++x) /* Filling White columns */ { for ( y = 0; y < result->height; ++y) { PIXEL * pixel_result = Pixel_At ( result, x, y); - + /* Filling White columns */ pixel_result->red = 255; pixel_result->green = 255; pixel_result->blue = 255; @@ -531,13 +408,13 @@ IMAGE* Append_Columns(IMAGE* small, IMAGE* big){ } } - for ( y = 0; y < result->height; ++y) + for ( y = 0; y < result->height; ++y) { for ( x = first_col; x < first_col + small->width; ++x) { PIXEL * pixel_small = Pixel_At ( small, (x - first_col), y); PIXEL * pixel_result = Pixel_At ( result, x, y); - + /* Putting the original IMAGE data */ pixel_result->red = pixel_small->red; pixel_result->green = pixel_small->green; pixel_result->blue = pixel_small->blue; @@ -550,7 +427,7 @@ IMAGE* Append_Columns(IMAGE* small, IMAGE* big){ for ( y = 0; y < result->height; ++y) { PIXEL * pixel_result = Pixel_At ( result, x, y); - + /* Filling White columns */ pixel_result->red = 255; pixel_result->green = 255; pixel_result->blue = 255; @@ -562,7 +439,7 @@ IMAGE* Append_Columns(IMAGE* small, IMAGE* big){ } IMAGE* Append_Rows(IMAGE* small, IMAGE* big){ - + /* small->height < big->height */ int x, y; IMAGE* result = (IMAGE*)malloc(sizeof(IMAGE)); @@ -576,10 +453,10 @@ IMAGE* Append_Rows(IMAGE* small, IMAGE* big){ for ( y = 0; y < first_row; ++y) { - for ( x = 0; x < result->width; ++x) + for ( x = 0; x < result->width; ++x) { PIXEL * pixel_result = Pixel_At ( result, x, y); - + /* Filling White rows */ pixel_result->red = 255; pixel_result->green = 255; pixel_result->blue = 255; @@ -590,10 +467,10 @@ IMAGE* Append_Rows(IMAGE* small, IMAGE* big){ for ( y = first_row; y < first_row + small->height; ++y) { for ( x = 0; x < result->width; ++x) - { + { PIXEL * pixel_small = Pixel_At ( small, x, y - first_row); PIXEL * pixel_result = Pixel_At ( result, x, y); - + /* Putting the original IMAGE data */ pixel_result->red = pixel_small->red; pixel_result->green = pixel_small->green; pixel_result->blue = pixel_small->blue; @@ -606,7 +483,7 @@ IMAGE* Append_Rows(IMAGE* small, IMAGE* big){ for ( x = 0; x < result->width; ++x) { PIXEL * pixel_result = Pixel_At ( result, x, y); - + /* Filling White rows */ pixel_result->red = 255; pixel_result->green = 255; pixel_result->blue = 255; @@ -617,6 +494,146 @@ IMAGE* Append_Rows(IMAGE* small, IMAGE* big){ return result; } +/********************************************************************/ +/* This fuction visually highlights the differences between the two */ +/* images generated for the same glyph. There are two effects each */ +/* given an Effect_ID. */ +/* This function generates a new IMAGE structure after comparing and*/ +/* adding the desired effect. */ +/* */ +/* Effect_ID =1 means that the differences in pixels are highlighted*/ +/* and the pixels that are same are in GRAY (RGB = (128,128,128)) */ +/* */ +/* Effect_ID =2 means that the differences in pixels are highlighted*/ +/* over the 'base' version's rendered image */ +/* */ +/* Highlighting is done in RED colour i.e. RGB=( 255, 0, 0) for */ +/* mono, grayscale and RGB-LCD displays and for BGR-LCD displays */ +/* is is done in BLUE colour i.e. RGB = ( 0, 0, 255). */ +/********************************************************************/ +int Add_effect(IMAGE* base, IMAGE* test, IMAGE* out, int Effect_ID) +{ + int pixel_diff = 0; + int x,y; + /* new IMAGE */ + out->width = base->width; + out->height = base->height; + out->pixels = + (PIXEL*)malloc(base->width * base->height * sizeof(PIXEL)); + + for( y = 0; y < base->height; y++) { + for( x = 0; x < base->width; x++ ) { + + PIXEL * pixel_base = Pixel_At ( base, x, y); + PIXEL * pixel_test = Pixel_At ( test, x, y); + PIXEL * pixel_out = Pixel_At ( out, x, y); + + if (Effect_ID == 1) + { /* If colour is white */ + if (pixel_base->red == 255 && + pixel_base->green == 255 && + pixel_base->blue == 255 && + pixel_base->alpha == 255 ) + { + pixel_out->red = 255; /* White*/ + pixel_out->green = 255; + pixel_out->blue = 255; + pixel_out->alpha = 255; + }else{ + pixel_out->red = 127; /* Gray */ + pixel_out->green = 127; + pixel_out->blue = 127; + pixel_out->alpha = 255; + } + } + /* if colour is different*/ + if (pixel_base->red != pixel_test->red || + pixel_base->green != pixel_test->green || + pixel_base->blue != pixel_test->blue || + pixel_base->alpha != pixel_test->alpha ) + { /* Highlighting pixels */ + pixel_out->red = 255; + pixel_out->green = 0; + pixel_out->blue = 0; + pixel_out->alpha = 255; + + pixel_diff++; + + }else{ + if (Effect_ID == 2) + { + pixel_out->red = pixel_base->red; + pixel_out->green = pixel_base->green; + pixel_out->blue = pixel_base->blue; + pixel_out->alpha = pixel_base->alpha; + } + } + } + } + return pixel_diff; +} + +/********************************************************************/ +/* This function takes two IMAGE structures and stitches the images */ +/* horizontally to make one IMAGE. */ +/* i.e. ( result->width = left->width + right->width ) */ +/* The first argument forms the left part of the image and the */ +/* second forms the right part. */ +/* This returns the pointer to the stitched image */ +/********************************************************************/ + +void Stitch(IMAGE* left, IMAGE* right, IMAGE* result){ + + int x, y; + + result->width = left->width + right->width; + result->height = MAX(left->height, right->height); + + result->pixels = + (PIXEL*)calloc(result->width * result->height, sizeof(PIXEL)); + + for ( y = 0; y < left->height; ++y) + { + for ( x = 0; x < left->width; ++x) + { + PIXEL * pixel_left = Pixel_At ( left, x, y); + PIXEL * pixel_result = Pixel_At ( result, x, y); + /* Filling Left part of the image*/ + pixel_result->red = pixel_left->red; + pixel_result->green = pixel_left->green; + pixel_result->blue = pixel_left->blue; + pixel_result->alpha = pixel_left->alpha; + } + } + + for ( y = 0; y < right->height; ++y) + { + for ( x = left->width; x < result->width; ++x) + { + PIXEL * pixel_right = Pixel_At ( right, x - left->width, y); + PIXEL * pixel_result = Pixel_At ( result, x, y); + /* Filling right part of the image*/ + pixel_result->red = pixel_right->red; + pixel_result->green = pixel_right->green; + pixel_result->blue = pixel_right->blue; + pixel_result->alpha = pixel_right->alpha; + } + } +} + +/* This prints a row to the HTML file for the list-view page. */ +void Print_Row( FILE* fp, int index, char* name, int diff ) +{ + fprintf(fp, + "\n\ + %04d\n\ + %s\n\ + %04d\n\ + \n\ + \n", index, name, diff, name); +} + +/* To calculate the Difference-Metric used in the list-view page */ int Image_Diff( IMAGE* base, IMAGE* test){ int diff = 0; @@ -632,3 +649,4 @@ int Image_Diff( IMAGE* base, IMAGE* test){ return diff; } +/* For more information on the list-view page, go to README */