mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 07:17:35 +00:00
LibGfx: Add a .pam loader
.pam is a "portrable arbitrarymap" as documented at https://netpbm.sourceforge.net/doc/pam.html It's very similar to .pbm, .pgm, and .ppm, so this uses the PortableImageMapLoader framework. The header is slightly different, so this has a custom header parsing function. Also, .pam only exixts in binary form, so the ascii form support becomes optional.
This commit is contained in:
parent
0d76a9da17
commit
187862ebe0
9 changed files with 173 additions and 9 deletions
52
Userland/Libraries/LibGfx/ImageFormats/PAMLoader.cpp
Normal file
52
Userland/Libraries/LibGfx/ImageFormats/PAMLoader.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2024, the SerenityOS developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "PAMLoader.h"
|
||||
#include "PortableImageLoaderCommon.h"
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
ErrorOr<void> read_image_data(PAMLoadingContext& context)
|
||||
{
|
||||
VERIFY(context.type == PAMLoadingContext::Type::RAWBITS);
|
||||
|
||||
// FIXME: Technically it's more to spec to check that a known tupl type has a minimum depth and then skip additional channels.
|
||||
bool is_gray = context.format_details.depth == 1 && context.format_details.tupl_type == "GRAYSCALE"sv;
|
||||
bool is_gray_alpha = context.format_details.depth == 2 && context.format_details.tupl_type == "GRAYSCALE_ALPHA"sv;
|
||||
bool is_rgb = context.format_details.depth == 3 && context.format_details.tupl_type == "RGB"sv;
|
||||
bool is_rgba = context.format_details.depth == 4 && context.format_details.tupl_type == "RGB_ALPHA"sv;
|
||||
|
||||
if (!is_gray && !is_gray_alpha && !is_rgb && !is_rgba)
|
||||
return Error::from_string_view("Unsupported PAM depth"sv);
|
||||
|
||||
TRY(create_bitmap(context));
|
||||
|
||||
auto& stream = *context.stream;
|
||||
|
||||
for (u64 i = 0; i < context.width * context.height; ++i) {
|
||||
if (is_gray) {
|
||||
Array<u8, 1> pixel;
|
||||
TRY(stream.read_until_filled(pixel));
|
||||
context.bitmap->set_pixel(i % context.width, i / context.width, { pixel[0], pixel[0], pixel[0] });
|
||||
} else if (is_gray_alpha) {
|
||||
Array<u8, 2> pixel;
|
||||
TRY(stream.read_until_filled(pixel));
|
||||
context.bitmap->set_pixel(i % context.width, i / context.width, { pixel[0], pixel[0], pixel[0], pixel[1] });
|
||||
} else if (is_rgb) {
|
||||
Array<u8, 3> pixel;
|
||||
TRY(stream.read_until_filled(pixel));
|
||||
context.bitmap->set_pixel(i % context.width, i / context.width, { pixel[0], pixel[1], pixel[2] });
|
||||
} else if (is_rgba) {
|
||||
Array<u8, 4> pixel;
|
||||
TRY(stream.read_until_filled(pixel));
|
||||
context.bitmap->set_pixel(i % context.width, i / context.width, { pixel[0], pixel[1], pixel[2], pixel[3] });
|
||||
}
|
||||
}
|
||||
|
||||
context.state = PAMLoadingContext::State::BitmapDecoded;
|
||||
return {};
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue