/src/serenity/Userland/Libraries/LibGfx/ImageFormats/PNGShared.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2022, the SerenityOS developers. |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #pragma once |
8 | | |
9 | | #include <AK/Array.h> |
10 | | #include <AK/Error.h> |
11 | | #include <AK/SIMD.h> |
12 | | #include <AK/SIMDMath.h> |
13 | | |
14 | | namespace Gfx::PNG { |
15 | | |
16 | | // https://www.w3.org/TR/PNG/#5PNG-file-signature |
17 | | static constexpr Array<u8, 8> header = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 }; |
18 | | |
19 | | // https://www.w3.org/TR/PNG/#6Colour-values |
20 | | enum class ColorType : u8 { |
21 | | Greyscale = 0, |
22 | | Truecolor = 2, // RGB |
23 | | IndexedColor = 3, |
24 | | GreyscaleWithAlpha = 4, |
25 | | TruecolorWithAlpha = 6, |
26 | | }; |
27 | | |
28 | | // https://www.w3.org/TR/PNG/#9Filter-types |
29 | | enum class FilterType : u8 { |
30 | | None, |
31 | | Sub, |
32 | | Up, |
33 | | Average, |
34 | | Paeth, |
35 | | }; |
36 | | |
37 | | inline ErrorOr<FilterType> filter_type(u8 byte) |
38 | 5.03M | { |
39 | 5.03M | if (byte <= 4) |
40 | 5.03M | return static_cast<FilterType>(byte); |
41 | 0 | return Error::from_string_literal("PNGImageDecoderPlugin: Invalid PNG filter"); |
42 | 5.03M | } |
43 | | |
44 | | // https://www.w3.org/TR/PNG/#9Filter-type-4-Paeth |
45 | | ALWAYS_INLINE u8 paeth_predictor(u8 a, u8 b, u8 c) |
46 | 3.67M | { |
47 | 3.67M | int p = a + b - c; |
48 | 3.67M | int pa = AK::abs(p - a); |
49 | 3.67M | int pb = AK::abs(p - b); |
50 | 3.67M | int pc = AK::abs(p - c); |
51 | 3.67M | if (pa <= pb && pa <= pc) |
52 | 3.07M | return a; |
53 | 602k | if (pb <= pc) |
54 | 567k | return b; |
55 | 35.2k | return c; |
56 | 602k | } |
57 | | |
58 | | ALWAYS_INLINE AK::SIMD::u8x4 paeth_predictor(AK::SIMD::u8x4 a, AK::SIMD::u8x4 b, AK::SIMD::u8x4 c) |
59 | 0 | { |
60 | 0 | using namespace AK::SIMD; |
61 | 0 | auto a16 = simd_cast<i16x4>(a); |
62 | 0 | auto b16 = simd_cast<i16x4>(b); |
63 | 0 | auto c16 = simd_cast<i16x4>(c); |
64 | 0 |
|
65 | 0 | auto p16 = a16 + b16 - c16; |
66 | 0 | auto pa16 = abs(p16 - a16); |
67 | 0 | auto pb16 = abs(p16 - b16); |
68 | 0 | auto pc16 = abs(p16 - c16); |
69 | 0 |
|
70 | 0 | auto mask_a = simd_cast<u8x4>((pa16 <= pb16) & (pa16 <= pc16)); |
71 | 0 | auto mask_b = ~mask_a & simd_cast<u8x4>(pb16 <= pc16); |
72 | 0 | auto mask_c = ~(mask_a | mask_b); |
73 | 0 |
|
74 | 0 | return (a & mask_a) | (b & mask_b) | (c & mask_c); |
75 | 0 | } |
76 | | |
77 | | }; |