From 4ca304898887c881c853bcc1b4bd92fbaa4353e7 Mon Sep 17 00:00:00 2001 From: Green Sky Date: Mon, 7 Apr 2025 16:18:32 +0200 Subject: [PATCH] add lossless webp encoding --- src/chat_gui/send_image_popup.cpp | 15 ++++++++++----- src/image_loader_webp.cpp | 26 +++++++++++++++++++------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/chat_gui/send_image_popup.cpp b/src/chat_gui/send_image_popup.cpp index b4d9389..680c49e 100644 --- a/src/chat_gui/send_image_popup.cpp +++ b/src/chat_gui/send_image_popup.cpp @@ -473,17 +473,17 @@ void SendImagePopup::render(float time_delta) { if (compress) { ImGui::SameLine(); - ImGui::Combo("##compression_type", ¤t_compressor, "webp\0jpeg\0png\0qoi\0"); + ImGui::Combo("##compression_type", ¤t_compressor, "webp\0webp lossless\0jpeg\0png\0qoi\0"); ImGui::Indent(); // combo "webp""webp-lossless""png""jpg?" // if lossy quality slider (1-100) default 80 - if (current_compressor == 0 || current_compressor == 1) { + if (current_compressor == 0 || current_compressor == 2) { const uint32_t qmin = 1; const uint32_t qmax = 100; recalc_size |= ImGui::SliderScalar("quality", ImGuiDataType_U32, &quality, &qmin, &qmax); } - if (current_compressor == 2) { + if (current_compressor == 1 || current_compressor == 3) { const uint32_t qmin = 0; const uint32_t qmax = 9; recalc_size |= ImGui::SliderScalar("compression_level", ImGuiDataType_U32, &compression_level, &qmin, &qmax); @@ -529,16 +529,21 @@ void SendImagePopup::render(float time_delta) { _on_send(new_data, ".webp"); } } else if (current_compressor == 1) { + new_data = ImageEncoderWebP{}.encodeToMemoryRGBA(tmp_img, {{"compression_level", compression_level}}); + if (!new_data.empty()) { + _on_send(new_data, ".webp"); + } + } else if (current_compressor == 2) { new_data = ImageEncoderSTBJpeg{}.encodeToMemoryRGBA(tmp_img, {{"quality", quality}});; if (!new_data.empty()) { _on_send(new_data, ".jpg"); } - } else if (current_compressor == 2) { + } else if (current_compressor == 3) { new_data = ImageEncoderSTBPNG{}.encodeToMemoryRGBA(tmp_img, {{"png_compression_level", compression_level}});; if (!new_data.empty()) { _on_send(new_data, ".png"); } - } else if (current_compressor == 3) { + } else if (current_compressor == 4) { new_data = ImageEncoderQOI{}.encodeToMemoryRGBA(tmp_img, {});; if (!new_data.empty()) { _on_send(new_data, ".qoi"); diff --git a/src/image_loader_webp.cpp b/src/image_loader_webp.cpp index 85a848b..1fba8b8 100644 --- a/src/image_loader_webp.cpp +++ b/src/image_loader_webp.cpp @@ -92,6 +92,13 @@ std::vector ImageEncoderWebP::encodeToMemoryRGBA(const ImageResult& inp if (extra_options.count("quality")) { quality = extra_options.at("quality"); } + bool lossless = false; + int compression_level = 6; + if (extra_options.count("compression_level")) { + // if compression_level is set, we assume lossless + lossless = true; + compression_level = extra_options.at("compression_level"); + } // start encoding @@ -113,15 +120,20 @@ std::vector ImageEncoderWebP::encodeToMemoryRGBA(const ImageResult& inp return {}; } - int prev_timestamp = 0; - for (const auto& frame : input_image.frames) { - WebPConfig config; - if (!WebPConfigPreset(&config, WebPPreset::WEBP_PRESET_DEFAULT, quality)) { - std::cerr << "IEWebP error: WebPConfigPreset()\n"; + WebPConfig config; + if (!WebPConfigPreset(&config, WebPPreset::WEBP_PRESET_DEFAULT, quality)) { + std::cerr << "IEWebP error: WebPConfigPreset()\n"; + return {}; + } + if (lossless) { + if (!WebPConfigLosslessPreset(&config, compression_level)) { + std::cerr << "IEWebP error: WebPConfigLosslessPreset()\n"; return {}; } - //WebPConfigLosslessPreset(&config, 6); // 9 for max compression + } + int prev_timestamp = 0; + for (const auto& frame : input_image.frames) { WebPPicture frame_webp; if (!WebPPictureInit(&frame_webp)) { std::cerr << "IEWebP error: WebPPictureInit()\n"; @@ -135,7 +147,7 @@ std::vector ImageEncoderWebP::encodeToMemoryRGBA(const ImageResult& inp } if (!WebPAnimEncoderAdd(enc.get(), &frame_webp, prev_timestamp, &config)) { - std::cerr << "IEWebP error: WebPAnimEncoderAdd()\n"; + std::cerr << "IEWebP error: WebPAnimEncoderAdd(): " << frame_webp.error_code << "\n"; WebPPictureFree(&frame_webp); return {}; }