| #ifdef RIVE_RENDERER_TESS |
| #include "viewer/tess/bitmap_decoder.hpp" |
| #include <vector> |
| |
| Bitmap::Bitmap(uint32_t width, |
| uint32_t height, |
| PixelFormat pixelFormat, |
| std::unique_ptr<const uint8_t[]> bytes) : |
| m_Width(width), m_Height(height), m_PixelFormat(pixelFormat), m_Bytes(std::move(bytes)) |
| {} |
| |
| Bitmap::Bitmap(uint32_t width, uint32_t height, PixelFormat pixelFormat, const uint8_t* bytes) : |
| Bitmap(width, height, pixelFormat, std::unique_ptr<const uint8_t[]>(bytes)) |
| {} |
| |
| size_t Bitmap::bytesPerPixel(PixelFormat format) const |
| { |
| switch (format) |
| { |
| case PixelFormat::R: |
| return 1; |
| case PixelFormat::RGB: |
| return 3; |
| case PixelFormat::RGBA: |
| return 4; |
| } |
| } |
| |
| size_t Bitmap::byteSize(PixelFormat format) const |
| { |
| return m_Width * m_Height * bytesPerPixel(format); |
| } |
| |
| size_t Bitmap::byteSize() const { return byteSize(m_PixelFormat); } |
| |
| std::unique_ptr<Bitmap> DecodePng(rive::Span<const uint8_t> bytes); |
| std::unique_ptr<Bitmap> DecodeJpeg(rive::Span<const uint8_t> bytes) { return nullptr; } |
| std::unique_ptr<Bitmap> DecodeWebP(rive::Span<const uint8_t> bytes) { return nullptr; } |
| |
| using BitmapDecoder = std::unique_ptr<Bitmap> (*)(rive::Span<const uint8_t> bytes); |
| struct ImageFormat |
| { |
| const char* name; |
| std::vector<const uint8_t> fingerprint; |
| BitmapDecoder decodeImage; |
| }; |
| |
| std::unique_ptr<Bitmap> Bitmap::decode(rive::Span<const uint8_t> bytes) |
| { |
| static ImageFormat decoders[] = { |
| { |
| "png", |
| {0x89, 0x50, 0x4E, 0x47}, |
| DecodePng, |
| }, |
| { |
| "jpeg", |
| {0xFF, 0xD8, 0xFF}, |
| DecodeJpeg, |
| }, |
| { |
| "webp", |
| {0x52, 0x49, 0x46}, |
| DecodeWebP, |
| }, |
| }; |
| |
| for (auto recognizer : decoders) |
| { |
| auto& fingerprint = recognizer.fingerprint; |
| |
| // Immediately discard decoders with fingerprints that are longer than |
| // the file buffer. |
| if (recognizer.fingerprint.size() > bytes.size()) |
| { |
| continue; |
| } |
| |
| // If the fingerprint doesn't match, discrd this decoder. These are all bytes so .size() is |
| // fine here. |
| if (std::memcmp(fingerprint.data(), bytes.data(), fingerprint.size()) != 0) |
| { |
| continue; |
| } |
| |
| auto bitmap = recognizer.decodeImage(bytes); |
| if (!bitmap) |
| { |
| fprintf(stderr, "Bitmap::decode - failed to decode a %s.\n", recognizer.name); |
| } |
| return bitmap; |
| } |
| return nullptr; |
| } |
| |
| void Bitmap::pixelFormat(PixelFormat format) |
| { |
| if (format == m_PixelFormat) |
| { |
| return; |
| } |
| auto nextByteSize = byteSize(format); |
| auto nextBytes = rivestd::make_unique<uint8_t[]>(nextByteSize); |
| |
| auto fromBytesPerPixel = bytesPerPixel(m_PixelFormat); |
| auto toBytesPerPixel = bytesPerPixel(format); |
| int writeIndex = 0; |
| int readIndex = 0; |
| for (int i = 0; i < m_Width * m_Height; i++) |
| { |
| for (int j = 0; j < toBytesPerPixel; j++) |
| { |
| nextBytes[writeIndex++] = j < fromBytesPerPixel ? m_Bytes[readIndex++] : 255; |
| } |
| } |
| |
| m_Bytes = std::move(nextBytes); |
| m_PixelFormat = format; |
| } |
| #endif |