LibGfx: Select largest ICO image before bpp tie-break
When choosing the best image from an ICO file, prefer the entry with the
largest pixel area first, and only use bits-per-pixel as a tie-breaker.
This had regressed in commit b10fe7c136.
This fixes ICO files like Discord's favicon, where 16x16, 32x32, 48x48,
and 256x256 entries all advertise the same bpp. We were previously just
choosing whichever we saw first, which happened to be the 16x16 icon.
This commit is contained in:
parent
d341ed5448
commit
b7c4cd511f
3 changed files with 19 additions and 9 deletions
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/Debug.h>
|
||||
#include <AK/Enumerate.h>
|
||||
#include <AK/MemoryStream.h>
|
||||
#include <AK/Types.h>
|
||||
#include <LibGfx/ImageFormats/BMPLoader.h>
|
||||
|
|
@ -120,19 +121,19 @@ static ErrorOr<ICOImageDescriptor> decode_ico_direntry(Stream& stream, IconType
|
|||
static size_t find_largest_image(ICOLoadingContext const& context)
|
||||
{
|
||||
size_t max_area = 0;
|
||||
size_t index = 0;
|
||||
size_t largest_index = 0;
|
||||
u16 max_bits_per_pixel = 0;
|
||||
for (auto const& desc : context.images) {
|
||||
if (static_cast<size_t>(desc.width) * static_cast<size_t>(desc.height) >= max_area) {
|
||||
if (desc.bits_per_pixel > max_bits_per_pixel) {
|
||||
max_area = desc.width * desc.height;
|
||||
largest_index = index;
|
||||
max_bits_per_pixel = desc.bits_per_pixel;
|
||||
}
|
||||
|
||||
for (auto const& [index, desc] : enumerate(context.images)) {
|
||||
auto area = static_cast<size_t>(desc.width) * static_cast<size_t>(desc.height);
|
||||
|
||||
if (area > max_area || (area == max_area && desc.bits_per_pixel > max_bits_per_pixel)) {
|
||||
max_area = area;
|
||||
largest_index = index;
|
||||
max_bits_per_pixel = desc.bits_per_pixel;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
|
||||
return largest_index;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -121,6 +121,15 @@ TEST_CASE(test_ico_malformed_frame)
|
|||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_ico_selects_largest_image_with_same_bpp)
|
||||
{
|
||||
auto input = TEST_INPUT("ico/multiple-sizes-with-same-bpp.ico"sv);
|
||||
auto file = TRY_OR_FAIL(Core::MappedFile::map(input));
|
||||
|
||||
auto plugin_decoder = TRY_OR_FAIL(Gfx::ICOImageDecoderPlugin::create(file->bytes()));
|
||||
EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(256, 256));
|
||||
}
|
||||
|
||||
TEST_CASE(test_cur)
|
||||
{
|
||||
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("cur/cursor.cur"sv)));
|
||||
|
|
|
|||
BIN
Tests/LibGfx/test-inputs/ico/multiple-sizes-with-same-bpp.ico
Normal file
BIN
Tests/LibGfx/test-inputs/ico/multiple-sizes-with-same-bpp.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 932 B |
Loading…
Reference in a new issue