Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » Allegro5 Save bitmap to byte array

This thread is locked; no one can reply to it. rss feed Print
Allegro5 Save bitmap to byte array
Kevin NO
Member #13,410
August 2011

Hello everyone,
I am looking to convert a sub bitmap to a byte array to save into an SQLite database. I have done it in .NET but I am having a lot of trouble doing it in C++. What I have now looks something like this:

size_t *size = new size_t();
ALLEGRO_FILE *SavFil = malloc(size);
al_save_bitmap_f(SavFil, ".bmp", al_create_sub_bitmap(World, x, y, 16, 16));

but that is totally wrong. How do I access the byte info inside of ALLEGRO_FILE?
do I need to use ALLEGRO_FILE_INTERFACE to access that information? ???
Thanks for the help!

beoran
Member #12,636
March 2011

You will need to use the memfile addon and al_open_memfile()

Kevin NO
Member #13,410
August 2011

Thanks for the quick reply! I am trying to use the memfile, here is what I have:

SubBmp = al_create_sub_bitmap(World, x, y, 16, 16);
al_draw_bitmap(SubBmp, 0,0,NULL);
al_flip_display();

data_size = al_get_bitmap_width(SubBmp) * al_get_bitmap_height(SubBmp) * al_get_pixel_size(al_get_bitmap_format(SubBmp));

ALLEGRO_BITMAP *bmp = al_create_sub_bitmap(World, x, y, 16, 16);
data = (char*)calloc(1, data_size);
ALLEGRO_FILE *memfile = al_open_memfile(buffer, data_size, "w+b");
bool result = al_save_bitmap_f(memfile, ".bmp", SubBmp);
size_t bytes = al_fread(memfile, buffer, data_size);

//Test if buffer has bitmap array
FILE *fp;
fp=fopen("c:\\test.bin", "wb");
fwrite(buffer, sizeof(buffer[0]), sizeof(buffer)/sizeof(buffer[0]), fp);

al_fclose(memfile);
free(data);

Still nothing in the buffer, or at lest i don't think there is.
This also seems like the wrong way of doing it. If you guys could help me on the right path I would really appreciate it. Thanks

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

I wouldn't do it quite that way. It would be easier to lock the bitmap and read the data directly.

Ex :

#SelectExpand
1unsigned char* BitmapBytes(ALLEGRO_BITMAP* bmp , int* size_store) { 2 int size = al_get_bitmap_width(bmp)*al_get_bitmap_height(bmp)*4; 3 unsigned char* buffer = malloc(size); 4 if (buffer) { 5 *size_store = size; 6 } else { 7 *size_store = 0; 8 return 0; 9 } 10 11 ALLEGRO_LOCKED_REGION* lock = al_lock_bitmap(bmp , ALLEGRO_PIXEL_FORMAT_RGBA_8888 , ALLEGRO_LOCK_READONLY); 12 13 for (unsigned int y = 0 ; y < al_get_bitmap_height(bmp) ; ++y) { 14 unsigned char* dat = (unsigned char*)lock->data + 4*y*lock->pitch; 15 memcpy(buffer + 4*y*al_get_bitmap_width(bmp) , dat , 4*al_get_bitmap_width(bmp)); 16 } 17 18 al_unlock_bitmap(bmp); 19 20 return buffer; 21}

Untested, but you get the idea. The bitmap is locked using RGBA_8888 (allegro will perform necessary conversions for you), and then a simple memcpy copies the memory into the newly allocated buffer and the function returns the buffer and stores the size in the int pointer provided to the function.

You can use <code>code goes here...</code> tags to show your code. Makes it easier to read.

Thomas Fjellstrom
Member #476
June 2000
avatar

Untested, but you get the idea. The bitmap is locked using RGBA_8888 (allegro will perform necessary conversions for you), and then a simple memcpy copies the memory into the newly allocated buffer and the function returns the buffer and stores the size in the int pointer provided to the function.

Depends if he wants the actual bitmap headers or not.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Thomas Fjellstrom
Member #476
June 2000
avatar

Depends if he wants it to hit the disk or not ;)

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

The point I was trying to make is that he has to know the exact layout of the file if he wants the headers and he is going to use a memfile, otherwise he doesn't know the exact size of the buffer he needs. That's why I suggested saving to disk.

beoran
Member #12,636
March 2011

In the code above, where does buffer come from? you shoyld use data to initailze the memfile and save that, I think. Also , you seem to draw to the wrong bitmap. It's hard to say without the complete code. Could you psot a complete, compilable example of what you're trying to do?

Kevin NO
Member #13,410
August 2011

Hello, What I am trying to do is read a Large bitmap into a database.
It should be easy, but I am having more trouble than I was thinking it was.
here is my full code:

#SelectExpand
1/* 2#include <stdio.h> 3#ifdef _MSC_VER 4#pragma comment ( linker, "/SUBSYSTEM:CONSOLE") 5#endif #define ALLEGRO_USE_CONSOLE 6#include <allegro5/allegro.h> 7#include <allegro5/allegro_memfile.h> 8 9int main(void) 10{ 11 ALLEGRO_FILE *memfile; 12 char *data; 13 int i; 14 const int data_size = 1024; 15 char buffer[50]; 16 if (!al_init()) 17 { 18 //abort_example("Could not init Allegro.\n"); 19 } 20 data = (char*)calloc(1, data_size); 21 if (!data) return 1; 22 printf("Creating memfile\n"); 23 memfile = al_open_memfile(data, data_size, "rw"); 24 if (!memfile) 25 { 26 printf("Error opening memfile :(\n"); 27 goto Error; 28 } 29 printf("Writing data to memfile\n"); 30 for (i = 0; i < data_size/4; i++) 31 { 32 if (al_fwrite32le(memfile, i) < 4) 33 { 34 printf("Failed to write %i to memfile\n", i); 35 goto Error; 36 } 37 } 38 al_fseek(memfile, 0, ALLEGRO_SEEK_SET); 39 printf("Reading and testing data from memfile\n"); 40 for (i = 0; i < data_size/4; i++) 41 { 42 int32_t ret = al_fread32le(memfile); 43 if (ret != i || al_feof(memfile)) 44 { 45 printf("Item %i failed to verify, got %i\n", i, ret); 46 goto Error; 47 } 48 } 49 if (al_feof(memfile)) 50 { 51 printf("EOF indicator prematurely set!\n"); 52 goto Error; 53 } 54 al_fseek(memfile, 0, ALLEGRO_SEEK_SET); 55 for (i = 0; al_fungetc(memfile, i) != EOF; ++i) { } 56 printf("Length of ungetc buffer: %d\n", i); 57 if (al_ftell(memfile) != -i) 58 { 59 printf("Current position is not correct. Expected -%d, but got %d\n", i, (int) al_ftell(memfile)); 60 goto Error; 61 } 62 while (i--) 63 { 64 if (i != al_fgetc(memfile)) 65 { 66 printf("Failed to verify ungetc data.\n"); 67 goto Error; 68 } 69 } 70 if (al_ftell(memfile) != 0) 71 { 72 printf("Current position is not correct after reading back the ungetc buffer\n"); 73 printf("Expected 0, but got %d\n", (int) al_ftell(memfile)); 74 goto Error; 75 } 76 al_fputs(memfile, "legro rocks!"); 77 al_fseek(memfile, 0, ALLEGRO_SEEK_SET); 78 al_fungetc(memfile, 'l'); 79 al_fungetc(memfile, 'A'); 80 al_fgets(memfile, buffer, 15); 81 if (strcmp(buffer, "Allegro rocks!")) 82 { 83 printf("Expected to see 'Allegro rocks!' but got '%s' instead.\n", buffer); 84 printf("(Maybe the ungetc buffer isn't big enough.)\n"); 85 goto Error; 86 } 87 printf("Done.\n"); 88 al_fclose(memfile); 89 free(data); 90 return 0; 91Error: 92 al_fclose(memfile); 93 free(data); 94 return 1; 95}*/ 96 97#pragma region MyRegion 98#include <stdio.h> 99#include <vector> 100#include <string> 101#include "sqlite3.h" 102#include <allegro5/allegro.h> 103#include <allegro5/allegro_font.h> 104#include <allegro5/allegro_ttf.h> 105#include <allegro5/allegro_image.h> 106#include <allegro5/allegro_memfile.h> 107#include "allegro5/allegro_native_dialog.h" 108#include <fstream> 109 110 111 112static int callback(void *NotUsed, int argc, char **argv, char **azColName){ 113 int i; 114 for(i=0; i<argc; i++){ 115 printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); 116 } 117 printf("\n"); 118 return 0; 119} 120 121unsigned char* BitmapBytes(ALLEGRO_BITMAP* bmp , int* size_store) 122{ 123 int size = al_get_bitmap_width(bmp)*al_get_bitmap_height(bmp)*4; 124 unsigned char* buffer = (unsigned char*)malloc(size); 125 if (buffer) 126 { 127 *size_store = size; 128 } 129 else 130 { 131 *size_store = 0; 132 return 0; 133 } 134 ALLEGRO_LOCKED_REGION* lock = al_lock_bitmap(bmp , ALLEGRO_PIXEL_FORMAT_RGBA_8888 , ALLEGRO_LOCK_READONLY); 135 for (unsigned int y = 0 ; y < al_get_bitmap_height(bmp); ++y) 136 { 137 unsigned char* dat = (unsigned char*)lock->data + 4*y*lock->pitch; 138 memcpy(buffer + 4*y*al_get_bitmap_width(bmp) , dat , 4*al_get_bitmap_width(bmp)); 139 } 140 al_unlock_bitmap(bmp); 141 return buffer; 142} 143 144int main(int argc, char **argv){ 145 146 al_init(); 147 al_init_image_addon(); 148 al_init_font_addon(); 149 al_init_ttf_addon(); 150 151 ALLEGRO_EVENT_QUEUE *event_queue = NULL; 152 event_queue = al_create_event_queue(); 153 154 std::vector<ALLEGRO_BITMAP*> Bitmaps; 155 156 ALLEGRO_DISPLAY *display = al_create_display(640,480); 157 al_register_event_source(event_queue, al_get_display_event_source(display)); 158 ALLEGRO_FONT *font = al_load_ttf_font("C:\\Users\\Kevin\\Desktop\\Programing\\BitmapToSqliteConverter\\Debug\\arial.ttf",24,0 ); 159 160 //al_clear_to_color(al_map_rgb(50,10,70)); 161 162 163 164 ALLEGRO_BITMAP* World = NULL; 165 World = al_load_bitmap("C:/Users/Kevin/Desktop/Programing/BitmapToSqliteConverter/Debug/Island.bmp"); 166 if(!World) { 167 printf("Error loading hello.bmp\n"); 168 return 1; 169 } 170 171 sqlite3 *db; 172 char *zErrMsg = 0; 173 int rc; 174 rc = sqlite3_open("C:\\Users\\Kevin\\Desktop\\Programing\\mov\\movDB", &db); 175 /* Open database */ 176 if( rc ){ 177 fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); 178 exit(0); 179 }else{ 180 fprintf(stderr, "Opened database successfully\n"); 181 } 182 const char* sql; 183 184 char fileName[10]; 185 int count = 0; 186 187 ALLEGRO_FILE *memfile; 188 ALLEGRO_BITMAP *SubBmp; 189 char data[5]; 190 int data_size; 191 unsigned char *buffer; 192 193 void *fileBuffer; 194 void *graphicBuffer; 195 int length = 16; 196 197 for (int y = 10; y < al_get_bitmap_height(World); y = y + 16) 198 { 199 for (int x = 0; x < al_get_bitmap_width(World); x = x + 16) 200 { 201 SubBmp = al_create_sub_bitmap(World, x, y, 16, 16); 202 //buffer = BitmapBytes(SubBmp, &length); 203 count++; 204 itoa(count,data,10); 205 al_save_bitmap(strcat(data,".bmp"),SubBmp); 206 207 } 208 } 209 return 0; 210} 211#pragma endregion

beoran
Member #12,636
March 2011

Hmmm, your coee seems to be missing the point. I have attached an example that cuts up a bitmap and saves it to files using the memfile addon. However, I think you could adapt without too much effort to saving to sqlite using the real_size and buffer.

Here is the code repeated:

#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_memfile.h> 3#include <stdio.h> 4#include <stdlib.h> 5 6 7#define DISPLAY_W 640 8#define DISPLAY_H 480 9 10#define SKIP_W 16 11#define SKIP_H 16 12 13void display_bitmap(ALLEGRO_BITMAP * bmp, int x, int y, double delay) { 14 al_clear_to_color(al_map_rgb(0, 0, 0)); 15 al_draw_bitmap(bmp, (double)x, (double)y, 0); 16 al_flip_display(); 17 al_rest(delay); 18} 19 20bool save_sub_bitmap(ALLEGRO_BITMAP * sub, 21 int x, int y, int slice_w, int slice_h, 22 const char * prefix) { 23 int size; 24 void * buffer; 25 int real_size; 26 ALLEGRO_FILE * memfile; 27 28 if(!sub) { 29 fprintf(stderr, "Could not create sub bitmap!\n"); 30 return false; 31 } 32 /* Allocate a buffer that should always be too big.*/ 33 size = slice_w * slice_h * 4 * 2; 34 buffer = calloc(size, 1); 35 real_size = 0; 36 if(!buffer) { 37 fprintf(stderr, "Could not allocate buffer!\n"); 38 return false; 39 } 40 41 /* Open memfile. */ 42 memfile = al_open_memfile(buffer, size, "rw"); 43 if(!memfile) { 44 fprintf(stderr, "Failed to open memfile!\n"); 45 } else { 46 /* save the bitmap into the memfile. */ 47 al_save_bitmap_f(memfile, ".bmp", sub); 48 /* Get the real size of the bitmap. */ 49 real_size = al_ftell(memfile); 50 if(real_size < 1) { 51 fprintf(stderr, "Real size is too small!\n"); 52 } else { 53 /* now, buffer contains the correct bitmap data. Save that to a file 54 * (but if could be stored into sqlite as well, if needed). */ 55 FILE * output; 56 char filename[255]; 57 sprintf(filename, "%.16s_%d_%d.bmp\0", prefix, (int)(x / slice_w) + 1, (int)(y/slice_h) + 1); 58 output = fopen(filename, "w"); 59 if(!output) { 60 fprintf(stderr, "Could not open output file!\n"); 61 } else { 62 fwrite(buffer, size, 1, output); 63 fclose(output); 64 } 65 } 66 al_fclose(memfile); 67 } 68 free(buffer); 69} 70 71 72bool split_and_save_bitmap(ALLEGRO_BITMAP * input, int slice_w, int slice_h, const char * prefix) { 73 int x, y; 74 for(y = 0; y < al_get_bitmap_height(input) ; y += slice_h) { 75 for(x = 0; x < al_get_bitmap_width(input) ; x += slice_w) { 76 /* create the sub bitmap */ 77 ALLEGRO_BITMAP * sub = al_create_sub_bitmap(input, x, y, slice_w, slice_h); 78 /* display it, then save it, and then clean up. */ 79 display_bitmap(sub, x, y, 0.1); 80 save_sub_bitmap(sub, x, y, slice_w, slice_h, prefix); 81 al_destroy_bitmap(sub); 82 } 83 } 84 85} 86 87 88int main(int argc, char ** argv) { 89 ALLEGRO_DISPLAY * display = NULL; 90 ALLEGRO_BITMAP * input = NULL; 91 92 if (!al_init()) { 93 fprintf(stderr, "Failed to initialize allegro!\n"); 94 return 1; 95 } 96 97 if (!al_init_image_addon()) { 98 fprintf(stderr, "Failed to initialize image addon!\n"); 99 return 2; 100 } 101 102 display = al_create_display(DISPLAY_W, DISPLAY_H); 103 if(!display) { 104 fprintf(stderr, "Failed to create display!\n"); 105 return 3; 106 } 107 108 input = al_load_bitmap("input.png"); 109 if (!input) { 110 fprintf(stderr, "Failed to load input!\n"); 111 al_destroy_display(display); 112 return 4; 113 } 114 /* Display loaded bitmap */ 115 display_bitmap(input, 0.0, 0.0, 0.5); 116 /* Now split and save it. */ 117 split_and_save_bitmap(input, SKIP_W, SKIP_H, "output"); 118 119 al_destroy_display(display); 120}

Oh and here is an example of how to save a binary blob, which would be a bitmap file in your case, using sqlite3 http://www.sqlite.org/cvstrac/wiki?p=BlobExample

Go to: