diff --git a/Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp index d9404601d0..443041746e 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp @@ -750,7 +750,9 @@ static ARGB32 add_argb32(ARGB32 a, ARGB32 b) class Transform { public: virtual ~Transform(); - virtual ErrorOr transform(Bitmap&) = 0; + + // Could modify the input bitmap and return it, or could return a new bitmap. + virtual ErrorOr> transform(NonnullRefPtr) = 0; }; Transform::~Transform() = default; @@ -759,7 +761,7 @@ Transform::~Transform() = default; class PredictorTransform : public Transform { public: static ErrorOr> read(WebPLoadingContext&, LittleEndianInputBitStream&, IntSize const& image_size); - virtual ErrorOr transform(Bitmap&) override; + virtual ErrorOr> transform(NonnullRefPtr) override; private: PredictorTransform(int size_bits, NonnullRefPtr predictor_bitmap) @@ -857,8 +859,10 @@ ErrorOr> PredictorTransform::read(WebPLoadingC return adopt_nonnull_own_or_enomem(new (nothrow) PredictorTransform(size_bits, move(predictor_bitmap))); } -ErrorOr PredictorTransform::transform(Bitmap& bitmap) +ErrorOr> PredictorTransform::transform(NonnullRefPtr bitmap_ref) { + Bitmap& bitmap = *bitmap_ref; + // "There are special handling rules for some border pixels. // If there is a prediction transform, regardless of the mode [0..13] for these pixels, // the predicted value for the left-topmost pixel of the image is 0xff000000, @@ -908,7 +912,7 @@ ErrorOr PredictorTransform::transform(Bitmap& bitmap) bitmap_previous_scanline = bitmap_scanline; } - return {}; + return bitmap_ref; } ErrorOr PredictorTransform::predict(u8 predictor, ARGB32 TL, ARGB32 T, ARGB32 TR, ARGB32 L) @@ -980,7 +984,7 @@ ErrorOr PredictorTransform::predict(u8 predictor, ARGB32 TL, ARGB32 T, A class ColorTransform : public Transform { public: static ErrorOr> read(WebPLoadingContext&, LittleEndianInputBitStream&, IntSize const& image_size); - virtual ErrorOr transform(Bitmap&) override; + virtual ErrorOr> transform(NonnullRefPtr) override; private: ColorTransform(int size_bits, NonnullRefPtr color_bitmap) @@ -1015,8 +1019,10 @@ ErrorOr> ColorTransform::read(WebPLoadingContext& return adopt_nonnull_own_or_enomem(new (nothrow) ColorTransform(size_bits, move(color_bitmap))); } -ErrorOr ColorTransform::transform(Bitmap& bitmap) +ErrorOr> ColorTransform::transform(NonnullRefPtr bitmap_ref) { + Bitmap& bitmap = *bitmap_ref; + for (int y = 0; y < bitmap.height(); ++y) { ARGB32* bitmap_scanline = bitmap.scanline(y); @@ -1028,7 +1034,7 @@ ErrorOr ColorTransform::transform(Bitmap& bitmap) bitmap_scanline[x] = inverse_transform(bitmap_scanline[x], color_scanline[color_x]); } } - return {}; + return bitmap_ref; } ARGB32 ColorTransform::inverse_transform(ARGB32 pixel, ARGB32 transform) @@ -1060,25 +1066,25 @@ ARGB32 ColorTransform::inverse_transform(ARGB32 pixel, ARGB32 transform) // https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification#43_subtract_green_transform class SubtractGreenTransform : public Transform { public: - virtual ErrorOr transform(Bitmap&) override; + virtual ErrorOr> transform(NonnullRefPtr) override; }; -ErrorOr SubtractGreenTransform::transform(Bitmap& bitmap) +ErrorOr> SubtractGreenTransform::transform(NonnullRefPtr bitmap) { - for (ARGB32& pixel : bitmap) { + for (ARGB32& pixel : *bitmap) { Color color = Color::from_argb(pixel); u8 red = (color.red() + color.green()) & 0xff; u8 blue = (color.blue() + color.green()) & 0xff; pixel = Color(red, color.green(), blue, color.alpha()).value(); } - return {}; + return bitmap; } // https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification#44_color_indexing_transform class ColorIndexingTransform : public Transform { public: static ErrorOr> read(WebPLoadingContext&, LittleEndianInputBitStream&); - virtual ErrorOr transform(Bitmap&) override; + virtual ErrorOr> transform(NonnullRefPtr) override; private: explicit ColorIndexingTransform(NonnullRefPtr palette_bitmap) @@ -1113,18 +1119,18 @@ ErrorOr> ColorIndexingTransform::read(WebP return adopt_nonnull_own_or_enomem(new (nothrow) ColorIndexingTransform(move(palette_bitmap))); } -ErrorOr ColorIndexingTransform::transform(Bitmap& bitmap) +ErrorOr> ColorIndexingTransform::transform(NonnullRefPtr bitmap) { // FIXME: If this is the last transform, consider returning an Indexed8 bitmap here? - for (ARGB32& pixel : bitmap) { + for (ARGB32& pixel : *bitmap) { // "The inverse transform for the image is simply replacing the pixel values (which are indices to the color table) // with the actual color table values. The indexing is done based on the green component of the ARGB color. [...] // If the index is equal or larger than color_table_size, the argb color value should be set to 0x00000000 (transparent black)." u8 index = Color::from_argb(pixel).green(); pixel = index < m_palette_bitmap->width() ? m_palette_bitmap->scanline(0)[index] : 0; } - return {}; + return bitmap; } } @@ -1209,7 +1215,7 @@ static ErrorOr decode_webp_chunk_VP8L(WebPLoadingContext& context, Chunk c // Transforms have to be applied in the reverse order they appear in in the file. // (As far as I can tell, this isn't mentioned in the spec.) for (auto const& transform : transforms.in_reverse()) - TRY(transform->transform(*context.bitmap)); + context.bitmap = TRY(transform->transform(context.bitmap.release_nonnull())); return {}; }