diff --git a/tests/make_png/README b/tests/make_png/README index a01ac2d77..e3ebb412b 100644 --- a/tests/make_png/README +++ b/tests/make_png/README @@ -1,6 +1,6 @@ -To generate hashes and store it in the same folder, +To generate hashes and store it in the ./hashes folder, - 1) sudo make + 1) sudo make hash (set resoluton in DPI by passing argument example: sudo make DPI=100, if not specified,default is 72) @@ -10,7 +10,26 @@ To generate hashes and store it in the same folder, By default, hashes of 256-level gray bitmaps will be generated + Values for render_mode 0 - monochrome + 1 - anti-aliased + 2 - lcd horizontal + 3 - lcd vertical + +To generate 32-bit RGBA PNG(s) of all glyphs in a font\n + + 1) sudo make png + (set resoluton in DPI by passing argument + example: sudo make DPI=100, if not specified,default is 72) + + 2.Usage ./ + + Images will be saved in a file named $(font)_$(pt_size)_$(render_mode)_$(glyph_index).png + + By default, hashes of 256-level gray bitmaps will be generated + Values for render_mode 0 - monochrome 1 - anti-aliased 2 - lcd horizontal-RGB - 3 - lcd vertical-RGB \ No newline at end of file + 3 - lcd horizontal-BGR + 4 - lcd vertical-RGB + 5 - lcd vertical-BGR \ No newline at end of file diff --git a/tests/make_png/bitmap.c b/tests/make_png/bitmap.c index 923d072f3..2813ff1b4 100644 --- a/tests/make_png/bitmap.c +++ b/tests/make_png/bitmap.c @@ -27,3 +27,198 @@ HASH_32 * Generate_Hash_x86_32(FT_Bitmap * bitmap, HASH_32 * murmur) return murmur; } +PIXEL * Pixel_At (IMAGE * bitmap, int x, int y) +{ + return bitmap->pixels + bitmap->width * y + x; +} + +int Generate_PNG (IMAGE *bitmap, const char *path,int render_mode) +{ + FILE * fp; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + size_t x, y; + png_byte ** row_pointers = NULL; + + int status = -1; + + int pixel_size = 4; + int depth = 8; + + fp = fopen (path, "wb"); + if (! fp) { + goto fopen_failed; + } + + png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + goto png_create_write_struct_failed; + } + + info_ptr = png_create_info_struct (png_ptr); + if (info_ptr == NULL) { + goto png_create_info_struct_failed; + } + + if (setjmp (png_jmpbuf (png_ptr))) { + goto png_failure; + } + + png_set_IHDR (png_ptr, + info_ptr, + bitmap->width, + bitmap->height, + depth, + PNG_COLOR_TYPE_RGBA, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + row_pointers = png_malloc (png_ptr, bitmap->height * sizeof (png_byte *)); + + for (y = 0; y < bitmap->height; y++) { + + png_byte *row = png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size); + row_pointers[y] = row; + + for (x = 0; x < bitmap->width; x++) { + + PIXEL * pixel = Pixel_At (bitmap, x, y); + + if (render_mode == 3 || render_mode == 5) + { + *row++ = pixel->blue; + *row++ = pixel->green; + *row++ = pixel->red; + *row++ = pixel->alpha; + continue; + } + *row++ = pixel->red; + *row++ = pixel->green; + *row++ = pixel->blue; + *row++ = pixel->alpha; + } + } + + png_init_io (png_ptr, fp); + png_set_rows (png_ptr, info_ptr, row_pointers); + png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + + status = 0; + + for (y = 0; y < bitmap->height; y++) { + png_free (png_ptr, row_pointers[y]); + } + png_free (png_ptr, row_pointers); + + png_failure: + png_create_info_struct_failed: + png_destroy_write_struct (&png_ptr, &info_ptr); + png_create_write_struct_failed: + fclose (fp); + fopen_failed: + return status; +} + +void Make_PNG(FT_Bitmap* bitmap,char* name,int i,int render_mode){ + + IMAGE fruit; + int x; + int y; + + unsigned char value; + int p; + + switch(render_mode){ + + case 0 : + 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; + } + + char * file_name = ( char * )calloc(150,sizeof(char)); + + sprintf(file_name, "%s_%d",name,i); + + Generate_PNG (& fruit, file_name,render_mode); + + free (fruit.pixels); +} \ No newline at end of file diff --git a/tests/make_png/bitmap.h b/tests/make_png/bitmap.h index fb7ab12e5..8a3a4f58e 100644 --- a/tests/make_png/bitmap.h +++ b/tests/make_png/bitmap.h @@ -1,7 +1,17 @@ #include +#include +#include +#include + +#include +#include + #include + #include "murmur3.h" // MurmurHash3_x64_128 header file -#include + +#include + #include FT_FREETYPE_H #include FT_MODULE_H @@ -18,6 +28,28 @@ typedef struct { // To store 128bit Hash FT_UInt32 hash[4]; }HASH_128; +typedef struct { + unsigned char red; + unsigned char green; + unsigned char blue; + unsigned char alpha; +} PIXEL; + +typedef struct { + unsigned char red; + unsigned char green; + unsigned char blue; + unsigned char alpha; +} PIXEL_BGRA; + +/* A picture. */ + +typedef struct { + PIXEL *pixels; + size_t width; + size_t height; +} IMAGE; + //------------------------------------------------------------------------------- HASH_32 * Generate_Hash_x86_32(FT_Bitmap * bitmap, HASH_32 * murmur); @@ -25,3 +57,9 @@ HASH_128 * Generate_Hash_x86_128(FT_Bitmap * bitmap, HASH_128 * murmur); HASH_128 * Generate_Hash_x64_128(FT_Bitmap * bitmap, HASH_128 * murmur); //------------------------------------------------------------------------------- + +PIXEL * Pixel_At (IMAGE * bitmap, int x, int y); + +void Make_PNG(FT_Bitmap* bitmap,char* name,int i,int render_mode); +int Generate_PNG (IMAGE *bitmap, const char *path,int render_mode); + diff --git a/tests/make_png/make_png.c b/tests/make_png/make_png.c new file mode 100644 index 000000000..4d3312561 --- /dev/null +++ b/tests/make_png/make_png.c @@ -0,0 +1,167 @@ +#include "bitmap.h" + +int main (int argc, char const *argv[]) +{ + FT_Library library; + FT_Face face; + FT_GlyphSlot slot; + + FT_Bitmap* bitmap; + + FT_Error error; + + const char* font_file; + int size; + int render_mode; // argument + + int load_flag; // FT_LOAD_XXX + int render_flag; // FT_RENDER_MODE_XXX + int target_flag; // FT_LOAD_TARGET_XXX + char* render_type; // for file_name + + char name[100]; // hashes file name + int i; // for loop + + if (argc != 4) + { + printf("\nTo generate 32-bit RGBA PNG(s) of all glyphs in a font\n"); + printf("Images will be saved in a file named \n\ + $(font)_$(pt_size)_$(render_mode)_$(glyph_index).png \n\n"); + + printf("By default, hashes of 256-level gray bitmaps will be generated\n\n"); + + printf("Usage ./ \n\n"); + + printf("Values for render_mode 0 - monochrome\n"); + printf(" 1 - anti-aliased\n"); + printf(" 2 - lcd horizontal-RGB\n"); + printf(" 3 - lcd horizontal-BGR\n"); + printf(" 4 - lcd vertical-RGB\n"); + printf(" 5 - lcd vertical-BGR\n"); + + return 1; + } + + font_file = argv[1]; + size = atof(argv[2]); + render_mode = atoi(argv[3]); + + error = FT_Init_FreeType( &library ); + if(error){ + printf("Error while initialising library\n"); + } + + error = FT_New_Face( library, + font_file, + 0, + &face ); + if(error){ + printf("Error loading new face\n"); + } + + error = FT_Set_Char_Size( face, + size * 64, + 0, + DPI, + 0 ); + if(error){ + printf("Error setting character size\n"); + } + + switch ( render_mode ) { + case 0: render_flag = FT_RENDER_MODE_MONO; + load_flag = FT_LOAD_MONOCHROME; + target_flag = FT_LOAD_TARGET_MONO; + render_type = "mono"; + break; + + case 1: render_flag = FT_RENDER_MODE_NORMAL; + load_flag = FT_LOAD_DEFAULT; + target_flag = FT_LOAD_TARGET_NORMAL; + render_type = "gray"; + break; + + case 2: render_flag = FT_RENDER_MODE_LCD; + load_flag = FT_LOAD_DEFAULT; + target_flag = FT_LOAD_TARGET_LCD; + render_type = "lcd_rgb"; + break; + + case 3: render_flag = FT_RENDER_MODE_LCD; + load_flag = FT_LOAD_DEFAULT; + target_flag = FT_LOAD_TARGET_LCD; + render_type = "lcd_bgr"; + break; + + case 4: render_flag = FT_RENDER_MODE_LCD_V; + load_flag = FT_LOAD_DEFAULT; + target_flag = FT_LOAD_TARGET_LCD_V; + render_type = "lcd_ver_rgb"; + break; + + case 5: render_flag = FT_RENDER_MODE_LCD_V; + load_flag = FT_LOAD_DEFAULT; + target_flag = FT_LOAD_TARGET_LCD_V; + render_type = "lcd_ver_bgr"; + break; + + default:render_flag = FT_RENDER_MODE_NORMAL; + load_flag = FT_LOAD_DEFAULT; + target_flag = FT_LOAD_TARGET_NORMAL; + render_type = "gray"; + } + + slot = face->glyph; + + sprintf(name,"./images/%s_%d_%s",font_file, + size, + render_type); + + for (i = 0; i <50; ++i) + { + error = FT_Load_Glyph( face, + i, + load_flag | target_flag); + if(error){ + printf("Error loading glyph\n"); + } + + FT_Render_Glyph( slot, + render_flag); + if(error){ + printf("Error rendering the glyph\n"); + } + + bitmap = &slot->bitmap; + + if (bitmap->width == 0 || bitmap->rows == 0) + { + continue; + } + + FT_Bitmap target; + FT_Bitmap_Init( &target ); + + if (bitmap->pixel_mode == 1) + { + int alignment = 4; + error = FT_Bitmap_Convert( library, + bitmap, + &target, + alignment); + if(error){ + printf("Error converting the bitmap\n"); + } + Make_PNG(&target,name,i,render_mode); + }else{ + + Make_PNG(bitmap,name,i,render_mode); + } + } + + FT_Done_Face ( face ); + FT_Done_FreeType( library ); + + return 0; + +} diff --git a/tests/make_png/makefile b/tests/make_png/makefile index d60a6d685..691a6fd1b 100644 --- a/tests/make_png/makefile +++ b/tests/make_png/makefile @@ -2,18 +2,24 @@ SHELL = /bin/sh -SRC = hash_to_file.c bitmap.c murmur3.c +SRC_HASH = hash_to_file.c bitmap.c murmur3.c +SRC_PNG = make_png.c bitmap.c murmur3.c OBJS = $(src:.c=.o) CFLAGS = -Wall -g CC = gcc INCLUDE = -I /usr/local/include/freetype2/ -LIBS = -lfreetype +LIBS = -lfreetype -lpng DPI = 72 -hash:$(SRC) - $(CC) $(CFLAGS) $(INCLUDE) -DDPI=$(DPI) -o $@ $(SRC) $(OBJS) $(LIBS) +all: png hash + +png:$(SRC_PNG) + $(CC) $(CFLAGS) $(INCLUDE) -DDPI=$(DPI) -o $@ $(SRC_PNG) $(OBJS) $(LIBS) + +hash:$(SRC_HASH) + $(CC) $(CFLAGS) $(INCLUDE) -DDPI=$(DPI) -o $@ $(SRC_HASH) $(OBJS) $(LIBS) .PHONY: clean clean: