forked from Green-Sky/tomato
full on qoi
This commit is contained in:
parent
f4fe94dfe6
commit
db54afd180
@ -25,6 +25,8 @@ add_executable(tomato
|
|||||||
./image_loader_stb.cpp
|
./image_loader_stb.cpp
|
||||||
./image_loader_webp.hpp
|
./image_loader_webp.hpp
|
||||||
./image_loader_webp.cpp
|
./image_loader_webp.cpp
|
||||||
|
./image_loader_qoi.hpp
|
||||||
|
./image_loader_qoi.cpp
|
||||||
|
|
||||||
./texture_uploader.hpp
|
./texture_uploader.hpp
|
||||||
./sdlrenderer_texture_uploader.hpp
|
./sdlrenderer_texture_uploader.hpp
|
||||||
@ -90,5 +92,6 @@ target_link_libraries(tomato PUBLIC
|
|||||||
stb_image_write
|
stb_image_write
|
||||||
webpdemux
|
webpdemux
|
||||||
libwebpmux # the f why (needed for anim encode)
|
libwebpmux # the f why (needed for anim encode)
|
||||||
|
qoi
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -613,6 +613,7 @@ float ChatGui4::render(float time_delta) {
|
|||||||
"image/gif",
|
"image/gif",
|
||||||
"image/jpeg",
|
"image/jpeg",
|
||||||
"image/bmp",
|
"image/bmp",
|
||||||
|
"image/qoi",
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const char* mime_type : image_mime_types) {
|
for (const char* mime_type : image_mime_types) {
|
||||||
|
91
src/image_loader_qoi.cpp
Normal file
91
src/image_loader_qoi.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include "./image_loader_qoi.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <qoi/qoi.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
ImageLoaderQOI::ImageInfo ImageLoaderQOI::loadInfoFromMemory(const uint8_t* data, uint64_t data_size) {
|
||||||
|
ImageInfo res;
|
||||||
|
|
||||||
|
qoi_desc desc;
|
||||||
|
// TODO: only read the header
|
||||||
|
auto* ret = qoi_decode(data, data_size, &desc, 4);
|
||||||
|
if (ret == nullptr) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
free(ret);
|
||||||
|
|
||||||
|
res.width = desc.width;
|
||||||
|
res.height = desc.height;
|
||||||
|
//desc.colorspace;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageLoaderQOI::ImageResult ImageLoaderQOI::loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) {
|
||||||
|
ImageResult res;
|
||||||
|
|
||||||
|
qoi_desc desc;
|
||||||
|
|
||||||
|
uint8_t* img_data = static_cast<uint8_t*>(
|
||||||
|
qoi_decode(data, data_size, &desc, 4)
|
||||||
|
);
|
||||||
|
if (img_data == nullptr) {
|
||||||
|
// not readable
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.width = desc.width;
|
||||||
|
res.height = desc.height;
|
||||||
|
|
||||||
|
auto& new_frame = res.frames.emplace_back();
|
||||||
|
new_frame.ms = 0;
|
||||||
|
new_frame.data.insert(new_frame.data.cbegin(), img_data, img_data+(desc.width*desc.height*4));
|
||||||
|
|
||||||
|
free(img_data);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> ImageEncoderQOI::encodeToMemoryRGBA(const ImageResult& input_image, const std::map<std::string, float>&) {
|
||||||
|
if (input_image.frames.empty()) {
|
||||||
|
std::cerr << "IEQOI error: empty image\n";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_image.frames.size() > 1) {
|
||||||
|
std::cerr << "IEQOI warning: image with animation, only first frame will be encoded!\n";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: look into RDO (eg https://github.com/richgel999/rdopng)
|
||||||
|
//int png_compression_level = 8;
|
||||||
|
//if (extra_options.count("png_compression_level")) {
|
||||||
|
//png_compression_level = extra_options.at("png_compression_level");
|
||||||
|
//}
|
||||||
|
|
||||||
|
qoi_desc desc;
|
||||||
|
desc.width = input_image.width;
|
||||||
|
desc.height = input_image.height;
|
||||||
|
desc.channels = 4;
|
||||||
|
desc.colorspace = QOI_SRGB; // TODO: decide
|
||||||
|
|
||||||
|
int out_len {0};
|
||||||
|
uint8_t* enc_data = static_cast<uint8_t*>(qoi_encode(
|
||||||
|
input_image.frames.front().data.data(),
|
||||||
|
&desc,
|
||||||
|
&out_len
|
||||||
|
));
|
||||||
|
|
||||||
|
if (enc_data == nullptr) {
|
||||||
|
std::cerr << "IEQOI error: qoi_encode failed!\n";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> new_data(enc_data, enc_data+out_len);
|
||||||
|
|
||||||
|
free(enc_data); // TODO: a streaming encoder would be better
|
||||||
|
|
||||||
|
return new_data;
|
||||||
|
}
|
||||||
|
|
13
src/image_loader_qoi.hpp
Normal file
13
src/image_loader_qoi.hpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "./image_loader.hpp"
|
||||||
|
|
||||||
|
struct ImageLoaderQOI : public ImageLoaderI {
|
||||||
|
ImageInfo loadInfoFromMemory(const uint8_t* data, uint64_t data_size) override;
|
||||||
|
ImageResult loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ImageEncoderQOI : public ImageEncoderI {
|
||||||
|
std::vector<uint8_t> encodeToMemoryRGBA(const ImageResult& input_image, const std::map<std::string, float>& extra_options = {}) override;
|
||||||
|
};
|
||||||
|
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "./image_loader_webp.hpp"
|
#include "./image_loader_webp.hpp"
|
||||||
#include "./image_loader_sdl_bmp.hpp"
|
#include "./image_loader_sdl_bmp.hpp"
|
||||||
|
#include "./image_loader_qoi.hpp"
|
||||||
#include "./image_loader_stb.hpp"
|
#include "./image_loader_stb.hpp"
|
||||||
|
|
||||||
#include <solanaceae/message3/components.hpp>
|
#include <solanaceae/message3/components.hpp>
|
||||||
@ -77,6 +78,7 @@ MediaMetaInfoLoader::MediaMetaInfoLoader(RegistryMessageModel& rmm) : _rmm(rmm)
|
|||||||
// HACK: make them be added externally?
|
// HACK: make them be added externally?
|
||||||
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
|
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
|
||||||
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
|
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
|
||||||
|
_image_loaders.push_back(std::make_unique<ImageLoaderQOI>());
|
||||||
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
|
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
|
||||||
|
|
||||||
_rmm.subscribe(this, RegistryMessageModel_Event::message_construct);
|
_rmm.subscribe(this, RegistryMessageModel_Event::message_construct);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "./message_image_loader.hpp"
|
#include "./message_image_loader.hpp"
|
||||||
|
|
||||||
#include "./image_loader_sdl_bmp.hpp"
|
#include "./image_loader_sdl_bmp.hpp"
|
||||||
|
#include "./image_loader_qoi.hpp"
|
||||||
#include "./image_loader_stb.hpp"
|
#include "./image_loader_stb.hpp"
|
||||||
#include "./image_loader_webp.hpp"
|
#include "./image_loader_webp.hpp"
|
||||||
#include "./media_meta_info_loader.hpp"
|
#include "./media_meta_info_loader.hpp"
|
||||||
@ -19,6 +20,7 @@ uint64_t getTimeMS(void);
|
|||||||
|
|
||||||
MessageImageLoader::MessageImageLoader(void) {
|
MessageImageLoader::MessageImageLoader(void) {
|
||||||
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
|
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
|
||||||
|
_image_loaders.push_back(std::make_unique<ImageLoaderQOI>());
|
||||||
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
|
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
|
||||||
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
|
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "./image_loader_sdl_bmp.hpp"
|
#include "./image_loader_sdl_bmp.hpp"
|
||||||
#include "./image_loader_stb.hpp"
|
#include "./image_loader_stb.hpp"
|
||||||
#include "./image_loader_webp.hpp"
|
#include "./image_loader_webp.hpp"
|
||||||
|
#include "./image_loader_qoi.hpp"
|
||||||
|
|
||||||
#include <imgui/imgui.h>
|
#include <imgui/imgui.h>
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ uint64_t getTimeMS(void);
|
|||||||
|
|
||||||
SendImagePopup::SendImagePopup(TextureUploaderI& tu) : _tu(tu) {
|
SendImagePopup::SendImagePopup(TextureUploaderI& tu) : _tu(tu) {
|
||||||
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
|
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
|
||||||
|
_image_loaders.push_back(std::make_unique<ImageLoaderQOI>());
|
||||||
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
|
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
|
||||||
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
|
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
|
||||||
}
|
}
|
||||||
@ -421,7 +423,7 @@ void SendImagePopup::render(float time_delta) {
|
|||||||
|
|
||||||
if (compress) {
|
if (compress) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Combo("##compression_type", ¤t_compressor, "webp\0jpeg\0png\n");
|
ImGui::Combo("##compression_type", ¤t_compressor, "webp\0jpeg\0png\0qoi\0");
|
||||||
|
|
||||||
ImGui::Indent();
|
ImGui::Indent();
|
||||||
// combo "webp""webp-lossless""png""jpg?"
|
// combo "webp""webp-lossless""png""jpg?"
|
||||||
@ -486,6 +488,11 @@ void SendImagePopup::render(float time_delta) {
|
|||||||
if (!new_data.empty()) {
|
if (!new_data.empty()) {
|
||||||
_on_send(new_data, ".png");
|
_on_send(new_data, ".png");
|
||||||
}
|
}
|
||||||
|
} else if (current_compressor == 3) {
|
||||||
|
new_data = ImageEncoderQOI{}.encodeToMemoryRGBA(tmp_img, {});;
|
||||||
|
if (!new_data.empty()) {
|
||||||
|
_on_send(new_data, ".qoi");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// error
|
// error
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "./tox_avatar_loader.hpp"
|
#include "./tox_avatar_loader.hpp"
|
||||||
|
|
||||||
#include "./image_loader_sdl_bmp.hpp"
|
#include "./image_loader_sdl_bmp.hpp"
|
||||||
|
#include "./image_loader_qoi.hpp"
|
||||||
#include "./image_loader_stb.hpp"
|
#include "./image_loader_stb.hpp"
|
||||||
#include "./image_loader_webp.hpp"
|
#include "./image_loader_webp.hpp"
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ uint64_t getTimeMS(void);
|
|||||||
|
|
||||||
ToxAvatarLoader::ToxAvatarLoader(Contact3Registry& cr) : _cr(cr) {
|
ToxAvatarLoader::ToxAvatarLoader(Contact3Registry& cr) : _cr(cr) {
|
||||||
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
|
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
|
||||||
|
_image_loaders.push_back(std::make_unique<ImageLoaderQOI>());
|
||||||
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
|
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
|
||||||
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
|
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user