PAMLoader.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. /*
  2. * Copyright (c) 2024, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "PAMLoader.h"
  7. #include "PortableImageLoaderCommon.h"
  8. namespace Gfx {
  9. ErrorOr<void> read_image_data(PAMLoadingContext& context)
  10. {
  11. VERIFY(context.type == PAMLoadingContext::Type::RAWBITS);
  12. // FIXME: Technically it's more to spec to check that a known tupl type has a minimum depth and then skip additional channels.
  13. bool is_gray = context.format_details.depth == 1 && context.format_details.tupl_type == "GRAYSCALE"sv;
  14. bool is_gray_alpha = context.format_details.depth == 2 && context.format_details.tupl_type == "GRAYSCALE_ALPHA"sv;
  15. bool is_rgb = context.format_details.depth == 3 && context.format_details.tupl_type == "RGB"sv;
  16. bool is_rgba = context.format_details.depth == 4 && context.format_details.tupl_type == "RGB_ALPHA"sv;
  17. bool is_cmyk = context.format_details.depth == 4 && context.format_details.tupl_type == "CMYK"sv;
  18. if (!is_gray && !is_gray_alpha && !is_rgb && !is_rgba && !is_cmyk)
  19. return Error::from_string_view("Unsupported PAM depth"sv);
  20. auto& stream = *context.stream;
  21. if (is_cmyk) {
  22. context.format_details.cmyk_bitmap = TRY(CMYKBitmap::create_with_size({ context.width, context.height }));
  23. CMYK* data = context.format_details.cmyk_bitmap.value()->begin();
  24. for (u64 i = 0; i < context.width * context.height; ++i) {
  25. Array<u8, 4> pixel;
  26. TRY(stream.read_until_filled(pixel));
  27. data[i] = { pixel[0], pixel[1], pixel[2], pixel[3] };
  28. }
  29. } else {
  30. TRY(create_bitmap(context));
  31. for (u64 i = 0; i < context.width * context.height; ++i) {
  32. if (is_gray) {
  33. Array<u8, 1> pixel;
  34. TRY(stream.read_until_filled(pixel));
  35. context.bitmap->set_pixel(i % context.width, i / context.width, { pixel[0], pixel[0], pixel[0] });
  36. } else if (is_gray_alpha) {
  37. Array<u8, 2> pixel;
  38. TRY(stream.read_until_filled(pixel));
  39. context.bitmap->set_pixel(i % context.width, i / context.width, { pixel[0], pixel[0], pixel[0], pixel[1] });
  40. } else if (is_rgb) {
  41. Array<u8, 3> pixel;
  42. TRY(stream.read_until_filled(pixel));
  43. context.bitmap->set_pixel(i % context.width, i / context.width, { pixel[0], pixel[1], pixel[2] });
  44. } else if (is_rgba) {
  45. Array<u8, 4> pixel;
  46. TRY(stream.read_until_filled(pixel));
  47. context.bitmap->set_pixel(i % context.width, i / context.width, { pixel[0], pixel[1], pixel[2], pixel[3] });
  48. }
  49. }
  50. }
  51. return {};
  52. }
  53. }