mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 12:17:44 +00:00
LibGfx: Don't mix up red/blue channels when blitting RGBA8888 bitmap
This makes CanvasRenderingContext2D.putImageData() actually paint the right colors into the canvas.
This commit is contained in:
parent
72689ce7bd
commit
9fa78b1a05
1 changed files with 19 additions and 1 deletions
|
@ -769,8 +769,21 @@ struct BlitState {
|
||||||
int row_count;
|
int row_count;
|
||||||
int column_count;
|
int column_count;
|
||||||
float opacity;
|
float opacity;
|
||||||
|
BitmapFormat src_format;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// FIXME: This is a hack to support blit_with_opacity() with RGBA8888 source.
|
||||||
|
// Ideally we'd have a more generic solution that allows any source format.
|
||||||
|
static void swap_red_and_blue_channels(Color& color)
|
||||||
|
{
|
||||||
|
u32 rgba = color.value();
|
||||||
|
u32 bgra = (rgba & 0xff00ff00)
|
||||||
|
| ((rgba & 0x000000ff) << 16)
|
||||||
|
| ((rgba & 0x00ff0000) >> 16);
|
||||||
|
color = Color::from_argb(bgra);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: This function is very unoptimized.
|
||||||
template<BlitState::AlphaState has_alpha>
|
template<BlitState::AlphaState has_alpha>
|
||||||
static void do_blit_with_opacity(BlitState& state)
|
static void do_blit_with_opacity(BlitState& state)
|
||||||
{
|
{
|
||||||
|
@ -779,11 +792,15 @@ static void do_blit_with_opacity(BlitState& state)
|
||||||
Color dest_color = (has_alpha & BlitState::DstAlpha) ? Color::from_argb(state.dst[x]) : Color::from_rgb(state.dst[x]);
|
Color dest_color = (has_alpha & BlitState::DstAlpha) ? Color::from_argb(state.dst[x]) : Color::from_rgb(state.dst[x]);
|
||||||
if constexpr (has_alpha & BlitState::SrcAlpha) {
|
if constexpr (has_alpha & BlitState::SrcAlpha) {
|
||||||
Color src_color_with_alpha = Color::from_argb(state.src[x]);
|
Color src_color_with_alpha = Color::from_argb(state.src[x]);
|
||||||
|
if (state.src_format == BitmapFormat::RGBA8888)
|
||||||
|
swap_red_and_blue_channels(src_color_with_alpha);
|
||||||
float pixel_opacity = src_color_with_alpha.alpha() / 255.0;
|
float pixel_opacity = src_color_with_alpha.alpha() / 255.0;
|
||||||
src_color_with_alpha.set_alpha(255 * (state.opacity * pixel_opacity));
|
src_color_with_alpha.set_alpha(255 * (state.opacity * pixel_opacity));
|
||||||
state.dst[x] = dest_color.blend(src_color_with_alpha).value();
|
state.dst[x] = dest_color.blend(src_color_with_alpha).value();
|
||||||
} else {
|
} else {
|
||||||
Color src_color_with_alpha = Color::from_rgb(state.src[x]);
|
Color src_color_with_alpha = Color::from_rgb(state.src[x]);
|
||||||
|
if (state.src_format == BitmapFormat::RGBA8888)
|
||||||
|
swap_red_and_blue_channels(src_color_with_alpha);
|
||||||
src_color_with_alpha.set_alpha(state.opacity * 255);
|
src_color_with_alpha.set_alpha(state.opacity * 255);
|
||||||
state.dst[x] = dest_color.blend(src_color_with_alpha).value();
|
state.dst[x] = dest_color.blend(src_color_with_alpha).value();
|
||||||
}
|
}
|
||||||
|
@ -826,7 +843,8 @@ void Painter::blit_with_opacity(IntPoint const& position, Gfx::Bitmap const& sou
|
||||||
.dst_pitch = m_target->pitch() / sizeof(ARGB32),
|
.dst_pitch = m_target->pitch() / sizeof(ARGB32),
|
||||||
.row_count = last_row - first_row + 1,
|
.row_count = last_row - first_row + 1,
|
||||||
.column_count = last_column - first_column + 1,
|
.column_count = last_column - first_column + 1,
|
||||||
.opacity = opacity
|
.opacity = opacity,
|
||||||
|
.src_format = source.format(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (source.has_alpha_channel() && apply_alpha) {
|
if (source.has_alpha_channel() && apply_alpha) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue