![]() |
|
Convert *bitmap to char buffer |
Scooter
Member #16,799
January 2018
|
Hi all: |
LennyLen
Member #5,313
December 2004
![]() |
I'm guessing since you reference BITMAP and not ALLEGRO_BITMAP that you mean A4. If so, then this should hopefully help: https://www.allegro.cc/manual/4/api/direct-access-to-video-memory/
|
Scooter
Member #16,799
January 2018
|
Hi LennyLen: Thanks for your reply, have a great day! |
DanielH
Member #934
January 2001
![]() |
Your original post said to put an allegro bitmap into char buffer. strcpy_s(my_buffer, size of my buffer, new name); |
Scooter
Member #16,799
January 2018
|
Hi Daniel: |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Learn the difference between a pointer and an array. char[100] is an array. char* is a pointer. If you want to copy into a char buffer fine, declare an array of char large enough to hold + 1 for the null or allocate memory for it. Then use strncpy to copy it into your char buffer. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Scooter
Member #16,799
January 2018
|
Hi Edgar: |
DanielH
Member #934
January 2001
![]() |
So you do want to save a bitmap to a char buffer. I am thoroughly confused. It's not so easy. The ALLEGRO_BITMAP pointer doesn't just point to the ALLEGRO_BITMAP struct. There are internal data pointers as well that point somewhere else. It is doable. Hardest part would be calculating the buffer size needed? Take a look at the struct. 1struct ALLEGRO_BITMAP
2{
3 ALLEGRO_BITMAP_INTERFACE *vt;
4
5 /*
6 * When this is a sub-bitmap, these are inherited from the parent. Don't
7 * access them directly, but use al_get_bitmap_format/flags or
8 * _al_get_bitmap_display unless you are super sure this is not a sub-bitmap
9 * (e.g. when you're creating a new bitmap).
10 */
11 int _format;
12 int _flags;
13 int _depth;
14 int _samples;
15 ALLEGRO_DISPLAY *_display;
16 ALLEGRO_BITMAP_WRAP _wrap_u;
17 ALLEGRO_BITMAP_WRAP _wrap_v;
18 /* What format is used for the backing memory
19 * (can be different from _format, for e.g. compressed bitmaps) */
20 int _memory_format;
21
22 int w, h;
23 /*
24 * The number of bytes between a pixel at (x,y) and (x,y+1).
25 * This is larger than w * pixel_size if there is padding between lines.
26 */
27 int pitch;
28 /*
29 * clip left, right, top, bottom
30 * Clip anything outside of this. cr/cb are exclusive, that is (0, 0, 1, 1)
31 * is the single pixel spawning a rectangle from floating point 0/0 to 1/1 -
32 * or in other words, the single pixel 0/0.
33 *
34 * There is always confusion as to whether cr/cb are exclusive, leading to
35 * subtle bugs. The suffixes are supposed to help with that.
36 */
37 int cl;
38 int cr_excl;
39 int ct;
40 int cb_excl;
41 /*
42 * Locking info.
43 *
44 * These values represent the actual locking dimensions, which may be different
45 * from what was passed in to al_lock_bitmap_region. This is transparent to the
46 * user, but the internal drawing functions must take this into account. To
47 * that end, use this lock_data parameter value and NOT the one in locked_region.
48 *
49 * locked - locked or not?
50 * lock_x/y - top left of the locked region
51 * lock_w/h - width and height of the locked region
52 * lock_flags - flags the region was locked with
53 * lock_data - the pointer to the real locked data (see above)
54 * locked_region - a copy of the locked rectangle
55 */
56 bool locked;
57 int lock_x;
58 int lock_y;
59 int lock_w;
60 int lock_h;
61 void* lock_data;
62 int lock_flags;
63 ALLEGRO_LOCKED_REGION locked_region;
64
65 /* Transformation for this bitmap */
66 ALLEGRO_TRANSFORM transform;
67 ALLEGRO_TRANSFORM inverse_transform;
68 bool inverse_transform_dirty;
69 ALLEGRO_TRANSFORM proj_transform;
70
71 /* Blender for this bitmap (if not set, use TLS) */
72 bool use_bitmap_blender;
73 ALLEGRO_BLENDER blender;
74
75 /* Shader applied to this bitmap. Set this field with
76 * _al_set_bitmap_shader_field to maintain invariants.
77 */
78 ALLEGRO_SHADER *shader;
79
80 /* Info for sub-bitmaps */
81 ALLEGRO_BITMAP *parent;
82 int xofs;
83 int yofs;
84
85 /* A memory copy of the bitmap data. May be NULL for an empty bitmap. */
86 unsigned char *memory;
87
88 /* Extra data for display bitmaps, like texture id and so on. */
89 void *extra;
90
91 _AL_LIST_ITEM *dtor_item;
92
93 /* set_target_bitmap and lock_bitmap mark bitmaps as dirty for preservation */
94 bool dirty;
95};
You could also look at the register save and load functions. Make your own that loads/saves to/from a char buffer. After all that, I don't know why you would want to. EDIT: |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
>EDIT: I wonder that also. Please be very clear what you want, and array of rgb stored in char, or a string name to save the file as? My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Scooter
Member #16,799
January 2018
|
Edgar and Daniel: if(lp == true); { // saving DEFAULT image al_set_target_bitmap(temp_image); temp_image = al_load_bitmap(name); al_save_bitmap("sample.png", temp_image); al_destroy_bitmap(temp_image); } Notice the (name) buffer called. Everything is still fine. I am happy!!! Now I want to modify that image. Buffer called name[] is no longer valid, Now I save the modified image. Code below: if(rt == true || mr == true || dt == true) { // saving ROTATED OR MIRROR images temp_image = al_create_bitmap(screen_width, working_screen_height); al_set_target_bitmap(temp_image); al_draw_bitmap(al_get_backbuffer(display), 0, 0, 0); al_set_target_backbuffer(display); al_save_bitmap("sample.png", temp_image); al_destroy_bitmap(temp_image); } Sorry, the code ran over to the next line.
I go back to the file manager. I see the "sample.png" file but I also see the I hope it is clear now. Thanks again for your time. |
DanielH
Member #934
January 2001
![]() |
You modify the image, name hasn't changed since you set it to argv[1] First code Second code So, what's the problem? Why do you say name[] is invalid if image is modified. also, use a bitmap to keep your bitmap in and don't use the display's back buffer. Do you need to save the entire display? OR just the bitmap you modified? Maybe if you explain a bit what your app does. |
Scooter
Member #16,799
January 2018
|
Hi Daniel: |
DanielH
Member #934
January 2001
![]() |
You said you had a char buffer called name. At the start of your program, copy argv[1] to name. No need to ever use argv after that. Here's and app that loads a bitmap from argv[1], modifies it, and save 1#include <allegro5/allegro.h>
2#include <allegro5/allegro_image.h>
3#include <string>
4
5const int display_width = 1366;
6const int display_height = 768;
7ALLEGRO_DISPLAY* display = nullptr;
8ALLEGRO_EVENT_QUEUE* queue = nullptr;
9ALLEGRO_TIMER* timer = nullptr;
10int32_t logic_counter = 0;
11bool kill = false;
12bool dirty = true;
13const char name[] = "My App Name";
14ALLEGRO_BITMAP* bitmap = nullptr;
15char bitmap_filename[256] = "";
16bool bitmap_is_modified = false;
17bool mouse_button_was_pressed = false;
18int bitmap_x = 100;
19int bitmap_y = 100;
20int mouse_x = 0;
21int mouse_y = 0;
22
23int init(int argc, char** argv);
24void shutdown();
25int32_t do_loop();
26void draw_display();
27void process_logic();
28void process_input();
29void display_set_title();
30
31int main(int argc, char** argv)
32{
33 if (init(argc, argv) == 0)
34 {
35 do_loop();
36 }
37
38 shutdown();
39
40 return 0;
41}
42
43int init(int argc, char** argv)
44{
45 if (argc == 2)
46 {
47 strcpy_s(bitmap_filename, 256, argv[1]);
48 }
49
50 if (!al_init())
51 {
52 return -1;
53 }
54
55 if (!al_install_mouse())
56 {
57 return -1;
58 }
59
60 if (!al_install_keyboard())
61 {
62 return -1;
63 }
64
65 if (!al_init_image_addon())
66 {
67 return -1;
68 }
69
70 al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST);
71 al_set_new_display_option(ALLEGRO_SAMPLES, 8, ALLEGRO_SUGGEST);
72 al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE);
73 display = al_create_display(display_width, display_height);
74 if (!display)
75 {
76 return -1;
77 }
78 display_set_title();
79
80 queue = al_create_event_queue();
81 if (!queue)
82 {
83 return -1;
84 }
85
86 timer = al_create_timer(1.0 / 60.0);
87 if (!timer)
88 {
89 return -1;
90 }
91
92 if (argc == 2)
93 {
94 if (bitmap)
95 {
96 al_destroy_bitmap(bitmap);
97 }
98 bitmap = al_load_bitmap(bitmap_filename);
99
100 if (!bitmap)
101 {
102 return -1;
103 }
104 }
105
106 al_register_event_source(queue, al_get_display_event_source(display));
107 al_register_event_source(queue, al_get_timer_event_source(timer));
108 al_register_event_source(queue, al_get_keyboard_event_source());
109 al_register_event_source(queue, al_get_mouse_event_source());
110
111 al_start_timer(timer);
112
113 return 0;
114}
115
116void shutdown()
117{
118 if (bitmap)
119 {
120 al_destroy_bitmap(bitmap);
121 bitmap = nullptr;
122 }
123
124 if (timer)
125 {
126 al_stop_timer(timer);
127 al_destroy_timer(timer);
128 timer = nullptr;
129 }
130
131 if (queue)
132 {
133 al_destroy_event_queue(queue);
134 queue = nullptr;
135 }
136
137 if (display)
138 {
139 al_destroy_display(display);
140 display = nullptr;
141 }
142}
143
144int32_t do_loop()
145{
146 while (!kill)
147 {
148 process_input();
149
150 while (logic_counter > 0)
151 {
152 process_logic();
153 --logic_counter;
154 }
155
156 if (dirty)
157 {
158 draw_display();
159 dirty = false;
160 }
161
162 al_rest(0.01);
163 }
164
165 return 0;
166}
167
168void draw_display()
169{
170 al_set_target_bitmap(al_get_backbuffer(display));
171 al_clear_to_color(al_map_rgb(255, 255, 255));
172
173 if (bitmap)
174 {
175 al_draw_bitmap(bitmap, bitmap_x, bitmpa_y, 0);
176 }
177
178 al_flip_display();
179}
180
181void process_logic()
182{
183 if (mouse_button_was_pressed)
184 {
185 if (bitmap)
186 {
187 ALLEGRO_LOCKED_REGION* region = al_lock_bitmap(bitmap, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY);
188 ALLEGRO_BITMAP* target = al_get_target_bitmap();
189 al_set_target_bitmap(bitmap);
190 al_put_pixel(mouse_x - bitmap_x, mouse_y - bitmap_y, al_map_rgb(0, 0, 0));
191 al_set_target_bitmap(target);
192 al_unlock_bitmap(bitmap);
193 bitmap_is_modified = true;
194 display_set_title();
195 dirty = true;
196 }
197 }
198}
199
200void process_input()
201{
202 static ALLEGRO_EVENT event;
203
204 while (!al_event_queue_is_empty(queue))
205 {
206 al_get_next_event(queue, &event);
207
208 switch (event.type)
209 {
210 case ALLEGRO_EVENT_TIMER:
211 {
212 ++logic_counter;
213 } break;
214
215 case ALLEGRO_EVENT_DISPLAY_CLOSE:
216 {
217 kill = true;
218 } break;
219
220 case ALLEGRO_EVENT_MOUSE_AXES:
221 {
222 mouse_x = event.mouse.x;
223 mouse_y = event.mouse.y;
224
225 } break;
226
227 case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
228 {
229 if (event.mouse.button == 1)
230 {
231 mouse_button_was_pressed = false;
232 }
233 } break;
234
235 case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
236 {
237 if (event.mouse.button == 1)
238 {
239 mouse_button_was_pressed = true;
240 }
241 } break;
242
243 case ALLEGRO_EVENT_KEY_UP:
244 {
245 if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
246 {
247 kill = true;
248 }
249
250 if (event.keyboard.keycode == ALLEGRO_KEY_F2)
251 {
252 if (bitmap)
253 {
254 al_save_bitmap("sample.png", bitmap);
255 bitmap_is_modified = false;
256 display_set_title();
257 }
258 }
259 } break;
260 }
261 }
262}
263
264void display_set_title()
265{
266 char title[256] = "";
267
268 strcat_s(title, 256, name);
269
270 if (bitmap_filename[0] != 0)
271 {
272 strcat_s(title, 256, " - ");
273 strcat_s(title, 256, bitmap_filename);
274
275 if (bitmap_is_modified)
276 {
277 strcat_s(title, 256, "*");
278 }
279 }
280
281 al_set_window_title(display, title);
282}
|
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
It's a matter of shallow vs deep copy. If you just point to argv[1], any changes to it will change argv[1]. Just make a char buffer and copy the new name into it. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
DanielH
Member #934
January 2001
![]() |
You could also add a function to load a different bitmap and modify name. If you had some sort of fileloader dialog or whatever. 1bool bitmap_load(const char* filename)
2{
3 if (!filename)
4 {
5 return false;
6 }
7
8 if (bitmap)
9 {
10 al_destroy_bitmap(bitmap);
11 }
12
13 bitmap = al_load_bitmap(filename);
14 if (!bitmap)
15 {
16 return false;
17 }
18
19 strcpy_s(name, 256, filename);
20 bitmap_is_modified = false;
21
22 return true;
23}
|
Scooter
Member #16,799
January 2018
|
Hi Daniel and Edgar: |
DanielH
Member #934
January 2001
![]() |
Are you changing argv in your code? While it is not constant, if you don't modify it, then it will always point to the same array of constant strings. Also, it will persist throughout runtime, You shouldn't have any program accessing it at any point (inside of scope). If outside of scope, then make a buffer. char name[256] = ""; // valid throughout source file int main(int argc, char** argv) // valid only inside main. { } Unless your modifying it. Also, can post code? |
Scooter
Member #16,799
January 2018
|
Hi Daniel: |
AceBlkwell
Member #13,038
July 2011
![]() |
This is probably a stupid suggestion and not applicable, but is there any way to declare argv[1] static? I know when you want to keep a value in a variable for when you re-enter a function, you can make it static and value does not reinitialize. static int count = 0; Just thinking out loud. Or maybe write the name to global variable or file? Again, just shooting in the dark. |
DanielH
Member #934
January 2001
![]() |
Once again, why and huh? Reenter function? They are already static because they will only ever be alive while your program is running. Which is the entire time. Just because you jump to other code and back doesn't change that. |
Scooter
Member #16,799
January 2018
|
Hi Daniel: |
DanielH
Member #934
January 2001
![]() |
Don't give up. Scooter said: The name buffer is still not updating Are you not updating the name buffer? It won't magically change unless you change it. Did you create a name buffer or are you only using argv[1]? I'm still confused on what you are doing or not doing or what you are trying to accomplish. |
|