mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 21:27:45 +00:00
LibGfx: Use common class template for PBM/PGM/PPM image loaders
PBM, PGM, and PPM image loaders are mostly common. The only difference is how the data is read and the associated magic numbers. The magic numbers are already made common using the loading contexts. Now make the implementations common via a class template which accepts the context to disambiguate.
This commit is contained in:
parent
786b02730c
commit
6a23dfbc92
7 changed files with 123 additions and 327 deletions
|
@ -13,7 +13,7 @@
|
|||
|
||||
namespace Gfx {
|
||||
|
||||
static bool read_image_data(PBMLoadingContext& context, Streamer& streamer)
|
||||
bool read_image_data(PBMLoadingContext& context, Streamer& streamer)
|
||||
{
|
||||
u8 byte;
|
||||
Vector<Gfx::Color> color_data;
|
||||
|
@ -64,91 +64,4 @@ static bool read_image_data(PBMLoadingContext& context, Streamer& streamer)
|
|||
context.state = PBMLoadingContext::State::Bitmap;
|
||||
return true;
|
||||
}
|
||||
|
||||
PBMImageDecoderPlugin::PBMImageDecoderPlugin(const u8* data, size_t size)
|
||||
{
|
||||
m_context = make<PBMLoadingContext>();
|
||||
m_context->data = data;
|
||||
m_context->data_size = size;
|
||||
}
|
||||
|
||||
PBMImageDecoderPlugin::~PBMImageDecoderPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
IntSize PBMImageDecoderPlugin::size()
|
||||
{
|
||||
if (m_context->state == PBMLoadingContext::State::Error)
|
||||
return {};
|
||||
|
||||
if (m_context->state < PBMLoadingContext::State::Decoded) {
|
||||
bool success = decode(*m_context);
|
||||
if (!success)
|
||||
return {};
|
||||
}
|
||||
|
||||
return { m_context->width, m_context->height };
|
||||
}
|
||||
|
||||
void PBMImageDecoderPlugin::set_volatile()
|
||||
{
|
||||
if (m_context->bitmap)
|
||||
m_context->bitmap->set_volatile();
|
||||
}
|
||||
|
||||
bool PBMImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->bitmap)
|
||||
return false;
|
||||
|
||||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool PBMImageDecoderPlugin::sniff()
|
||||
{
|
||||
if (m_context->data_size < 2)
|
||||
return false;
|
||||
|
||||
if (m_context->data[0] == 'P' && m_context->data[1] == '1')
|
||||
return true;
|
||||
|
||||
if (m_context->data[0] == 'P' && m_context->data[1] == '4')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PBMImageDecoderPlugin::is_animated()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t PBMImageDecoderPlugin::loop_count()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t PBMImageDecoderPlugin::frame_count()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ErrorOr<ImageFrameDescriptor> PBMImageDecoderPlugin::frame(size_t index)
|
||||
{
|
||||
if (index > 0)
|
||||
return Error::from_string_literal("PBMImageDecoderPlugin: Invalid frame index"sv);
|
||||
|
||||
if (m_context->state == PBMLoadingContext::State::Error)
|
||||
return Error::from_string_literal("PBMImageDecoderPlugin: Decoding failed"sv);
|
||||
|
||||
if (m_context->state < PBMLoadingContext::State::Decoded) {
|
||||
bool success = decode(*m_context);
|
||||
if (!success)
|
||||
return Error::from_string_literal("PBMImageDecoderPlugin: Decoding failed"sv);
|
||||
}
|
||||
|
||||
VERIFY(m_context->bitmap);
|
||||
return ImageFrameDescriptor { m_context->bitmap, 0 };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,26 +20,7 @@ struct PBM {
|
|||
};
|
||||
|
||||
using PBMLoadingContext = PortableImageMapLoadingContext<PBM>;
|
||||
using PBMImageDecoderPlugin = PortableImageDecoderPlugin<PBMLoadingContext>;
|
||||
|
||||
class PBMImageDecoderPlugin final : public ImageDecoderPlugin {
|
||||
public:
|
||||
PBMImageDecoderPlugin(const u8*, size_t);
|
||||
virtual ~PBMImageDecoderPlugin() override;
|
||||
|
||||
virtual IntSize size() override;
|
||||
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
|
||||
virtual bool sniff() override;
|
||||
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
virtual size_t frame_count() override;
|
||||
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
|
||||
|
||||
private:
|
||||
OwnPtr<PBMLoadingContext> m_context;
|
||||
};
|
||||
|
||||
bool read_image_data(PBMLoadingContext& context, Streamer& streamer);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ static void set_adjusted_pixels(PGMLoadingContext& context, const Vector<Gfx::Co
|
|||
}
|
||||
}
|
||||
|
||||
static bool read_image_data(PGMLoadingContext& context, Streamer& streamer)
|
||||
bool read_image_data(PGMLoadingContext& context, Streamer& streamer)
|
||||
{
|
||||
Vector<Gfx::Color> color_data;
|
||||
|
||||
|
@ -65,91 +65,4 @@ static bool read_image_data(PGMLoadingContext& context, Streamer& streamer)
|
|||
context.state = PGMLoadingContext::State::Bitmap;
|
||||
return true;
|
||||
}
|
||||
|
||||
PGMImageDecoderPlugin::PGMImageDecoderPlugin(const u8* data, size_t size)
|
||||
{
|
||||
m_context = make<PGMLoadingContext>();
|
||||
m_context->data = data;
|
||||
m_context->data_size = size;
|
||||
}
|
||||
|
||||
PGMImageDecoderPlugin::~PGMImageDecoderPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
IntSize PGMImageDecoderPlugin::size()
|
||||
{
|
||||
if (m_context->state == PGMLoadingContext::State::Error)
|
||||
return {};
|
||||
|
||||
if (m_context->state < PGMLoadingContext::State::Decoded) {
|
||||
bool success = decode(*m_context);
|
||||
if (!success)
|
||||
return {};
|
||||
}
|
||||
|
||||
return { m_context->width, m_context->height };
|
||||
}
|
||||
|
||||
void PGMImageDecoderPlugin::set_volatile()
|
||||
{
|
||||
if (m_context->bitmap)
|
||||
m_context->bitmap->set_volatile();
|
||||
}
|
||||
|
||||
bool PGMImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->bitmap)
|
||||
return false;
|
||||
|
||||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool PGMImageDecoderPlugin::sniff()
|
||||
{
|
||||
if (m_context->data_size < 2)
|
||||
return false;
|
||||
|
||||
if (m_context->data[0] == 'P' && m_context->data[1] == '2')
|
||||
return true;
|
||||
|
||||
if (m_context->data[0] == 'P' && m_context->data[1] == '5')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PGMImageDecoderPlugin::is_animated()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t PGMImageDecoderPlugin::loop_count()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t PGMImageDecoderPlugin::frame_count()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ErrorOr<ImageFrameDescriptor> PGMImageDecoderPlugin::frame(size_t index)
|
||||
{
|
||||
if (index > 0)
|
||||
return Error::from_string_literal("PGMImageDecoderPlugin: Invalid frame index"sv);
|
||||
|
||||
if (m_context->state == PGMLoadingContext::State::Error)
|
||||
return Error::from_string_literal("PGMImageDecoderPlugin: Decoding failed"sv);
|
||||
|
||||
if (m_context->state < PGMLoadingContext::State::Decoded) {
|
||||
bool success = decode(*m_context);
|
||||
if (!success)
|
||||
return Error::from_string_literal("PGMImageDecoderPlugin: Decoding failed"sv);
|
||||
}
|
||||
|
||||
VERIFY(m_context->bitmap);
|
||||
return ImageFrameDescriptor { m_context->bitmap, 0 };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,26 +21,7 @@ struct PGM {
|
|||
};
|
||||
|
||||
using PGMLoadingContext = PortableImageMapLoadingContext<PGM>;
|
||||
using PGMImageDecoderPlugin = PortableImageDecoderPlugin<PGMLoadingContext>;
|
||||
|
||||
class PGMImageDecoderPlugin final : public ImageDecoderPlugin {
|
||||
public:
|
||||
PGMImageDecoderPlugin(const u8*, size_t);
|
||||
virtual ~PGMImageDecoderPlugin() override;
|
||||
|
||||
virtual IntSize size() override;
|
||||
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
|
||||
virtual bool sniff() override;
|
||||
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
virtual size_t frame_count() override;
|
||||
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
|
||||
|
||||
private:
|
||||
OwnPtr<PGMLoadingContext> m_context;
|
||||
};
|
||||
|
||||
bool read_image_data(PGMLoadingContext& context, Streamer& streamer);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
namespace Gfx {
|
||||
|
||||
static bool read_image_data(PPMLoadingContext& context, Streamer& streamer)
|
||||
bool read_image_data(PPMLoadingContext& context, Streamer& streamer)
|
||||
{
|
||||
Vector<Gfx::Color> color_data;
|
||||
color_data.ensure_capacity(context.width * context.height);
|
||||
|
@ -69,91 +69,4 @@ static bool read_image_data(PPMLoadingContext& context, Streamer& streamer)
|
|||
context.state = PPMLoadingContext::State::Bitmap;
|
||||
return true;
|
||||
}
|
||||
|
||||
PPMImageDecoderPlugin::PPMImageDecoderPlugin(const u8* data, size_t size)
|
||||
{
|
||||
m_context = make<PPMLoadingContext>();
|
||||
m_context->data = data;
|
||||
m_context->data_size = size;
|
||||
}
|
||||
|
||||
PPMImageDecoderPlugin::~PPMImageDecoderPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
IntSize PPMImageDecoderPlugin::size()
|
||||
{
|
||||
if (m_context->state == PPMLoadingContext::State::Error)
|
||||
return {};
|
||||
|
||||
if (m_context->state < PPMLoadingContext::State::Decoded) {
|
||||
bool success = decode(*m_context);
|
||||
if (!success)
|
||||
return {};
|
||||
}
|
||||
|
||||
return { m_context->width, m_context->height };
|
||||
}
|
||||
|
||||
void PPMImageDecoderPlugin::set_volatile()
|
||||
{
|
||||
if (m_context->bitmap)
|
||||
m_context->bitmap->set_volatile();
|
||||
}
|
||||
|
||||
bool PPMImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->bitmap)
|
||||
return false;
|
||||
|
||||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool PPMImageDecoderPlugin::sniff()
|
||||
{
|
||||
if (m_context->data_size < 2)
|
||||
return false;
|
||||
|
||||
if (m_context->data[0] == 'P' && m_context->data[1] == '3')
|
||||
return true;
|
||||
|
||||
if (m_context->data[0] == 'P' && m_context->data[1] == '6')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PPMImageDecoderPlugin::is_animated()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t PPMImageDecoderPlugin::loop_count()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t PPMImageDecoderPlugin::frame_count()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ErrorOr<ImageFrameDescriptor> PPMImageDecoderPlugin::frame(size_t index)
|
||||
{
|
||||
if (index > 0)
|
||||
return Error::from_string_literal("PPMImageDecoderPlugin: Invalid frame index"sv);
|
||||
|
||||
if (m_context->state == PPMLoadingContext::State::Error)
|
||||
return Error::from_string_literal("PGMImageDecoderPlugin: Decoding failed"sv);
|
||||
|
||||
if (m_context->state < PPMLoadingContext::State::Decoded) {
|
||||
bool success = decode(*m_context);
|
||||
if (!success)
|
||||
return Error::from_string_literal("PGMImageDecoderPlugin: Decoding failed"sv);
|
||||
}
|
||||
|
||||
VERIFY(m_context->bitmap);
|
||||
return ImageFrameDescriptor { m_context->bitmap, 0 };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,26 +21,7 @@ struct PPM {
|
|||
};
|
||||
|
||||
using PPMLoadingContext = PortableImageMapLoadingContext<PPM>;
|
||||
using PPMImageDecoderPlugin = PortableImageDecoderPlugin<PPMLoadingContext>;
|
||||
|
||||
class PPMImageDecoderPlugin final : public ImageDecoderPlugin {
|
||||
public:
|
||||
PPMImageDecoderPlugin(const u8*, size_t);
|
||||
virtual ~PPMImageDecoderPlugin() override;
|
||||
|
||||
virtual IntSize size() override;
|
||||
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
|
||||
virtual bool sniff() override;
|
||||
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
virtual size_t frame_count() override;
|
||||
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
|
||||
|
||||
private:
|
||||
OwnPtr<PPMLoadingContext> m_context;
|
||||
};
|
||||
|
||||
bool read_image_data(PPMLoadingContext& context, Streamer& streamer);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <AK/StringView.h>
|
||||
#include <AK/Types.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/PortableImageLoaderCommon.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
|
@ -45,4 +46,117 @@ struct PortableImageMapLoadingContext {
|
|||
RefPtr<Gfx::Bitmap> bitmap;
|
||||
};
|
||||
|
||||
template<typename TContext>
|
||||
class PortableImageDecoderPlugin final : public ImageDecoderPlugin {
|
||||
public:
|
||||
PortableImageDecoderPlugin(const u8*, size_t);
|
||||
virtual ~PortableImageDecoderPlugin() override = default;
|
||||
|
||||
virtual IntSize size() override;
|
||||
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
|
||||
virtual bool sniff() override;
|
||||
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
virtual size_t frame_count() override;
|
||||
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
|
||||
|
||||
private:
|
||||
OwnPtr<TContext> m_context;
|
||||
};
|
||||
|
||||
template<typename TContext>
|
||||
PortableImageDecoderPlugin<TContext>::PortableImageDecoderPlugin(const u8* data, size_t size)
|
||||
{
|
||||
m_context = make<TContext>();
|
||||
m_context->data = data;
|
||||
m_context->data_size = size;
|
||||
}
|
||||
|
||||
template<typename TContext>
|
||||
IntSize PortableImageDecoderPlugin<TContext>::size()
|
||||
{
|
||||
if (m_context->state == TContext::State::Error)
|
||||
return {};
|
||||
|
||||
if (m_context->state < TContext::State::Decoded) {
|
||||
bool success = decode(*m_context);
|
||||
if (!success)
|
||||
return {};
|
||||
}
|
||||
|
||||
return { m_context->width, m_context->height };
|
||||
}
|
||||
|
||||
template<typename TContext>
|
||||
void PortableImageDecoderPlugin<TContext>::set_volatile()
|
||||
{
|
||||
if (m_context->bitmap)
|
||||
m_context->bitmap->set_volatile();
|
||||
}
|
||||
|
||||
template<typename TContext>
|
||||
bool PortableImageDecoderPlugin<TContext>::set_nonvolatile(bool& was_purged)
|
||||
{
|
||||
if (!m_context->bitmap)
|
||||
return false;
|
||||
|
||||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
template<typename TContext>
|
||||
bool PortableImageDecoderPlugin<TContext>::sniff()
|
||||
{
|
||||
using Context = TContext;
|
||||
if (m_context->data_size < 2)
|
||||
return false;
|
||||
|
||||
if (m_context->data[0] == 'P' && m_context->data[1] == Context::FormatDetails::ascii_magic_number)
|
||||
return true;
|
||||
|
||||
if (m_context->data[0] == 'P' && m_context->data[1] == Context::FormatDetails::binary_magic_number)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename TContext>
|
||||
bool PortableImageDecoderPlugin<TContext>::is_animated()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename TContext>
|
||||
size_t PortableImageDecoderPlugin<TContext>::loop_count()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename TContext>
|
||||
size_t PortableImageDecoderPlugin<TContext>::frame_count()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename TContext>
|
||||
ErrorOr<ImageFrameDescriptor> PortableImageDecoderPlugin<TContext>::frame(size_t index)
|
||||
{
|
||||
if (index > 0)
|
||||
return Error::from_string_literal("PortableImageDecoderPlugin: Invalid frame index"sv);
|
||||
|
||||
if (m_context->state == TContext::State::Error)
|
||||
return Error::from_string_literal("PortableImageDecoderPlugin: Decoding failed"sv);
|
||||
|
||||
if (m_context->state < TContext::State::Decoded) {
|
||||
bool success = decode(*m_context);
|
||||
if (!success)
|
||||
return Error::from_string_literal("PortableImageDecoderPlugin: Decoding failed"sv);
|
||||
}
|
||||
|
||||
VERIFY(m_context->bitmap);
|
||||
return ImageFrameDescriptor { m_context->bitmap, 0 };
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue