PNGShared.h 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /*
  2. * Copyright (c) 2022, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Array.h>
  8. #include <AK/Error.h>
  9. #include <AK/SIMD.h>
  10. namespace Gfx::PNG {
  11. // https://www.w3.org/TR/PNG/#5PNG-file-signature
  12. static constexpr Array<u8, 8> header = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 };
  13. // https://www.w3.org/TR/PNG/#6Colour-values
  14. enum class ColorType : u8 {
  15. Greyscale = 0,
  16. Truecolor = 2, // RGB
  17. IndexedColor = 3,
  18. GreyscaleWithAlpha = 4,
  19. TruecolorWithAlpha = 6,
  20. };
  21. // https://www.w3.org/TR/PNG/#9Filter-types
  22. enum class FilterType : u8 {
  23. None,
  24. Sub,
  25. Up,
  26. Average,
  27. Paeth,
  28. };
  29. inline ErrorOr<FilterType> filter_type(u8 byte)
  30. {
  31. if (byte <= 4)
  32. return static_cast<FilterType>(byte);
  33. return Error::from_string_literal("PNGImageDecoderPlugin: Invalid PNG filter");
  34. }
  35. // https://www.w3.org/TR/PNG/#9Filter-type-4-Paeth
  36. ALWAYS_INLINE u8 paeth_predictor(u8 a, u8 b, u8 c)
  37. {
  38. int p = a + b - c;
  39. int pa = AK::abs(p - a);
  40. int pb = AK::abs(p - b);
  41. int pc = AK::abs(p - c);
  42. if (pa <= pb && pa <= pc)
  43. return a;
  44. if (pb <= pc)
  45. return b;
  46. return c;
  47. }
  48. ALWAYS_INLINE AK::SIMD::u8x4 paeth_predictor(AK::SIMD::u8x4 a, AK::SIMD::u8x4 b, AK::SIMD::u8x4 c)
  49. {
  50. return AK::SIMD::u8x4 {
  51. paeth_predictor(a[0], b[0], c[0]),
  52. paeth_predictor(a[1], b[1], c[1]),
  53. paeth_predictor(a[2], b[2], c[2]),
  54. paeth_predictor(a[3], b[3], c[3]),
  55. };
  56. }
  57. };