mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:28:12 +00:00

Originally I simply thought that passing file paths is quite OK, but as Linus pointed to, it turned out that passing file paths to ensure some files are able to be decoded is awkward because it does not work with images being served over HTTP. Therefore, ideally we should just use the MIME type as an optional argument to ensure that we can always fallback to use that in case sniffing for the correct image type has failed so we can still detect files like with the TGA format, which has no magic bytes.
70 lines
2 KiB
C++
70 lines
2 KiB
C++
/*
|
|
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/ByteBuffer.h>
|
|
#include <AK/OwnPtr.h>
|
|
#include <AK/RefCounted.h>
|
|
#include <AK/RefPtr.h>
|
|
#include <LibGfx/Bitmap.h>
|
|
#include <LibGfx/Size.h>
|
|
|
|
namespace Gfx {
|
|
|
|
class Bitmap;
|
|
|
|
static constexpr size_t maximum_width_for_decoded_images = 16384;
|
|
static constexpr size_t maximum_height_for_decoded_images = 16384;
|
|
|
|
struct ImageFrameDescriptor {
|
|
RefPtr<Bitmap> image;
|
|
int duration { 0 };
|
|
};
|
|
|
|
class ImageDecoderPlugin {
|
|
public:
|
|
virtual ~ImageDecoderPlugin() = default;
|
|
|
|
virtual IntSize size() = 0;
|
|
|
|
virtual void set_volatile() = 0;
|
|
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) = 0;
|
|
|
|
virtual bool sniff() = 0;
|
|
|
|
virtual bool is_animated() = 0;
|
|
virtual size_t loop_count() = 0;
|
|
virtual size_t frame_count() = 0;
|
|
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) = 0;
|
|
|
|
protected:
|
|
ImageDecoderPlugin() = default;
|
|
};
|
|
|
|
class ImageDecoder : public RefCounted<ImageDecoder> {
|
|
public:
|
|
static RefPtr<ImageDecoder> try_create_for_raw_bytes(ReadonlyBytes, Optional<DeprecatedString> mime_type = {});
|
|
~ImageDecoder() = default;
|
|
|
|
IntSize size() const { return m_plugin->size(); }
|
|
int width() const { return size().width(); }
|
|
int height() const { return size().height(); }
|
|
void set_volatile() { m_plugin->set_volatile(); }
|
|
[[nodiscard]] bool set_nonvolatile(bool& was_purged) { return m_plugin->set_nonvolatile(was_purged); }
|
|
bool sniff() const { return m_plugin->sniff(); }
|
|
bool is_animated() const { return m_plugin->is_animated(); }
|
|
size_t loop_count() const { return m_plugin->loop_count(); }
|
|
size_t frame_count() const { return m_plugin->frame_count(); }
|
|
ErrorOr<ImageFrameDescriptor> frame(size_t index) const { return m_plugin->frame(index); }
|
|
|
|
private:
|
|
explicit ImageDecoder(NonnullOwnPtr<ImageDecoderPlugin>);
|
|
|
|
NonnullOwnPtr<ImageDecoderPlugin> mutable m_plugin;
|
|
};
|
|
|
|
}
|