
When trying to figure out the correct implementation, we now have a very strong distinction on plugins that are well suited for sniffing, and plugins that need a MIME type to be chosen. Instead of having multiple calls to non-static virtual sniff methods for each Image decoding plugin, we have 2 static methods for each implementation: 1. The sniff method, which in contrast to the old method, gets a ReadonlyBytes parameter and ensures we can figure out the result with zero heap allocations for most implementations. 2. The create method, which just creates a new instance so we don't expose the constructor to everyone anymore. In addition to that, we have a new virtual method called initialize, which has a per-implementation initialization pattern to actually ensure each implementation can construct a decoder object, and then have a correct context being applied to it for the actual decoding.
66 lines
1.7 KiB
C++
66 lines
1.7 KiB
C++
/*
|
|
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Forward.h>
|
|
#include <LibGfx/Forward.h>
|
|
#include <LibGfx/ImageDecoder.h>
|
|
|
|
namespace Gfx {
|
|
|
|
// Decoder for the "Quite OK Image" format (v1.0).
|
|
// https://qoiformat.org/qoi-specification.pdf
|
|
|
|
struct [[gnu::packed]] QOIHeader {
|
|
char magic[4];
|
|
u32 width;
|
|
u32 height;
|
|
u8 channels;
|
|
u8 colorspace;
|
|
};
|
|
|
|
struct QOILoadingContext {
|
|
enum class State {
|
|
NotDecoded = 0,
|
|
HeaderDecoded,
|
|
ImageDecoded,
|
|
Error,
|
|
};
|
|
State state { State::NotDecoded };
|
|
u8 const* data { nullptr };
|
|
size_t data_size { 0 };
|
|
QOIHeader header {};
|
|
RefPtr<Bitmap> bitmap;
|
|
Optional<Error> error;
|
|
};
|
|
|
|
class QOIImageDecoderPlugin final : public ImageDecoderPlugin {
|
|
public:
|
|
static ErrorOr<bool> sniff(ReadonlyBytes);
|
|
static ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> create(ReadonlyBytes);
|
|
|
|
virtual ~QOIImageDecoderPlugin() override = default;
|
|
|
|
virtual IntSize size() override;
|
|
virtual void set_volatile() override;
|
|
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
|
virtual bool initialize() override;
|
|
virtual bool is_animated() override { return false; }
|
|
virtual size_t loop_count() override { return 0; }
|
|
virtual size_t frame_count() override { return 1; }
|
|
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
|
|
|
|
private:
|
|
ErrorOr<void> decode_header_and_update_context(InputMemoryStream&);
|
|
ErrorOr<void> decode_image_and_update_context(InputMemoryStream&);
|
|
|
|
QOIImageDecoderPlugin(u8 const*, size_t);
|
|
|
|
OwnPtr<QOILoadingContext> m_context;
|
|
};
|
|
|
|
}
|