Open katastic opened 2 years ago
Saving to a TARGA is also affected since TARGA supports alpha channels. PCX and BMP output fine.
Also, DDS doesn't appear to output any file at all even though the documentation says PCX, BMP, TGA and DDS are supported always. Separate issue raised for that #1339
What does al_get_pixel
return on one of the black regions of your screen?
RGBA
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
0.000000 0.000000 0.000000 0.623529
Not sure if anyone else needs this, but I wrote this D function to work around the problem.
void al_save_screen(string path)
{
auto disp = al_get_backbuffer(al_display);
auto w = al_get_bitmap_width(disp);
auto h = al_get_bitmap_height(disp);
ALLEGRO_BITMAP* temp = al_create_bitmap(w, h);
al_lock_bitmap(temp, al_get_bitmap_format(temp), ALLEGRO_LOCK_WRITEONLY);
al_lock_bitmap(disp, al_get_bitmap_format(temp), ALLEGRO_LOCK_READONLY); // makes HUGE difference (6.4 seconds vs 270 milliseconds)
al_set_target_bitmap(temp);
for(int j = 0; j < h; j++)
for(int i = 0; i < w; i++)
{
auto pixel = al_get_pixel(disp, i, j);
pixel.a = 1.0; // remove alpha
al_put_pixel(i, j, pixel);
}
al_unlock_bitmap(disp);
al_unlock_bitmap(temp);
al_save_bitmap(path.toStringz, temp);
al_reset_target();
al_destroy_bitmap(temp);
}
Which runs in ~250 ms on my netbook vs ~170 ms for al_save_bitmap(). Resolution is ~1366x768. It would be very few changes to port it to C.
[edit] It appears doing clear_to_color on the destination, then adding the display, still produces the problem
al_set_target_bitmap(temp);
al_clear_to_color(ALLEGRO_COLOR(0,0,0,1));
al_draw_bitmap(disp, 0, 0, 0);
Though it's marginally faster at ~210 ms.
I don't understand why compositing it onto an opaque black bitmap doesn't work. I (independently) wrote this
void save_opaque(const char* fi, ALLEGRO_BITMAP* b) {
// Create clone bitmap
int w = al_get_bitmap_width(b);
int h = al_get_bitmap_height(b);
ALLEGRO_BITMAP* tmp = al_create_bitmap(w, h);
// Remember current target
ALLEGRO_BITMAP* old = al_get_target_bitmap();
al_set_target_bitmap(tmp);
// Clear to opaque black
al_clear_to_color(al_map_rgba_f(0.0f, 0.0f, 0.0f, 1.0f));
al_draw_bitmap(b, 0.0f, 0.0f, 0);
// Save and clean up
al_save_bitmap(fi, tmp);
al_destroy_bitmap(tmp);
// Restore target
al_set_target_bitmap(old);
}
to be called like save_opaque("shot.png", al_get_backbuffer(al_get_current_display()));
and it 'worked' - but on my system the backbuffer never had an alpha channel anyway.
Also is it possible to create a colour with ALLEGRO_COLOR(0,0,0,1)
rather than al_map_rgba_f
, is that a D thing?
That's a D-syntax, but in C/C++ you can use {0, 0, 0, 1}
or w/e other struct initializer syntax. ALLEGRO_COLOR
has all of its fields public.
As for this issue, I'd like to know why the screen has alpha < 1. Maybe I need to try to compile your game and see what's up.
Something seems odd. The background should be opaque; katastic is drawing a layer with alpha=1 then one with alpha = 0.5 then one with alpha = 0.25: https://github.com/katastic/dgravity/blob/daf46923b22ece54458d206ff2a195869b4475a4/src/g.d#L250-L270 It's just the backbuffer seems to have some other idea about alpha. Also in this minimal (C) code
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
/* You can make blob.png with imagemagick: */
/* magick logo: -resize 64x64 -transparent white blob.png */
int main() {
al_init();
al_init_image_addon();
ALLEGRO_DISPLAY* disp = al_create_display(320,240);
al_clear_to_color(al_map_rgba_f(0.0f, 0.0f, 0.0f, 0.0f));
ALLEGRO_BITMAP* blob = al_load_bitmap("blob.png");
al_draw_bitmap(blob, 0.0f, 0.0f, 0);
al_save_bitmap("direct.png", al_get_backbuffer(disp));
ALLEGRO_BITMAP* tmp = al_create_bitmap(320,240);
al_set_target_bitmap(tmp);
al_clear_to_color(al_map_rgba_f(0.0f, 1.0f, 0.0f, 1.0f));
al_draw_bitmap(al_get_backbuffer(disp), 0.0f, 0.0f, 0);
al_save_bitmap("indirect.png", tmp);
return 0;
}
I'd expect indirect.png to be blob.png on a green background but it is just transparent same as direct.png. (apologies if I've misunderstood alpha blending!)
If there's a snippet of code you want me to try on my machine, I can do that. I'm going to re-try the provided clear_to_color() code tonight to double check I'm not mixing up screenshots with code.
And maybe do some al_get_pixel logging between each draw layer of the "space" textures.
The images I'm drawing (of which you can grab from my dgravity repo above), all have transparency layers themselves, in addition to drawing them with al_draw_tinted_bitmap() alpha values.
Also the blending mode used (perhaps this is key):
al_set_blender(ALLEGRO_BLEND_OPERATIONS.ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
[edit]
al_clear_to_color(ALLEGRO_COLOR(0,0,0,1));
al_draw_bitmap(disp, 0, 0, 0);
definitely keeps the transparency compared to
for(int j = 0; j < h; j++)
for(int i = 0; i < w; i++)
{
auto pixel = al_get_pixel(disp, i, j);
pixel.a = 1.0; // remove alpha
al_put_pixel(i, j, pixel);
}
Right. I was able to compile and run your game on MacOS and get the same issue with the translucent screenshot, so it's not a platform dependent thing. (D compiles amazingly quick, it's really impressive!) In a nutshell I'd expect drawing a translucent image over an opaque background to give me an opaque bitmap with the image blended in. In my mini-program above, drawing the backbuffer onto a background just replaces the background with the screen image, alpha and all.
I've experienced this problem independently too, so I've got some nuggets of wisdom to share.
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
ALLEGRO_PIXEL_FORMAT_ABGR_8888
on my old machine, and ALLEGRO_PIXEL_FORMAT_ARGB_8888
in the current one, so that's probably not the issue.ALLEGRO_RED_SHIFT
0 vs 16ALLEGRO_BLUE_SHIFT
16 vs 0ALLEGRO_ACC_RED_SIZE
to ALLEGRO_ACC_ALPHA_SIZE
16 vs 0ALLEGRO_AUX_BUFFERS
4 vs 0ALLEGRO_DEPTH_SIZE
24 vs 0ALLEGRO_STENCIL_SIZE
8 vs 0ALLEGRO_SWAP_METHOD
32867 (?) vs 0ALLEGRO_OPENGL_MINOR_VERSION
5 vs 6Hopefully these will help figure out the problem.
I just posted on A.CC but the server is currently half-dead so here we go.
Saving a screenshot of the screen is wrong (at least on Linux). I just realized it's dumping a alpha channel! Which, AFAIK, is meaningless for a screen.
gnome-screenshot yields this:
al_save_bitmap loading with GIMP does this: (note alpha channel visible)
Relevant Allegro code line: https://github.com/liballeg/allegro5/blob/20ea4d7bdd9e9999a9d89278dc06dc453fa3f0a6/src/bitmap_io.c#L223
Since this supports multiple "file handlers", it may not affect non-PNG save formats. I'll test that now. Though PNG is of course, 'the best' format to use.