Coverage Report

Created: 2026-05-16 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibGfx/ImageFormats/PAMLoader.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2024, the SerenityOS developers.
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include "PAMLoader.h"
8
#include "PortableImageLoaderCommon.h"
9
10
namespace Gfx {
11
12
ErrorOr<void> read_image_data(PAMLoadingContext& context)
13
760
{
14
760
    VERIFY(context.type == PAMLoadingContext::Type::RAWBITS);
15
16
    // FIXME: Technically it's more to spec to check that a known tupl type has a minimum depth and then skip additional channels.
17
760
    bool is_gray = context.format_details.depth == 1 && context.format_details.tupl_type == "GRAYSCALE"sv;
18
760
    bool is_gray_alpha = context.format_details.depth == 2 && context.format_details.tupl_type == "GRAYSCALE_ALPHA"sv;
19
760
    bool is_rgb = context.format_details.depth == 3 && context.format_details.tupl_type == "RGB"sv;
20
760
    bool is_rgba = context.format_details.depth == 4 && context.format_details.tupl_type == "RGB_ALPHA"sv;
21
22
760
    bool is_cmyk = context.format_details.depth == 4 && context.format_details.tupl_type == "CMYK"sv;
23
24
760
    if (!is_gray && !is_gray_alpha && !is_rgb && !is_rgba && !is_cmyk)
25
191
        return Error::from_string_view("Unsupported PAM depth"sv);
26
27
569
    auto& stream = *context.stream;
28
29
569
    if (is_cmyk) {
30
178
        context.format_details.cmyk_bitmap = TRY(CMYKBitmap::create_with_size({ context.width, context.height }));
31
149
        CMYK* data = context.format_details.cmyk_bitmap.value()->begin();
32
156k
        for (u64 i = 0; i < context.width * context.height; ++i) {
33
156k
            Array<u8, 4> pixel;
34
156k
            TRY(stream.read_until_filled(pixel));
35
156k
            data[i] = { pixel[0], pixel[1], pixel[2], pixel[3] };
36
156k
        }
37
391
    } else {
38
391
        TRY(create_bitmap(context));
39
277k
        for (u64 i = 0; i < context.width * context.height; ++i) {
40
277k
            if (is_gray) {
41
74.9k
                Array<u8, 1> pixel;
42
74.9k
                TRY(stream.read_until_filled(pixel));
43
74.8k
                context.bitmap->set_pixel(i % context.width, i / context.width, { pixel[0], pixel[0], pixel[0] });
44
202k
            } else if (is_gray_alpha) {
45
66.0k
                Array<u8, 2> pixel;
46
66.0k
                TRY(stream.read_until_filled(pixel));
47
65.9k
                context.bitmap->set_pixel(i % context.width, i / context.width, { pixel[0], pixel[0], pixel[0], pixel[1] });
48
136k
            } else if (is_rgb) {
49
70.7k
                Array<u8, 3> pixel;
50
70.7k
                TRY(stream.read_until_filled(pixel));
51
70.6k
                context.bitmap->set_pixel(i % context.width, i / context.width, { pixel[0], pixel[1], pixel[2] });
52
70.6k
            } else if (is_rgba) {
53
65.8k
                Array<u8, 4> pixel;
54
65.8k
                TRY(stream.read_until_filled(pixel));
55
65.7k
                context.bitmap->set_pixel(i % context.width, i / context.width, { pixel[0], pixel[1], pixel[2], pixel[3] });
56
65.7k
            }
57
277k
        }
58
382
    }
59
60
569
    return {};
61
569
}
62
}