mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +00:00
LibGfx/GIF: Write the netscape extension block
This allows us to encode the required number of loops in the file.
This commit is contained in:
parent
ebb3d8025c
commit
bee8dd76ee
Notes:
sideshowbarker
2024-07-17 05:13:53 +09:00
Author: https://github.com/LucasChollet Commit: https://github.com/SerenityOS/serenity/commit/bee8dd76ee Pull-request: https://github.com/SerenityOS/serenity/pull/24412 Reviewed-by: https://github.com/nico ✅ Reviewed-by: https://github.com/trflynn89
3 changed files with 37 additions and 3 deletions
|
@ -167,6 +167,36 @@ ErrorOr<void> GIFAnimationWriter::add_frame(Bitmap& bitmap, int duration_ms, Int
|
|||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> write_netscape_extension(BigEndianOutputBitStream& stream, u16 loop_count)
|
||||
{
|
||||
// This is a vendor extension, its sole usage is to provide the loop count.
|
||||
// I used this link as a source: https://web.archive.org/web/19990418091037/http://www6.uniovi.es/gifanim/gifabout.htm
|
||||
|
||||
// Extension Introducer
|
||||
TRY(stream.write_value<u8>(0x21));
|
||||
// Application Extension Label
|
||||
TRY(stream.write_value<u8>(0xFF));
|
||||
|
||||
// Block Size
|
||||
constexpr auto netscape_signature = "NETSCAPE2.0"sv;
|
||||
TRY(stream.write_value<u8>(netscape_signature.length()));
|
||||
TRY(stream.write_until_depleted(netscape_signature));
|
||||
|
||||
// Length of Data Sub-Block
|
||||
TRY(stream.write_value<u8>(3));
|
||||
|
||||
// Undocumented
|
||||
TRY(stream.write_value<u8>(1));
|
||||
|
||||
// Number of loops, 0 means infinite
|
||||
TRY(stream.write_value<u16>(loop_count));
|
||||
|
||||
// Block Terminator
|
||||
TRY(stream.write_value<u8>(0));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ErrorOr<void> GIFWriter::encode(Stream& stream, Bitmap const& bitmap)
|
||||
|
@ -187,12 +217,16 @@ ErrorOr<void> GIFWriter::encode(Stream& stream, Bitmap const& bitmap)
|
|||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<NonnullOwnPtr<AnimationWriter>> GIFWriter::start_encoding_animation(SeekableStream& stream, IntSize dimensions)
|
||||
ErrorOr<NonnullOwnPtr<AnimationWriter>> GIFWriter::start_encoding_animation(SeekableStream& stream, IntSize dimensions, u16 loop_count)
|
||||
{
|
||||
TRY(write_header(stream));
|
||||
|
||||
BigEndianOutputBitStream bit_stream { MaybeOwned<Stream> { stream } };
|
||||
TRY(write_logical_descriptor(bit_stream, dimensions));
|
||||
|
||||
// Vendor extension to support looping
|
||||
TRY(write_netscape_extension(bit_stream, loop_count));
|
||||
|
||||
return make<GIFAnimationWriter>(stream);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Gfx {
|
|||
class GIFWriter {
|
||||
public:
|
||||
static ErrorOr<void> encode(Stream&, Bitmap const&);
|
||||
static ErrorOr<NonnullOwnPtr<AnimationWriter>> start_encoding_animation(SeekableStream&, IntSize dimensions);
|
||||
static ErrorOr<NonnullOwnPtr<AnimationWriter>> start_encoding_animation(SeekableStream&, IntSize dimensions, u16 loop_count);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
if (options.out_path.ends_with(".webp"sv))
|
||||
return Gfx::WebPWriter::start_encoding_animation(*output_stream, decoder->size(), decoder->loop_count());
|
||||
if (options.out_path.ends_with(".gif"sv))
|
||||
return Gfx::GIFWriter::start_encoding_animation(*output_stream, decoder->size());
|
||||
return Gfx::GIFWriter::start_encoding_animation(*output_stream, decoder->size(), decoder->loop_count());
|
||||
return Error::from_string_literal("Unable to find a encoder for the requested extension.");
|
||||
}());
|
||||
|
||||
|
|
Loading…
Reference in a new issue