diff --git a/CMakeLists.txt b/CMakeLists.txt index b7590cb..1fa9258 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,11 @@ cmake_minimum_required(VERSION 3.5) project(singlechat.wt LANGUAGES CXX) +add_compile_options(-Wno-deprecated-declarations) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_COMPILER "/usr/bin/g++-12") set(CMAKE_PREFIX_PATH "/usr") add_executable(${PROJECT_NAME} @@ -14,14 +16,16 @@ add_executable(${PROJECT_NAME} docroot/ads.txt docroot/links.csv ) - target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20) +find_package(Threads REQUIRED) + target_link_libraries(${PROJECT_NAME} wt wthttp curl xml2 + ${CMAKE_THREAD_LIBS_INIT} ) find_package(Boost COMPONENTS system filesystem REQUIRED) diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user index c3c00b4..eca8067 100644 --- a/CMakeLists.txt.user +++ b/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -37,7 +37,6 @@ true true 1 - 0 false true false @@ -77,7 +76,6 @@ true Builtin.DefaultTidyAndClazy 8 - true @@ -100,7 +98,6 @@ 0 Debug - 2 false -DCMAKE_GENERATOR:STRING=Ninja @@ -154,7 +151,6 @@ Release - 2 false -DCMAKE_GENERATOR:STRING=Ninja @@ -206,7 +202,6 @@ RelWithDebInfo - 2 false -DCMAKE_GENERATOR:STRING=Ninja @@ -258,7 +253,6 @@ RelWithDebInfo - 2 false -DCMAKE_GENERATOR:STRING=Ninja @@ -311,7 +305,6 @@ MinSizeRel - 2 false -DCMAKE_GENERATOR:STRING=Ninja @@ -378,20 +371,19 @@ true true - 0 true /usr/bin/valgrind 2 - false - SingleChat - CMakeProjectManager.CMakeRunConfiguration.SingleChat - SingleChat - true + singlechat.wt + CMakeProjectManager.CMakeRunConfiguration.singlechat.wt + singlechat.wt --docroot ../docroot/ --http-port=4500 --http-address=0.0.0.0 + false true true + false true /home/torsten/Programs/SingleChat/build diff --git a/src/app.cpp b/src/app.cpp index 52edf33..bd1249c 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -469,57 +469,22 @@ void App::sendImage() { void App::imageUploaded(Wt::WFileUpload *fileWidget, std::shared_ptr localImage, Wt::WImage *image, Wt::WPushButton *okButton) { try { + const std::string uploadedFile = fileWidget->spoolFileName(); std::list originalImages; - Magick::readImages(&originalImages, fileWidget->spoolFileName()); - std::list previewList; - std::list localList; - - // Maximale Größen für Vorschau und lokale Liste festlegen - int maxPreviewWidth = 100; - int maxPreviewHeight = 100; - int maxLocalWidth = 500; - int maxLocalHeight = 500; - - // Originalgröße des ersten Bildes erhalten - int originalWidth = originalImages.front().columns(); - int originalHeight = originalImages.front().rows(); - - // Vorschau- und lokale Größe berechnen - int previewWidth = std::min(originalWidth, maxPreviewWidth); - int previewHeight = std::min(originalHeight, maxPreviewHeight); - int localWidth = std::min(originalWidth, maxLocalWidth); - int localHeight = std::min(originalHeight, maxLocalHeight); - - // Größenänderung für alle Frames durchführen - for (const auto& img : originalImages) { - // Größenänderung nur durchführen, wenn das Bild größer als die maximalen Größen ist - if (originalWidth > maxPreviewWidth || originalHeight > maxPreviewHeight) { - Magick::Image resizedPreview = img; - resizedPreview.resize(Magick::Geometry(previewWidth, previewHeight)); - previewList.push_back(resizedPreview); - } else { - previewList.push_back(img); // Originalgröße beibehalten - } - - if (originalWidth > maxLocalWidth || originalHeight > maxLocalHeight) { - Magick::Image resizedLocal = img; - resizedLocal.resize(Magick::Geometry(localWidth, localHeight)); - localList.push_back(resizedLocal); - } else { - localList.push_back(img); // Originalgröße beibehalten - } - } - - Magick::Blob resizedBlob; - Magick::writeImages(previewList.begin(), previewList.end(), &resizedBlob); - Magick::writeImages(localList.begin(), localList.end(), &(*localImage)); - auto resizedBase64 = resizedBlob.base64(); - auto resizedImageString = Wt::Utils::base64Decode(resizedBase64); - std::string imageFormat = previewList.front().magick(); - auto imageResource = std::make_shared( - "image/" + imageFormat, - std::vector(resizedImageString.begin(), resizedImageString.end())); - image->setImageLink(Wt::WLink(imageResource)); + Magick::readImages(&originalImages, uploadedFile); + std::list resizedForLocalImage; + std::list resizedForDisplayImage; + resizedForLocalImage = resizeImages(originalImages, 500, 500); + resizedForDisplayImage = resizeImages(originalImages, 100, 100); + std::string imageType = originalImages.front().magick(); + std::string mimeType = "image/" + imageType; + Magick::writeImages(resizedForLocalImage.begin(), resizedForLocalImage.end(), localImage.get(), true); + Magick::Blob displayBlob; + Magick::writeImages(resizedForDisplayImage.begin(), resizedForDisplayImage.end(), &displayBlob, true); + auto memoryResource = std::make_shared(mimeType); + memoryResource->setData(static_cast(displayBlob.data()), displayBlob.length()); + image->setImageLink(Wt::WLink(memoryResource)); + image->setAlternateText("Hochgeladenes und verarbeitetes Bild"); okButton->setEnabled(true); triggerUpdate(); } catch (const std::exception& e) { @@ -527,16 +492,19 @@ void App::imageUploaded(Wt::WFileUpload *fileWidget, std::shared_ptr maxSize) { - scale = (maxSize * 100) / maxDimension; +std::list App::resizeImages(std::list &images, int maxWidth, int maxHeight) { + std::list resizedImages; + for (auto& img : images) { + Magick::Geometry newSize = img.size(); + newSize.aspect(true); + if (newSize.width() > maxWidth || newSize.height() > maxHeight) { + newSize.width(maxWidth); + newSize.height(maxHeight); + img.resize(newSize); + } + resizedImages.push_back(img); } - scale = (scale < 100) ? scale : 100; - Magick::Image scaledImage(originalImage); - scaledImage.scale(Magick::Geometry(originalImage.size().width() * scale / 100, originalImage.size().height() * scale / 100)); - return scaledImage; + return resizedImages; } Wt::WContainerWidget* App::createSmileyButton(Wt::WHBoxLayout* inputLayout, Wt::WLineEdit* inputLine, std::shared_ptr cursorPosition) { @@ -696,30 +664,16 @@ void App::createImprintContainer(Wt::WVBoxLayout *containerLayout) { Wt::WWebWidget* App::createImageElement(Wt::Json::Object& line, const std::string& writer, Wt::WContainerWidget* outputContainer, std::string id) { Wt::Json::Object imageDescription = line["image"]; - std::cout << __LINE__ << std::endl; auto imageLineItem = outputContainer->addNew(); - std::cout << __LINE__ << std::endl; auto outputText = Wt::WString("{1}: ").arg(writer); - std::cout << __LINE__ << std::endl; imageLineItem->addNew(outputText)->setStyleClass("output-line"); - std::cout << __LINE__ << std::endl; auto image = imageLineItem->addNew(); - std::cout << __LINE__ << std::endl; std::string base64Data = (std::string)imageDescription["imageblobbase64"]; - std::string decodedData = Wt::Utils::base64Decode(base64Data); // Decode Base64 data - Magick::Blob imageBlob(decodedData.data(), decodedData.size()); - Magick::Image magickImage; - magickImage.read(imageBlob); - std::string imageFormat = magickImage.magick(); - std::cout << __LINE__ << std::endl; - std::cout << imageFormat << std::endl; - Magick::Blob blob; - magickImage.write(&blob); - auto resizedBase64 = blob.base64(); - auto resizedImageString = Wt::Utils::base64Decode(resizedBase64); + std::string decodedData = Wt::Utils::base64Decode(base64Data); + std::string imageType = imageDescription["type"].toString(); // Lese den Bildtyp auto imageResource = std::make_shared( - "image/" + imageFormat, - std::vector(resizedImageString.begin(), resizedImageString.end())); // Verwenden Sie den direkt decodierten Inhalt + "image/" + imageType, + std::vector(decodedData.begin(), decodedData.end())); std::cout << __LINE__ << std::endl; image->setImageLink(Wt::WLink(imageResource)); imageLineItem->setAttributeValue("dummy", id); diff --git a/src/app.h b/src/app.h index 17354d1..b59de2f 100644 --- a/src/app.h +++ b/src/app.h @@ -183,7 +183,6 @@ private: void setCurlOptions(CURL *curl, const std::string &apiUrl); std::string buildApiUrl(const std::string &userIP); std::string getUserIP(); - Magick::Image scaleImage(const Magick::Image &originalImage, int maxSize) const; Wt::WWebWidget *createImageElement(Wt::Json::Object &line, const std::string &writer, Wt::WContainerWidget *outputContainer, std::string id); Wt::WWebWidget *createTextElement(const std::string &writer, const std::string &text, Wt::WContainerWidget *outputContainer, std::string id); void createImprintContainer(Wt::WVBoxLayout *containerLayout); @@ -209,6 +208,7 @@ private: void showPartnerSites(); void sendImage(); void imageUploaded(Wt::WFileUpload *fileWidget, std::shared_ptr localImage, Wt::WImage *image, Wt::WPushButton *okButton); + std::list resizeImages(std::list& images, int maxWidth, int maxHeight); bool isAnimatedGIF(const Magick::Blob &blob); }; diff --git a/src/broadcast.cpp b/src/broadcast.cpp index b16fb6a..f694830 100644 --- a/src/broadcast.cpp +++ b/src/broadcast.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -669,10 +670,13 @@ Broadcast::Message::Message(std::string fromSessionId_, std::shared_ptr(imageBlob->data()), imageBlob->length()); + std::string imageFormat = image_.magick(); image = { {"width", Wt::Json::Value((int)image_.columns())}, {"height", Wt::Json::Value((int)image_.rows())}, - {"imageblobbase64", Wt::Json::Value(imageBlob->base64())} + {"imageblobbase64", Wt::Json::Value(Wt::Utils::base64Encode(imageData))}, + {"type", Wt::Json::Value(imageFormat)} }; }