forked from minhngoc25a/freetype2
Generate test BMPs for glyphs with differing hashes
This commit is contained in:
parent
35ca70a141
commit
ccd52daaa2
|
@ -0,0 +1,269 @@
|
|||
#include "bitmap.h"
|
||||
|
||||
HASH_128 * Generate_Hash_x64_128(FT_Bitmap * bitmap, HASH_128 * murmur)
|
||||
{
|
||||
int seed = 99; // Dont change
|
||||
|
||||
MurmurHash3_x64_128(bitmap->buffer, (bitmap->pitch * bitmap->rows), seed, murmur->hash);
|
||||
|
||||
return murmur;
|
||||
}
|
||||
|
||||
HASH_128 * Generate_Hash_x86_128(FT_Bitmap * bitmap, HASH_128 * murmur)
|
||||
{
|
||||
int seed = 99; // Dont change
|
||||
|
||||
MurmurHash3_x86_128(bitmap->buffer, (bitmap->pitch * bitmap->rows), seed, murmur->hash);
|
||||
|
||||
return murmur;
|
||||
}
|
||||
|
||||
HASH_32 * Generate_Hash_x86_32(FT_Bitmap * bitmap, HASH_32 * murmur)
|
||||
{
|
||||
int seed = 99; // Dont change
|
||||
|
||||
MurmurHash3_x86_32(bitmap->buffer, (bitmap->pitch * bitmap->rows), seed, murmur->hash);
|
||||
|
||||
return murmur;
|
||||
}
|
||||
|
||||
int Get_Padding( FT_Bitmap* bitmap ){
|
||||
|
||||
int rem;
|
||||
if (bitmap->pixel_mode == 6)
|
||||
{
|
||||
rem = ( 3 * bitmap->width ) % 4;
|
||||
}else{
|
||||
rem = ( bitmap->width ) % 4;
|
||||
}
|
||||
|
||||
if (!rem )
|
||||
{
|
||||
return rem;
|
||||
}
|
||||
return (4 - rem);
|
||||
}
|
||||
|
||||
int Get_Bits_Per_Pixel ( unsigned char PIXEL_MODE) {
|
||||
if (PIXEL_MODE < 5)
|
||||
{
|
||||
return BITS_PER_PIXEL_GRAY;
|
||||
}else{
|
||||
return BITS_PER_PIXEL_LCD;
|
||||
}
|
||||
}
|
||||
|
||||
void Write_Bitmap_Header (FT_Bitmap * bitmap, char * fname ) {
|
||||
|
||||
FILE *fp = fopen(fname,"w"); // Bitmap File
|
||||
HEADER *header = ( HEADER* ) calloc( 1 , sizeof( HEADER ));
|
||||
|
||||
unsigned char pixel_mode = ( bitmap->pixel_mode );
|
||||
FT_UInt image_width;
|
||||
FT_UInt image_rows;
|
||||
FT_UInt color_table_size = 0;
|
||||
|
||||
switch(pixel_mode){
|
||||
|
||||
case 5 : image_width = bitmap->width / 3; // LCD
|
||||
image_rows = bitmap->rows;
|
||||
break;
|
||||
|
||||
case 6 : image_width = bitmap->width; // LCD_V
|
||||
image_rows = bitmap->rows / 3;
|
||||
break;
|
||||
|
||||
default : image_width = bitmap->width; // MONO and GRAY
|
||||
image_rows = bitmap->rows;
|
||||
color_table_size = 4* 256;
|
||||
break;
|
||||
}
|
||||
|
||||
FT_Int image_size;
|
||||
image_size = (image_rows * image_width );
|
||||
|
||||
header->file_header.type = 0x4D42;
|
||||
header->file_header.file_size = sizeof(HEADER) + color_table_size + image_size;
|
||||
header->file_header.file_offset = sizeof(HEADER) + color_table_size;
|
||||
|
||||
header->info_header.info_header_size = sizeof(BMP_INFO_HEADER);
|
||||
header->info_header.width = image_width ;
|
||||
header->info_header.height = - image_rows;
|
||||
header->info_header.planes = PLANES;
|
||||
header->info_header.bits_per_pixel = Get_Bits_Per_Pixel( bitmap->pixel_mode );
|
||||
header->info_header.compression = COMPRESSION;
|
||||
header->info_header.image_size = image_size;
|
||||
header->info_header.y_pixels_per_meter = Y_PIXELS_PER_METER ;
|
||||
header->info_header.x_pixels_per_meter = X_PIXELS_PER_METER ;
|
||||
header->info_header.used_colors = USED_COLORS;
|
||||
header->info_header.important_colors = IMPORTANT_COLORS;
|
||||
|
||||
fwrite (header, 1, sizeof(HEADER),fp);
|
||||
free(header);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void Write_Bitmap_Data_LCD_RGB( FT_Bitmap * bitmap, char * fname ){
|
||||
|
||||
char value;
|
||||
int i,j,k;
|
||||
|
||||
FILE *fp = fopen(fname,"a");
|
||||
|
||||
for (i = 0; i < bitmap->rows ; ++i)
|
||||
{
|
||||
for ( j = 2; j < bitmap->width; j = j+3)
|
||||
{
|
||||
for ( k = 0; k < 3; ++k)
|
||||
{
|
||||
value = 0xff - bitmap->buffer[( i * bitmap->pitch) + j - k];
|
||||
fwrite (&value, 1, 1,fp);
|
||||
}
|
||||
}
|
||||
for ( k = 0; k < Get_Padding(bitmap); ++k)
|
||||
{
|
||||
value = 0xff;
|
||||
fwrite (&value, 1, 1,fp);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void Write_Bitmap_Data_LCD_BGR( FT_Bitmap * bitmap, char * fname ){
|
||||
|
||||
char value;
|
||||
int i,j,k;
|
||||
|
||||
FILE *fp = fopen(fname,"a");
|
||||
|
||||
for ( i = 0; i < bitmap->rows ; ++i)
|
||||
{
|
||||
for ( j = 0; j < bitmap->width; j++)
|
||||
{
|
||||
value = 0xff - bitmap->buffer[( i * bitmap->pitch) + j];
|
||||
fwrite (&value, 1, 1,fp);
|
||||
}
|
||||
for ( k = 0; k < Get_Padding(bitmap); ++k)
|
||||
{
|
||||
value = 0xff;
|
||||
fwrite (&value, 1, 1,fp);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void Write_Bitmap_Data_LCD_V_BGR (FT_Bitmap * bitmap, char * fname) {
|
||||
|
||||
FILE *fp = fopen(fname,"a");
|
||||
|
||||
int i,j,k,step;
|
||||
char value;
|
||||
step = 0;
|
||||
|
||||
while ( step < bitmap->rows ){
|
||||
|
||||
for (i = 0; i < bitmap->width; i++)
|
||||
{
|
||||
for (j = step ; j < step + 3; ++j)
|
||||
{
|
||||
value = 0xff - bitmap->buffer[(j * bitmap->pitch) + i];
|
||||
fwrite (&value, 1, 1,fp);
|
||||
}
|
||||
}
|
||||
for (k = 0; k < Get_Padding(bitmap); ++k)
|
||||
{
|
||||
value = 0xff;
|
||||
fwrite (&value, 1, 1,fp);
|
||||
}
|
||||
step = step + 3; // Jumping 3 rows up
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void Write_Bitmap_Data_LCD_V_RGB (FT_Bitmap * bitmap, char * fname) {
|
||||
|
||||
FILE *fp = fopen(fname,"a");
|
||||
|
||||
int i,j,k,step;
|
||||
char value;
|
||||
step = 0;
|
||||
|
||||
while ( step < bitmap->rows ){
|
||||
|
||||
for (i = 0; i < bitmap->width; i++)
|
||||
{
|
||||
for (j = step + 2 ; j >= step; --j)
|
||||
{
|
||||
value = 0xff - bitmap->buffer[(j * bitmap->pitch) + i];
|
||||
fwrite (&value, 1, 1,fp);
|
||||
}
|
||||
}
|
||||
for (k = 0; k < Get_Padding(bitmap); ++k)
|
||||
{
|
||||
value = 0xff;
|
||||
fwrite (&value, 1, 1,fp);
|
||||
}
|
||||
step = step + 3; // Jumping 3 rows up
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void Write_Bitmap_Data_MONO (FT_Bitmap * bitmap, char * fname) {
|
||||
|
||||
FILE *fp = fopen(fname,"a");
|
||||
|
||||
int i;
|
||||
unsigned char value;
|
||||
for ( i = 0; i < 256; ++i)
|
||||
{
|
||||
value = i;
|
||||
fwrite (&value,1,1,fp);
|
||||
fwrite (&value,1,1,fp);
|
||||
fwrite (&value,1,1,fp);
|
||||
value = 0;
|
||||
fwrite (&value,1,1,fp);
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < bitmap->pitch * bitmap->rows; ++i)
|
||||
{
|
||||
if ( bitmap->buffer[i] != 0x00 ){
|
||||
value = 0x00; // remember taking reverse
|
||||
fwrite (&value, 1, 1,fp);
|
||||
}else{
|
||||
value = 0xff;
|
||||
fwrite (&value, 1, 1,fp);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void Write_Bitmap_Data_GRAY(FT_Bitmap * bitmap, char * fname) {
|
||||
|
||||
FILE *fp = fopen(fname,"a");
|
||||
int i;
|
||||
|
||||
unsigned char value;
|
||||
for ( i = 0; i < 256; ++i)
|
||||
{
|
||||
value = i;
|
||||
fwrite (&value,1,1,fp);
|
||||
fwrite (&value,1,1,fp);
|
||||
fwrite (&value,1,1,fp);
|
||||
value = 0;
|
||||
fwrite (&value,1,1,fp);
|
||||
}
|
||||
|
||||
for (int i = 0; i < bitmap->pitch * bitmap->rows; ++i)
|
||||
{
|
||||
value = 255 - bitmap->buffer[i];
|
||||
fwrite(&value,1,1,fp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
#include <stdio.h>
|
||||
#include <ft2build.h>
|
||||
#include <string.h>
|
||||
#include "murmur3.h" // MurmurHash3_x64_128 header file
|
||||
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_MODULE_H
|
||||
#include FT_LCD_FILTER_H
|
||||
#include FT_BITMAP_H
|
||||
|
||||
#define BITS_PER_PIXEL_MONO 1 // Constants for the Bitmap Header
|
||||
#define BITS_PER_PIXEL_GRAY 8
|
||||
#define BITS_PER_PIXEL_LCD 24
|
||||
|
||||
#define PLANES 1 // Constants for the Bitmap Header
|
||||
#define COMPRESSION 0
|
||||
#define X_PIXELS_PER_METER 0
|
||||
#define Y_PIXELS_PER_METER 0
|
||||
#define USED_COLORS 0
|
||||
#define IMPORTANT_COLORS 0
|
||||
//-------------------------------------------------------------------------------
|
||||
#pragma pack(push,1)
|
||||
|
||||
typedef struct{ // Bitmap FILE Header
|
||||
|
||||
FT_UInt16 type;
|
||||
FT_UInt32 file_size;
|
||||
FT_UInt32 reserved;
|
||||
FT_UInt32 file_offset;
|
||||
|
||||
} BMP_FILE_HEADER;
|
||||
|
||||
typedef struct{ // Bitmap INFO Header
|
||||
|
||||
FT_UInt32 info_header_size;
|
||||
FT_UInt32 width;
|
||||
FT_Int height;
|
||||
FT_UInt16 planes;
|
||||
FT_UInt16 bits_per_pixel;
|
||||
FT_UInt32 compression;
|
||||
FT_UInt32 image_size;
|
||||
FT_UInt32 y_pixels_per_meter;
|
||||
FT_UInt32 x_pixels_per_meter;
|
||||
FT_UInt32 used_colors;
|
||||
FT_UInt32 important_colors;
|
||||
|
||||
} BMP_INFO_HEADER;
|
||||
|
||||
typedef struct { // Bitmap Header
|
||||
|
||||
BMP_FILE_HEADER file_header;
|
||||
BMP_INFO_HEADER info_header;
|
||||
|
||||
} HEADER;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
typedef struct { // To store 32bit Hash
|
||||
FT_UInt32 hash[1];
|
||||
}HASH_32;
|
||||
|
||||
typedef struct { // To store 128bit Hash
|
||||
FT_UInt32 hash[4];
|
||||
}HASH_128;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
HASH_32 * Generate_Hash_x86_32(FT_Bitmap * bitmap, HASH_32 * murmur);
|
||||
HASH_128 * Generate_Hash_x86_128(FT_Bitmap * bitmap, HASH_128 * murmur);
|
||||
HASH_128 * Generate_Hash_x64_128(FT_Bitmap * bitmap, HASH_128 * murmur);
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
int Get_Padding (FT_Bitmap * bitmap);
|
||||
|
||||
int Get_Bits_Per_Pixel ( unsigned char PIXEL_MODE );
|
||||
|
||||
void Write_Bitmap_Header (FT_Bitmap * bitmap, char * fname);
|
||||
|
||||
void Write_Bitmap_Data_MONO (FT_Bitmap * bitmap, char * fname);
|
||||
void Write_Bitmap_Data_GRAY (FT_Bitmap * bitmap, char * fname);
|
||||
void Write_Bitmap_Data_LCD_BGR (FT_Bitmap * bitmap, char * fname);
|
||||
void Write_Bitmap_Data_LCD_RGB (FT_Bitmap * bitmap, char * fname);
|
||||
void Write_Bitmap_Data_LCD_V_RGB (FT_Bitmap * bitmap, char * fname);
|
||||
void Write_Bitmap_Data_LCD_V_BGR (FT_Bitmap * bitmap, char * fname);
|
|
@ -0,0 +1,103 @@
|
|||
#include "bitmap.h"
|
||||
|
||||
int main(int argc, char const * argv[])
|
||||
{
|
||||
FT_Library library;
|
||||
FT_Face face;
|
||||
FT_GlyphSlot slot;
|
||||
FT_Bitmap * bitmap;
|
||||
FT_UInt32 size;
|
||||
|
||||
const char * filename;
|
||||
|
||||
int i, j;
|
||||
|
||||
char mmhash[40];
|
||||
unsigned int lines;
|
||||
int line_len = 40;
|
||||
char ** hashes;
|
||||
char fname[20];
|
||||
|
||||
FILE * fp = fopen("old-hashes.txt", "r");
|
||||
|
||||
filename = argv[1];
|
||||
size = atoi(argv[2]);
|
||||
|
||||
if (FT_Init_FreeType(&library))
|
||||
{
|
||||
printf("Error: library init.\n");
|
||||
}
|
||||
|
||||
if (FT_New_Face(library, filename, 0, &face))
|
||||
{
|
||||
printf("Error: loading face.\n");
|
||||
}
|
||||
|
||||
lines = face->num_glyphs;
|
||||
hashes = (char **)malloc(sizeof(char*)*lines);
|
||||
|
||||
for (i = 0; i < lines; i++)
|
||||
{
|
||||
hashes[i] = malloc(line_len);
|
||||
if (hashes[i]==NULL)
|
||||
{
|
||||
fprintf(stderr,"Out of memory (3).\n");
|
||||
exit(4);
|
||||
}
|
||||
if (fgets(hashes[i],line_len-1,fp)==NULL)
|
||||
break;
|
||||
|
||||
/* Get rid of CR or LF at end of line */
|
||||
for (j=strlen(hashes[i])-1;j>=0 && (hashes[i][j]=='\n' || hashes[i][j]=='\r');j--)
|
||||
;
|
||||
hashes[i][j+1]='\0';
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
if (FT_Set_Char_Size(face, size * 64, 0, 96, 0))
|
||||
{
|
||||
printf("Error: setting char size.\n");
|
||||
}
|
||||
|
||||
slot = face->glyph;
|
||||
|
||||
for (i = 0; i < face->num_glyphs; ++i)
|
||||
{
|
||||
if (FT_Load_Glyph(face, i, FT_LOAD_DEFAULT))
|
||||
{
|
||||
printf("Error: loading glyph.\n");
|
||||
}
|
||||
|
||||
if (FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL))
|
||||
{
|
||||
printf("Error: rendering glyph.\n");
|
||||
}
|
||||
|
||||
bitmap = &slot->bitmap;
|
||||
|
||||
HASH_128 * murmur = (HASH_128 *)malloc(sizeof(HASH_128));
|
||||
murmur = Generate_Hash_x64_128(bitmap,murmur);
|
||||
|
||||
sprintf(mmhash, "%08x%08x%08x%08x", murmur->hash[0], murmur->hash[1], murmur->hash[2], murmur->hash[3]);
|
||||
|
||||
printf("%s\n", hashes[i]);
|
||||
printf("%s\n", mmhash);
|
||||
if (strcmp(mmhash, hashes[i]) == 0)
|
||||
{
|
||||
if (bitmap->width != 0 && bitmap->rows !=0)
|
||||
{
|
||||
printf("Glyph %d differs.\n", i);
|
||||
sprintf(fname, "%d-new.bmp", i);
|
||||
Write_Bitmap_Header(bitmap, fname);
|
||||
Write_Bitmap_Data_GRAY(bitmap, fname);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(library);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
#include "bitmap.h"
|
||||
|
||||
int main(int argc, char const * argv[])
|
||||
{
|
||||
FT_Library library;
|
||||
FT_Face face;
|
||||
FT_GlyphSlot slot;
|
||||
FT_Bitmap * bitmap;
|
||||
FT_UInt32 size;
|
||||
|
||||
const char * filename;
|
||||
|
||||
int i;
|
||||
|
||||
FILE * fp = fopen("old-hashes.txt", "w");
|
||||
|
||||
filename = argv[1];
|
||||
size = atoi(argv[2]);
|
||||
|
||||
if (FT_Init_FreeType(&library))
|
||||
{
|
||||
printf("Error: library init.\n");
|
||||
}
|
||||
|
||||
if (FT_New_Face(library, filename, 0, &face))
|
||||
{
|
||||
printf("Error: loading face.\n");
|
||||
}
|
||||
|
||||
if (FT_Set_Char_Size(face, size * 64, 0, 96, 0))
|
||||
{
|
||||
printf("Error: setting char size.\n");
|
||||
}
|
||||
|
||||
slot = face->glyph;
|
||||
|
||||
for (i = 0; i < face->num_glyphs; ++i)
|
||||
{
|
||||
if (FT_Load_Glyph(face, i, FT_LOAD_DEFAULT))
|
||||
{
|
||||
printf("Error: loading glyph.\n");
|
||||
}
|
||||
|
||||
if (FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL))
|
||||
{
|
||||
printf("Error: rendering glyph.\n");
|
||||
}
|
||||
|
||||
bitmap = &slot->bitmap;
|
||||
|
||||
HASH_128 * murmur = (HASH_128 *)malloc(sizeof(HASH_128));
|
||||
murmur = Generate_Hash_x64_128(bitmap, murmur);
|
||||
|
||||
fprintf(fp, "%08x%08x%08x%08x\n", murmur->hash[0], murmur->hash[1], murmur->hash[2], murmur->hash[3]);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(library);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include "qdbmp.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
// ft
|
||||
FT_Library library;
|
||||
FT_Face face;
|
||||
FT_Bitmap bmp;
|
||||
FT_UInt x, y, glyph_index;
|
||||
FT_Byte byte;
|
||||
BMP* qdbmp;
|
||||
char filename[20];
|
||||
|
||||
if (FT_Init_FreeType(&library))
|
||||
{
|
||||
printf("Error: Library initialization\n");
|
||||
}
|
||||
|
||||
if (FT_New_Face(library, "/usr/share/fonts/truetype/liberation/LiberationSerif-Regular.ttf", 0, &face))
|
||||
{
|
||||
printf("Error: Loading face\n");
|
||||
}
|
||||
|
||||
// if (FT_Set_Char_Size(face, 0, 16*64, 96, 0))
|
||||
// {
|
||||
// printf("Error: Setting character size\n");
|
||||
// }
|
||||
|
||||
if (FT_Set_Pixel_Sizes(face, 0, 48))
|
||||
{
|
||||
printf("Error: Setting character size\n");
|
||||
}
|
||||
|
||||
for (glyph_index = 65; glyph_index < 91; glyph_index++)
|
||||
{
|
||||
if (FT_Load_Char(face, glyph_index, FT_LOAD_RENDER))
|
||||
{
|
||||
printf("Error: Loading characte.r\n");
|
||||
}
|
||||
|
||||
bmp = face->glyph->bitmap;
|
||||
|
||||
// printf("Width: %u\n", bmp.width);
|
||||
// printf("Height: %u\n", bmp.rows);
|
||||
// printf("Num grays: %u\n", bmp.num_grays);
|
||||
// printf("Pitch: %d\n", bmp.pitch);
|
||||
|
||||
qdbmp = BMP_Create(bmp.width,bmp.rows,24);
|
||||
BMP_CHECK_ERROR(stdout, 1);
|
||||
|
||||
for (y = 0; y < bmp.rows; y++)
|
||||
{
|
||||
for (x = 0; x < bmp.width; x++)
|
||||
{
|
||||
byte = bmp.buffer[bmp.pitch * y + x];
|
||||
BMP_SetPixelRGB(qdbmp, x, y, 255 - byte, 255 - byte, 255 - byte);
|
||||
BMP_CHECK_ERROR(stdout, 1);
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(filename, "%d-2", glyph_index);
|
||||
|
||||
BMP_WriteFile(qdbmp, filename);
|
||||
BMP_CHECK_ERROR(stdout, 1);
|
||||
|
||||
}
|
||||
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(library);
|
||||
return 0;
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include "qdbmp.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
// ft
|
||||
FT_Library library;
|
||||
FT_Face face;
|
||||
FT_Bitmap bmp;
|
||||
FT_UInt x, y, glyph_index;
|
||||
FT_Byte byte;
|
||||
BMP* qdbmp;
|
||||
char filename[20];
|
||||
|
||||
if (FT_Init_FreeType(&library))
|
||||
{
|
||||
printf("Error: Library initialization\n");
|
||||
}
|
||||
|
||||
if (FT_New_Face(library, "/usr/share/fonts/truetype/liberation/LiberationSerif-Regular.ttf", 0, &face))
|
||||
{
|
||||
printf("Error: Loading face\n");
|
||||
}
|
||||
|
||||
// if (FT_Set_Char_Size(face, 0, 16*64, 96, 0))
|
||||
// {
|
||||
// printf("Error: Setting character size\n");
|
||||
// }
|
||||
|
||||
if (FT_Set_Pixel_Sizes(face, 0, 48))
|
||||
{
|
||||
printf("Error: Setting character size\n");
|
||||
}
|
||||
|
||||
for (glyph_index = 65; glyph_index < 91; glyph_index++)
|
||||
{
|
||||
if (FT_Load_Char(face, glyph_index, FT_LOAD_RENDER))
|
||||
{
|
||||
printf("Error: Loading characte.r\n");
|
||||
}
|
||||
|
||||
bmp = face->glyph->bitmap;
|
||||
|
||||
// printf("Width: %u\n", bmp.width);
|
||||
// printf("Height: %u\n", bmp.rows);
|
||||
// printf("Num grays: %u\n", bmp.num_grays);
|
||||
// printf("Pitch: %d\n", bmp.pitch);
|
||||
|
||||
qdbmp = BMP_Create(bmp.width,bmp.rows,24);
|
||||
BMP_CHECK_ERROR(stdout, 1);
|
||||
|
||||
for (y = 0; y < bmp.rows; y++)
|
||||
{
|
||||
for (x = 0; x < bmp.width; x++)
|
||||
{
|
||||
byte = bmp.buffer[bmp.pitch * y + x];
|
||||
BMP_SetPixelRGB(qdbmp, x, y, 255 - byte, 255 - byte, 255 - byte);
|
||||
BMP_CHECK_ERROR(stdout, 1);
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(filename, "%d", glyph_index);
|
||||
|
||||
BMP_WriteFile(qdbmp, filename);
|
||||
BMP_CHECK_ERROR(stdout, 1);
|
||||
|
||||
}
|
||||
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(library);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,312 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note - The x86 and x64 versions do _not_ produce the same results, as the
|
||||
// algorithms are optimized for their respective platforms. You can still
|
||||
// compile and run any of them on any platform, but your performance with the
|
||||
// non-native version will be less than optimal.
|
||||
|
||||
#include "murmur3.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Platform-specific functions and macros
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#else
|
||||
#define FORCE_INLINE inline
|
||||
#endif
|
||||
|
||||
static FORCE_INLINE uint32_t rotl32 ( uint32_t x, int8_t r )
|
||||
{
|
||||
return (x << r) | (x >> (32 - r));
|
||||
}
|
||||
|
||||
static FORCE_INLINE uint64_t rotl64 ( uint64_t x, int8_t r )
|
||||
{
|
||||
return (x << r) | (x >> (64 - r));
|
||||
}
|
||||
|
||||
#define ROTL32(x,y) rotl32(x,y)
|
||||
#define ROTL64(x,y) rotl64(x,y)
|
||||
|
||||
#define BIG_CONSTANT(x) (x##LLU)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Block read - if your platform needs to do endian-swapping or can only
|
||||
// handle aligned reads, do the conversion here
|
||||
|
||||
#define getblock(p, i) (p[i])
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finalization mix - force all bits of a hash block to avalanche
|
||||
|
||||
static FORCE_INLINE uint32_t fmix32 ( uint32_t h )
|
||||
{
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
h ^= h >> 13;
|
||||
h *= 0xc2b2ae35;
|
||||
h ^= h >> 16;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
//----------
|
||||
|
||||
static FORCE_INLINE uint64_t fmix64 ( uint64_t k )
|
||||
{
|
||||
k ^= k >> 33;
|
||||
k *= BIG_CONSTANT(0xff51afd7ed558ccd);
|
||||
k ^= k >> 33;
|
||||
k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
|
||||
k ^= k >> 33;
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MurmurHash3_x86_32 ( const void * key, int len,
|
||||
uint32_t seed, void * out )
|
||||
{
|
||||
const uint8_t * data = (const uint8_t*)key;
|
||||
const int nblocks = len / 4;
|
||||
int i;
|
||||
|
||||
uint32_t h1 = seed;
|
||||
|
||||
uint32_t c1 = 0xcc9e2d51;
|
||||
uint32_t c2 = 0x1b873593;
|
||||
|
||||
//----------
|
||||
// body
|
||||
|
||||
const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
|
||||
|
||||
for(i = -nblocks; i; i++)
|
||||
{
|
||||
uint32_t k1 = getblock(blocks,i);
|
||||
|
||||
k1 *= c1;
|
||||
k1 = ROTL32(k1,15);
|
||||
k1 *= c2;
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = ROTL32(h1,13);
|
||||
h1 = h1*5+0xe6546b64;
|
||||
}
|
||||
|
||||
//----------
|
||||
// tail
|
||||
|
||||
const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
|
||||
|
||||
uint32_t k1 = 0;
|
||||
|
||||
switch(len & 3)
|
||||
{
|
||||
case 3: k1 ^= tail[2] << 16;
|
||||
case 2: k1 ^= tail[1] << 8;
|
||||
case 1: k1 ^= tail[0];
|
||||
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
|
||||
};
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
|
||||
h1 ^= len;
|
||||
|
||||
h1 = fmix32(h1);
|
||||
|
||||
*(uint32_t*)out = h1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MurmurHash3_x86_128 ( const void * key, const int len,
|
||||
uint32_t seed, void * out )
|
||||
{
|
||||
const uint8_t * data = (const uint8_t*)key;
|
||||
const int nblocks = len / 16;
|
||||
int i;
|
||||
|
||||
uint32_t h1 = seed;
|
||||
uint32_t h2 = seed;
|
||||
uint32_t h3 = seed;
|
||||
uint32_t h4 = seed;
|
||||
|
||||
uint32_t c1 = 0x239b961b;
|
||||
uint32_t c2 = 0xab0e9789;
|
||||
uint32_t c3 = 0x38b34ae5;
|
||||
uint32_t c4 = 0xa1e38b93;
|
||||
|
||||
//----------
|
||||
// body
|
||||
|
||||
const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
|
||||
|
||||
for(i = -nblocks; i; i++)
|
||||
{
|
||||
uint32_t k1 = getblock(blocks,i*4+0);
|
||||
uint32_t k2 = getblock(blocks,i*4+1);
|
||||
uint32_t k3 = getblock(blocks,i*4+2);
|
||||
uint32_t k4 = getblock(blocks,i*4+3);
|
||||
|
||||
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
|
||||
|
||||
h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
|
||||
|
||||
k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
|
||||
|
||||
h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
|
||||
|
||||
k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
|
||||
|
||||
h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
|
||||
|
||||
k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
|
||||
|
||||
h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
|
||||
}
|
||||
|
||||
//----------
|
||||
// tail
|
||||
|
||||
const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
|
||||
|
||||
uint32_t k1 = 0;
|
||||
uint32_t k2 = 0;
|
||||
uint32_t k3 = 0;
|
||||
uint32_t k4 = 0;
|
||||
|
||||
switch(len & 15)
|
||||
{
|
||||
case 15: k4 ^= tail[14] << 16;
|
||||
case 14: k4 ^= tail[13] << 8;
|
||||
case 13: k4 ^= tail[12] << 0;
|
||||
k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
|
||||
|
||||
case 12: k3 ^= tail[11] << 24;
|
||||
case 11: k3 ^= tail[10] << 16;
|
||||
case 10: k3 ^= tail[ 9] << 8;
|
||||
case 9: k3 ^= tail[ 8] << 0;
|
||||
k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
|
||||
|
||||
case 8: k2 ^= tail[ 7] << 24;
|
||||
case 7: k2 ^= tail[ 6] << 16;
|
||||
case 6: k2 ^= tail[ 5] << 8;
|
||||
case 5: k2 ^= tail[ 4] << 0;
|
||||
k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
|
||||
|
||||
case 4: k1 ^= tail[ 3] << 24;
|
||||
case 3: k1 ^= tail[ 2] << 16;
|
||||
case 2: k1 ^= tail[ 1] << 8;
|
||||
case 1: k1 ^= tail[ 0] << 0;
|
||||
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
|
||||
};
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
|
||||
h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
|
||||
|
||||
h1 += h2; h1 += h3; h1 += h4;
|
||||
h2 += h1; h3 += h1; h4 += h1;
|
||||
|
||||
h1 = fmix32(h1);
|
||||
h2 = fmix32(h2);
|
||||
h3 = fmix32(h3);
|
||||
h4 = fmix32(h4);
|
||||
|
||||
h1 += h2; h1 += h3; h1 += h4;
|
||||
h2 += h1; h3 += h1; h4 += h1;
|
||||
|
||||
((uint32_t*)out)[0] = h1;
|
||||
((uint32_t*)out)[1] = h2;
|
||||
((uint32_t*)out)[2] = h3;
|
||||
((uint32_t*)out)[3] = h4;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MurmurHash3_x64_128 ( const void * key, const int len,
|
||||
const uint32_t seed, void * out )
|
||||
{
|
||||
const uint8_t * data = (const uint8_t*)key;
|
||||
const int nblocks = len / 16;
|
||||
int i;
|
||||
|
||||
uint64_t h1 = seed;
|
||||
uint64_t h2 = seed;
|
||||
|
||||
uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
|
||||
uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
|
||||
|
||||
//----------
|
||||
// body
|
||||
|
||||
const uint64_t * blocks = (const uint64_t *)(data);
|
||||
|
||||
for(i = 0; i < nblocks; i++)
|
||||
{
|
||||
uint64_t k1 = getblock(blocks,i*2+0);
|
||||
uint64_t k2 = getblock(blocks,i*2+1);
|
||||
|
||||
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
|
||||
|
||||
h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
|
||||
|
||||
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
|
||||
|
||||
h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
|
||||
}
|
||||
|
||||
//----------
|
||||
// tail
|
||||
|
||||
const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
|
||||
|
||||
uint64_t k1 = 0;
|
||||
uint64_t k2 = 0;
|
||||
|
||||
switch(len & 15)
|
||||
{
|
||||
case 15: k2 ^= (uint64_t)(tail[14]) << 48;
|
||||
case 14: k2 ^= (uint64_t)(tail[13]) << 40;
|
||||
case 13: k2 ^= (uint64_t)(tail[12]) << 32;
|
||||
case 12: k2 ^= (uint64_t)(tail[11]) << 24;
|
||||
case 11: k2 ^= (uint64_t)(tail[10]) << 16;
|
||||
case 10: k2 ^= (uint64_t)(tail[ 9]) << 8;
|
||||
case 9: k2 ^= (uint64_t)(tail[ 8]) << 0;
|
||||
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
|
||||
|
||||
case 8: k1 ^= (uint64_t)(tail[ 7]) << 56;
|
||||
case 7: k1 ^= (uint64_t)(tail[ 6]) << 48;
|
||||
case 6: k1 ^= (uint64_t)(tail[ 5]) << 40;
|
||||
case 5: k1 ^= (uint64_t)(tail[ 4]) << 32;
|
||||
case 4: k1 ^= (uint64_t)(tail[ 3]) << 24;
|
||||
case 3: k1 ^= (uint64_t)(tail[ 2]) << 16;
|
||||
case 2: k1 ^= (uint64_t)(tail[ 1]) << 8;
|
||||
case 1: k1 ^= (uint64_t)(tail[ 0]) << 0;
|
||||
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
|
||||
};
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
|
||||
h1 ^= len; h2 ^= len;
|
||||
|
||||
h1 += h2;
|
||||
h2 += h1;
|
||||
|
||||
h1 = fmix64(h1);
|
||||
h2 = fmix64(h2);
|
||||
|
||||
h1 += h2;
|
||||
h2 += h1;
|
||||
|
||||
((uint64_t*)out)[0] = h1;
|
||||
((uint64_t*)out)[1] = h2;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef _MURMURHASH3_H_
|
||||
#define _MURMURHASH3_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MurmurHash3_x86_32 (const void *key, int len, uint32_t seed, void *out);
|
||||
|
||||
void MurmurHash3_x86_128(const void *key, int len, uint32_t seed, void *out);
|
||||
|
||||
void MurmurHash3_x64_128(const void *key, int len, uint32_t seed, void *out);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _MURMURHASH3_H_
|
|
@ -1,798 +0,0 @@
|
|||
#include "qdbmp.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Bitmap header */
|
||||
typedef struct _BMP_Header
|
||||
{
|
||||
USHORT Magic; /* Magic identifier: "BM" */
|
||||
UINT FileSize; /* Size of the BMP file in bytes */
|
||||
USHORT Reserved1; /* Reserved */
|
||||
USHORT Reserved2; /* Reserved */
|
||||
UINT DataOffset; /* Offset of image data relative to the file's start */
|
||||
UINT HeaderSize; /* Size of the header in bytes */
|
||||
UINT Width; /* Bitmap's width */
|
||||
UINT Height; /* Bitmap's height */
|
||||
USHORT Planes; /* Number of color planes in the bitmap */
|
||||
USHORT BitsPerPixel; /* Number of bits per pixel */
|
||||
UINT CompressionType; /* Compression type */
|
||||
UINT ImageDataSize; /* Size of uncompressed image's data */
|
||||
UINT HPixelsPerMeter; /* Horizontal resolution (pixels per meter) */
|
||||
UINT VPixelsPerMeter; /* Vertical resolution (pixels per meter) */
|
||||
UINT ColorsUsed; /* Number of color indexes in the color table that are actually used by the bitmap */
|
||||
UINT ColorsRequired; /* Number of color indexes that are required for displaying the bitmap */
|
||||
} BMP_Header;
|
||||
|
||||
|
||||
/* Private data structure */
|
||||
struct _BMP
|
||||
{
|
||||
BMP_Header Header;
|
||||
UCHAR* Palette;
|
||||
UCHAR* Data;
|
||||
};
|
||||
|
||||
|
||||
/* Holds the last error code */
|
||||
static BMP_STATUS BMP_LAST_ERROR_CODE = 0;
|
||||
|
||||
|
||||
/* Error description strings */
|
||||
static const char* BMP_ERROR_STRING[] =
|
||||
{
|
||||
"",
|
||||
"General error",
|
||||
"Could not allocate enough memory to complete the operation",
|
||||
"File input/output error",
|
||||
"File not found",
|
||||
"File is not a supported BMP variant (must be uncompressed 8, 24 or 32 BPP)",
|
||||
"File is not a valid BMP image",
|
||||
"An argument is invalid or out of range",
|
||||
"The requested action is not compatible with the BMP's type"
|
||||
};
|
||||
|
||||
|
||||
/* Size of the palette data for 8 BPP bitmaps */
|
||||
#define BMP_PALETTE_SIZE ( 256 * 4 )
|
||||
|
||||
|
||||
|
||||
/*********************************** Forward declarations **********************************/
|
||||
int ReadHeader ( BMP* bmp, FILE* f );
|
||||
int WriteHeader ( BMP* bmp, FILE* f );
|
||||
|
||||
int ReadUINT ( UINT* x, FILE* f );
|
||||
int ReadUSHORT ( USHORT *x, FILE* f );
|
||||
|
||||
int WriteUINT ( UINT x, FILE* f );
|
||||
int WriteUSHORT ( USHORT x, FILE* f );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************** Public methods **********************************/
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Creates a blank BMP image with the specified dimensions
|
||||
and bit depth.
|
||||
**************************************************************/
|
||||
BMP* BMP_Create( UINT width, UINT height, USHORT depth )
|
||||
{
|
||||
BMP* bmp;
|
||||
int bytes_per_pixel = depth >> 3;
|
||||
UINT bytes_per_row;
|
||||
|
||||
if ( height <= 0 || width <= 0 )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( depth != 8 && depth != 24 && depth != 32 )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_FILE_NOT_SUPPORTED;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate the bitmap data structure */
|
||||
bmp = calloc( 1, sizeof( BMP ) );
|
||||
if ( bmp == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Set header' default values */
|
||||
bmp->Header.Magic = 0x4D42;
|
||||
bmp->Header.Reserved1 = 0;
|
||||
bmp->Header.Reserved2 = 0;
|
||||
bmp->Header.HeaderSize = 40;
|
||||
bmp->Header.Planes = 1;
|
||||
bmp->Header.CompressionType = 0;
|
||||
bmp->Header.HPixelsPerMeter = 0;
|
||||
bmp->Header.VPixelsPerMeter = 0;
|
||||
bmp->Header.ColorsUsed = 0;
|
||||
bmp->Header.ColorsRequired = 0;
|
||||
|
||||
|
||||
/* Calculate the number of bytes used to store a single image row. This is always
|
||||
rounded up to the next multiple of 4. */
|
||||
bytes_per_row = width * bytes_per_pixel;
|
||||
bytes_per_row += ( bytes_per_row % 4 ? 4 - bytes_per_row % 4 : 0 );
|
||||
|
||||
|
||||
/* Set header's image specific values */
|
||||
bmp->Header.Width = width;
|
||||
bmp->Header.Height = height;
|
||||
bmp->Header.BitsPerPixel = depth;
|
||||
bmp->Header.ImageDataSize = bytes_per_row * height;
|
||||
bmp->Header.FileSize = bmp->Header.ImageDataSize + 54 + ( depth == 8 ? BMP_PALETTE_SIZE : 0 );
|
||||
bmp->Header.DataOffset = 54 + ( depth == 8 ? BMP_PALETTE_SIZE : 0 );
|
||||
|
||||
|
||||
/* Allocate palette */
|
||||
if ( bmp->Header.BitsPerPixel == 8 )
|
||||
{
|
||||
bmp->Palette = (UCHAR*) calloc( BMP_PALETTE_SIZE, sizeof( UCHAR ) );
|
||||
if ( bmp->Palette == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
|
||||
free( bmp );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bmp->Palette = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate pixels */
|
||||
bmp->Data = (UCHAR*) calloc( bmp->Header.ImageDataSize, sizeof( UCHAR ) );
|
||||
if ( bmp->Data == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
|
||||
free( bmp->Palette );
|
||||
free( bmp );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Frees all the memory used by the specified BMP image.
|
||||
**************************************************************/
|
||||
void BMP_Free( BMP* bmp )
|
||||
{
|
||||
if ( bmp == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( bmp->Palette != NULL )
|
||||
{
|
||||
free( bmp->Palette );
|
||||
}
|
||||
|
||||
if ( bmp->Data != NULL )
|
||||
{
|
||||
free( bmp->Data );
|
||||
}
|
||||
|
||||
free( bmp );
|
||||
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Reads the specified BMP image file.
|
||||
**************************************************************/
|
||||
BMP* BMP_ReadFile( const char* filename )
|
||||
{
|
||||
BMP* bmp;
|
||||
FILE* f;
|
||||
|
||||
if ( filename == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate */
|
||||
bmp = calloc( 1, sizeof( BMP ) );
|
||||
if ( bmp == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Open file */
|
||||
f = fopen( filename, "rb" );
|
||||
if ( f == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_FILE_NOT_FOUND;
|
||||
free( bmp );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Read header */
|
||||
if ( ReadHeader( bmp, f ) != BMP_OK || bmp->Header.Magic != 0x4D42 )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
|
||||
fclose( f );
|
||||
free( bmp );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Verify that the bitmap variant is supported */
|
||||
if ( ( bmp->Header.BitsPerPixel != 32 && bmp->Header.BitsPerPixel != 24 && bmp->Header.BitsPerPixel != 8 )
|
||||
|| bmp->Header.CompressionType != 0 || bmp->Header.HeaderSize != 40 )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_FILE_NOT_SUPPORTED;
|
||||
fclose( f );
|
||||
free( bmp );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate and read palette */
|
||||
if ( bmp->Header.BitsPerPixel == 8 )
|
||||
{
|
||||
bmp->Palette = (UCHAR*) malloc( BMP_PALETTE_SIZE * sizeof( UCHAR ) );
|
||||
if ( bmp->Palette == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
|
||||
fclose( f );
|
||||
free( bmp );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( fread( bmp->Palette, sizeof( UCHAR ), BMP_PALETTE_SIZE, f ) != BMP_PALETTE_SIZE )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
|
||||
fclose( f );
|
||||
free( bmp->Palette );
|
||||
free( bmp );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else /* Not an indexed image */
|
||||
{
|
||||
bmp->Palette = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate memory for image data */
|
||||
bmp->Data = (UCHAR*) malloc( bmp->Header.ImageDataSize );
|
||||
if ( bmp->Data == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
|
||||
fclose( f );
|
||||
free( bmp->Palette );
|
||||
free( bmp );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Read image data */
|
||||
if ( fread( bmp->Data, sizeof( UCHAR ), bmp->Header.ImageDataSize, f ) != bmp->Header.ImageDataSize )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
|
||||
fclose( f );
|
||||
free( bmp->Data );
|
||||
free( bmp->Palette );
|
||||
free( bmp );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
fclose( f );
|
||||
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Writes the BMP image to the specified file.
|
||||
**************************************************************/
|
||||
void BMP_WriteFile( BMP* bmp, const char* filename )
|
||||
{
|
||||
FILE* f;
|
||||
|
||||
if ( filename == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Open file */
|
||||
f = fopen( filename, "wb" );
|
||||
if ( f == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_FILE_NOT_FOUND;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Write header */
|
||||
if ( WriteHeader( bmp, f ) != BMP_OK )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
|
||||
fclose( f );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Write palette */
|
||||
if ( bmp->Palette )
|
||||
{
|
||||
if ( fwrite( bmp->Palette, sizeof( UCHAR ), BMP_PALETTE_SIZE, f ) != BMP_PALETTE_SIZE )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
|
||||
fclose( f );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Write data */
|
||||
if ( fwrite( bmp->Data, sizeof( UCHAR ), bmp->Header.ImageDataSize, f ) != bmp->Header.ImageDataSize )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
|
||||
fclose( f );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
fclose( f );
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Returns the image's width.
|
||||
**************************************************************/
|
||||
UINT BMP_GetWidth( BMP* bmp )
|
||||
{
|
||||
if ( bmp == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
|
||||
return ( bmp->Header.Width );
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Returns the image's height.
|
||||
**************************************************************/
|
||||
UINT BMP_GetHeight( BMP* bmp )
|
||||
{
|
||||
if ( bmp == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
|
||||
return ( bmp->Header.Height );
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Returns the image's color depth (bits per pixel).
|
||||
**************************************************************/
|
||||
USHORT BMP_GetDepth( BMP* bmp )
|
||||
{
|
||||
if ( bmp == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
|
||||
return ( bmp->Header.BitsPerPixel );
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Populates the arguments with the specified pixel's RGB
|
||||
values.
|
||||
**************************************************************/
|
||||
void BMP_GetPixelRGB( BMP* bmp, UINT x, UINT y, UCHAR* r, UCHAR* g, UCHAR* b )
|
||||
{
|
||||
UCHAR* pixel;
|
||||
UINT bytes_per_row;
|
||||
UCHAR bytes_per_pixel;
|
||||
|
||||
if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
|
||||
bytes_per_pixel = bmp->Header.BitsPerPixel >> 3;
|
||||
|
||||
/* Row's size is rounded up to the next multiple of 4 bytes */
|
||||
bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
|
||||
|
||||
/* Calculate the location of the relevant pixel (rows are flipped) */
|
||||
pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x * bytes_per_pixel );
|
||||
|
||||
|
||||
/* In indexed color mode the pixel's value is an index within the palette */
|
||||
if ( bmp->Header.BitsPerPixel == 8 )
|
||||
{
|
||||
pixel = bmp->Palette + *pixel * 4;
|
||||
}
|
||||
|
||||
/* Note: colors are stored in BGR order */
|
||||
if ( r ) *r = *( pixel + 2 );
|
||||
if ( g ) *g = *( pixel + 1 );
|
||||
if ( b ) *b = *( pixel + 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Sets the specified pixel's RGB values.
|
||||
**************************************************************/
|
||||
void BMP_SetPixelRGB( BMP* bmp, UINT x, UINT y, UCHAR r, UCHAR g, UCHAR b )
|
||||
{
|
||||
UCHAR* pixel;
|
||||
UINT bytes_per_row;
|
||||
UCHAR bytes_per_pixel;
|
||||
|
||||
if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
else if ( bmp->Header.BitsPerPixel != 24 && bmp->Header.BitsPerPixel != 32 )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
|
||||
bytes_per_pixel = bmp->Header.BitsPerPixel >> 3;
|
||||
|
||||
/* Row's size is rounded up to the next multiple of 4 bytes */
|
||||
bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
|
||||
|
||||
/* Calculate the location of the relevant pixel (rows are flipped) */
|
||||
pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x * bytes_per_pixel );
|
||||
|
||||
/* Note: colors are stored in BGR order */
|
||||
*( pixel + 2 ) = r;
|
||||
*( pixel + 1 ) = g;
|
||||
*( pixel + 0 ) = b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Gets the specified pixel's color index.
|
||||
**************************************************************/
|
||||
void BMP_GetPixelIndex( BMP* bmp, UINT x, UINT y, UCHAR* val )
|
||||
{
|
||||
UCHAR* pixel;
|
||||
UINT bytes_per_row;
|
||||
|
||||
if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
else if ( bmp->Header.BitsPerPixel != 8 )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
|
||||
/* Row's size is rounded up to the next multiple of 4 bytes */
|
||||
bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
|
||||
|
||||
/* Calculate the location of the relevant pixel */
|
||||
pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x );
|
||||
|
||||
|
||||
if ( val ) *val = *pixel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Sets the specified pixel's color index.
|
||||
**************************************************************/
|
||||
void BMP_SetPixelIndex( BMP* bmp, UINT x, UINT y, UCHAR val )
|
||||
{
|
||||
UCHAR* pixel;
|
||||
UINT bytes_per_row;
|
||||
|
||||
if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
else if ( bmp->Header.BitsPerPixel != 8 )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
|
||||
/* Row's size is rounded up to the next multiple of 4 bytes */
|
||||
bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
|
||||
|
||||
/* Calculate the location of the relevant pixel */
|
||||
pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x );
|
||||
|
||||
*pixel = val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Gets the color value for the specified palette index.
|
||||
**************************************************************/
|
||||
void BMP_GetPaletteColor( BMP* bmp, UCHAR index, UCHAR* r, UCHAR* g, UCHAR* b )
|
||||
{
|
||||
if ( bmp == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
else if ( bmp->Header.BitsPerPixel != 8 )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if ( r ) *r = *( bmp->Palette + index * 4 + 2 );
|
||||
if ( g ) *g = *( bmp->Palette + index * 4 + 1 );
|
||||
if ( b ) *b = *( bmp->Palette + index * 4 + 0 );
|
||||
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Sets the color value for the specified palette index.
|
||||
**************************************************************/
|
||||
void BMP_SetPaletteColor( BMP* bmp, UCHAR index, UCHAR r, UCHAR g, UCHAR b )
|
||||
{
|
||||
if ( bmp == NULL )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
else if ( bmp->Header.BitsPerPixel != 8 )
|
||||
{
|
||||
BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
*( bmp->Palette + index * 4 + 2 ) = r;
|
||||
*( bmp->Palette + index * 4 + 1 ) = g;
|
||||
*( bmp->Palette + index * 4 + 0 ) = b;
|
||||
|
||||
BMP_LAST_ERROR_CODE = BMP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Returns the last error code.
|
||||
**************************************************************/
|
||||
BMP_STATUS BMP_GetError()
|
||||
{
|
||||
return BMP_LAST_ERROR_CODE;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Returns a description of the last error code.
|
||||
**************************************************************/
|
||||
const char* BMP_GetErrorDescription()
|
||||
{
|
||||
if ( BMP_LAST_ERROR_CODE > 0 && BMP_LAST_ERROR_CODE < BMP_ERROR_NUM )
|
||||
{
|
||||
return BMP_ERROR_STRING[ BMP_LAST_ERROR_CODE ];
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************** Private methods **********************************/
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Reads the BMP file's header into the data structure.
|
||||
Returns BMP_OK on success.
|
||||
**************************************************************/
|
||||
int ReadHeader( BMP* bmp, FILE* f )
|
||||
{
|
||||
if ( bmp == NULL || f == NULL )
|
||||
{
|
||||
return BMP_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
/* The header's fields are read one by one, and converted from the format's
|
||||
little endian to the system's native representation. */
|
||||
if ( !ReadUSHORT( &( bmp->Header.Magic ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUINT( &( bmp->Header.FileSize ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUSHORT( &( bmp->Header.Reserved1 ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUSHORT( &( bmp->Header.Reserved2 ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUINT( &( bmp->Header.DataOffset ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUINT( &( bmp->Header.HeaderSize ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUINT( &( bmp->Header.Width ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUINT( &( bmp->Header.Height ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUSHORT( &( bmp->Header.Planes ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUSHORT( &( bmp->Header.BitsPerPixel ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUINT( &( bmp->Header.CompressionType ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUINT( &( bmp->Header.ImageDataSize ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUINT( &( bmp->Header.HPixelsPerMeter ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUINT( &( bmp->Header.VPixelsPerMeter ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUINT( &( bmp->Header.ColorsUsed ), f ) ) return BMP_IO_ERROR;
|
||||
if ( !ReadUINT( &( bmp->Header.ColorsRequired ), f ) ) return BMP_IO_ERROR;
|
||||
|
||||
return BMP_OK;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Writes the BMP file's header into the data structure.
|
||||
Returns BMP_OK on success.
|
||||
**************************************************************/
|
||||
int WriteHeader( BMP* bmp, FILE* f )
|
||||
{
|
||||
if ( bmp == NULL || f == NULL )
|
||||
{
|
||||
return BMP_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
/* The header's fields are written one by one, and converted to the format's
|
||||
little endian representation. */
|
||||
if ( !WriteUSHORT( bmp->Header.Magic, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUINT( bmp->Header.FileSize, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUSHORT( bmp->Header.Reserved1, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUSHORT( bmp->Header.Reserved2, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUINT( bmp->Header.DataOffset, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUINT( bmp->Header.HeaderSize, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUINT( bmp->Header.Width, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUINT( bmp->Header.Height, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUSHORT( bmp->Header.Planes, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUSHORT( bmp->Header.BitsPerPixel, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUINT( bmp->Header.CompressionType, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUINT( bmp->Header.ImageDataSize, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUINT( bmp->Header.HPixelsPerMeter, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUINT( bmp->Header.VPixelsPerMeter, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUINT( bmp->Header.ColorsUsed, f ) ) return BMP_IO_ERROR;
|
||||
if ( !WriteUINT( bmp->Header.ColorsRequired, f ) ) return BMP_IO_ERROR;
|
||||
|
||||
return BMP_OK;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Reads a little-endian unsigned int from the file.
|
||||
Returns non-zero on success.
|
||||
**************************************************************/
|
||||
int ReadUINT( UINT* x, FILE* f )
|
||||
{
|
||||
UCHAR little[ 4 ]; /* BMPs use 32 bit ints */
|
||||
|
||||
if ( x == NULL || f == NULL )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( fread( little, 4, 1, f ) != 1 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*x = ( little[ 3 ] << 24 | little[ 2 ] << 16 | little[ 1 ] << 8 | little[ 0 ] );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Reads a little-endian unsigned short int from the file.
|
||||
Returns non-zero on success.
|
||||
**************************************************************/
|
||||
int ReadUSHORT( USHORT *x, FILE* f )
|
||||
{
|
||||
UCHAR little[ 2 ]; /* BMPs use 16 bit shorts */
|
||||
|
||||
if ( x == NULL || f == NULL )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( fread( little, 2, 1, f ) != 1 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*x = ( little[ 1 ] << 8 | little[ 0 ] );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Writes a little-endian unsigned int to the file.
|
||||
Returns non-zero on success.
|
||||
**************************************************************/
|
||||
int WriteUINT( UINT x, FILE* f )
|
||||
{
|
||||
UCHAR little[ 4 ]; /* BMPs use 32 bit ints */
|
||||
|
||||
little[ 3 ] = (UCHAR)( ( x & 0xff000000 ) >> 24 );
|
||||
little[ 2 ] = (UCHAR)( ( x & 0x00ff0000 ) >> 16 );
|
||||
little[ 1 ] = (UCHAR)( ( x & 0x0000ff00 ) >> 8 );
|
||||
little[ 0 ] = (UCHAR)( ( x & 0x000000ff ) >> 0 );
|
||||
|
||||
return ( f && fwrite( little, 4, 1, f ) == 1 );
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Writes a little-endian unsigned short int to the file.
|
||||
Returns non-zero on success.
|
||||
**************************************************************/
|
||||
int WriteUSHORT( USHORT x, FILE* f )
|
||||
{
|
||||
UCHAR little[ 2 ]; /* BMPs use 16 bit shorts */
|
||||
|
||||
little[ 1 ] = (UCHAR)( ( x & 0xff00 ) >> 8 );
|
||||
little[ 0 ] = (UCHAR)( ( x & 0x00ff ) >> 0 );
|
||||
|
||||
return ( f && fwrite( little, 2, 1, f ) == 1 );
|
||||
}
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
#ifndef _BMP_H_
|
||||
#define _BMP_H_
|
||||
|
||||
|
||||
/**************************************************************
|
||||
|
||||
QDBMP - Quick n' Dirty BMP
|
||||
|
||||
v1.0.0 - 2007-04-07
|
||||
http://qdbmp.sourceforge.net
|
||||
|
||||
|
||||
The library supports the following BMP variants:
|
||||
1. Uncompressed 32 BPP (alpha values are ignored)
|
||||
2. Uncompressed 24 BPP
|
||||
3. Uncompressed 8 BPP (indexed color)
|
||||
|
||||
QDBMP is free and open source software, distributed
|
||||
under the MIT licence.
|
||||
|
||||
Copyright (c) 2007 Chai Braudo (braudo@users.sourceforge.net)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
**************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
/* Type definitions */
|
||||
#ifndef UINT
|
||||
#define UINT unsigned long int
|
||||
#endif
|
||||
|
||||
#ifndef USHORT
|
||||
#define USHORT unsigned short
|
||||
#endif
|
||||
|
||||
#ifndef UCHAR
|
||||
#define UCHAR unsigned char
|
||||
#endif
|
||||
|
||||
|
||||
/* Version */
|
||||
#define QDBMP_VERSION_MAJOR 1
|
||||
#define QDBMP_VERSION_MINOR 0
|
||||
#define QDBMP_VERSION_PATCH 1
|
||||
|
||||
|
||||
/* Error codes */
|
||||
typedef enum
|
||||
{
|
||||
BMP_OK = 0, /* No error */
|
||||
BMP_ERROR, /* General error */
|
||||
BMP_OUT_OF_MEMORY, /* Could not allocate enough memory to complete the operation */
|
||||
BMP_IO_ERROR, /* General input/output error */
|
||||
BMP_FILE_NOT_FOUND, /* File not found */
|
||||
BMP_FILE_NOT_SUPPORTED, /* File is not a supported BMP variant */
|
||||
BMP_FILE_INVALID, /* File is not a BMP image or is an invalid BMP */
|
||||
BMP_INVALID_ARGUMENT, /* An argument is invalid or out of range */
|
||||
BMP_TYPE_MISMATCH, /* The requested action is not compatible with the BMP's type */
|
||||
BMP_ERROR_NUM
|
||||
} BMP_STATUS;
|
||||
|
||||
|
||||
/* Bitmap image */
|
||||
typedef struct _BMP BMP;
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************** Public methods **********************************/
|
||||
|
||||
|
||||
/* Construction/destruction */
|
||||
BMP* BMP_Create ( UINT width, UINT height, USHORT depth );
|
||||
void BMP_Free ( BMP* bmp );
|
||||
|
||||
|
||||
/* I/O */
|
||||
BMP* BMP_ReadFile ( const char* filename );
|
||||
void BMP_WriteFile ( BMP* bmp, const char* filename );
|
||||
|
||||
|
||||
/* Meta info */
|
||||
UINT BMP_GetWidth ( BMP* bmp );
|
||||
UINT BMP_GetHeight ( BMP* bmp );
|
||||
USHORT BMP_GetDepth ( BMP* bmp );
|
||||
|
||||
|
||||
/* Pixel access */
|
||||
void BMP_GetPixelRGB ( BMP* bmp, UINT x, UINT y, UCHAR* r, UCHAR* g, UCHAR* b );
|
||||
void BMP_SetPixelRGB ( BMP* bmp, UINT x, UINT y, UCHAR r, UCHAR g, UCHAR b );
|
||||
void BMP_GetPixelIndex ( BMP* bmp, UINT x, UINT y, UCHAR* val );
|
||||
void BMP_SetPixelIndex ( BMP* bmp, UINT x, UINT y, UCHAR val );
|
||||
|
||||
|
||||
/* Palette handling */
|
||||
void BMP_GetPaletteColor ( BMP* bmp, UCHAR index, UCHAR* r, UCHAR* g, UCHAR* b );
|
||||
void BMP_SetPaletteColor ( BMP* bmp, UCHAR index, UCHAR r, UCHAR g, UCHAR b );
|
||||
|
||||
|
||||
/* Error handling */
|
||||
BMP_STATUS BMP_GetError ();
|
||||
const char* BMP_GetErrorDescription ();
|
||||
|
||||
|
||||
/* Useful macro that may be used after each BMP operation to check for an error */
|
||||
#define BMP_CHECK_ERROR( output_file, return_value ) \
|
||||
if ( BMP_GetError() != BMP_OK ) \
|
||||
{ \
|
||||
fprintf( ( output_file ), "BMP error: %s\n", BMP_GetErrorDescription() ); \
|
||||
return( return_value ); \
|
||||
} \
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue