aboutsummaryrefslogtreecommitdiff
path: root/src/QuickMedia.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/QuickMedia.cpp')
-rw-r--r--src/QuickMedia.cpp119
1 files changed, 111 insertions, 8 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 75bc027..6db58c9 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -13,6 +13,7 @@
#include "../include/GoogleCaptcha.hpp"
#include "../include/Notification.hpp"
#include "../include/ImageViewer.hpp"
+#include "../include/ImageUtils.hpp"
#include <cppcodec/base64_rfc4648.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
@@ -68,6 +69,11 @@ static int get_monitor_max_hz(Display *display) {
return 60;
}
+static void get_screen_resolution(Display *display, int *width, int *height) {
+ *width = DefaultScreenOfDisplay(display)->width;
+ *height = DefaultScreenOfDisplay(display)->height;
+}
+
static bool has_gl_ext(Display *disp, const char *ext) {
const char *extensions = glXQueryExtensionsString(disp, DefaultScreen(disp));
if(!extensions)
@@ -193,6 +199,14 @@ namespace QuickMedia {
}
Program::~Program() {
+ running = false;
+ if(upscale_images) {
+ {
+ std::unique_lock<std::mutex> lock(image_upscale_mutex);
+ image_upscale_cv.notify_one();
+ }
+ image_upscale_thead.join();
+ }
delete related_media_body;
delete body;
delete current_plugin;
@@ -223,6 +237,7 @@ namespace QuickMedia {
fprintf(stderr, " plugin The plugin to use. Should be either 4chan, manganelo, mangatown, mangadex, pornhub, youtube or dmenu\n");
fprintf(stderr, " --tor Use tor. Disabled by default\n");
fprintf(stderr, " --use-system-mpv-config Use system mpv config instead of no config. Disabled by default\n");
+ fprintf(stderr, " --upscale-images Upscale low-resolution manga pages using waifu2x-ncnn-vulkan. Disabled by default\n");
fprintf(stderr, " -p Change the placeholder text for dmenu\n");
fprintf(stderr, "EXAMPLES:\n");
fprintf(stderr, "QuickMedia manganelo\n");
@@ -292,6 +307,8 @@ namespace QuickMedia {
use_tor = true;
} else if(strcmp(argv[i], "--use-system-mpv-config") == 0) {
use_system_mpv_config = true;
+ } else if(strcmp(argv[i], "--upscale-images") == 0) {
+ upscale_images = true;
} else if(strcmp(argv[i], "-p") == 0) {
if(i < argc - 1) {
search_placeholder = argv[i + 1];
@@ -309,6 +326,51 @@ namespace QuickMedia {
return -2;
}
+ if(upscale_images) {
+ if(!current_plugin->is_manga()) {
+ fprintf(stderr, "Option --upscale-images is only valid for manganelo, mangatown and mangadex\n");
+ return -2;
+ }
+
+ if(!is_program_executable_by_name("waifu2x-ncnn-vulkan")) {
+ fprintf(stderr, "waifu2x-ncnn-vulkan needs to be installed (and accessible from PATH environment variable) when using the --upscale-images option\n");
+ return -2;
+ }
+
+ running = true;
+ image_upscale_thead = std::thread([this]{
+ CopyOp copy_op;
+ while(running) {
+ {
+ std::unique_lock<std::mutex> lock(image_upscale_mutex);
+ while(images_to_upscale.empty() && running) image_upscale_cv.wait(lock);
+ if(!running)
+ break;
+ copy_op = images_to_upscale.front();
+ images_to_upscale.pop_front();
+ }
+
+ Path tmp_file = copy_op.source;
+ tmp_file.append(".tmp.jpg");
+
+ fprintf(stderr, "Upscaling %s\n", copy_op.source.data.c_str());
+ const char *args[] = { "waifu2x-ncnn-vulkan", "-i", copy_op.source.data.c_str(), "-o", tmp_file.data.c_str(), nullptr };
+ if(exec_program(args, nullptr, nullptr) != 0) {
+ fprintf(stderr, "Warning: failed to upscale %s with waifu2x-ncnn-vulkan\n", copy_op.source.data.c_str());
+ // No conversion, but we need the file to have the destination name to see that the operation completed (and read it)
+ if(rename(copy_op.source.data.c_str(), copy_op.destination.data.c_str()) != 0)
+ perror(tmp_file.data.c_str());
+ continue;
+ }
+
+ if(rename(tmp_file.data.c_str(), copy_op.destination.data.c_str()) != 0)
+ perror(tmp_file.data.c_str());
+ }
+ });
+ } else {
+ running = true;
+ }
+
current_plugin->use_tor = use_tor;
window.setTitle("QuickMedia - " + current_plugin->name);
@@ -1828,6 +1890,7 @@ namespace QuickMedia {
}
}
+ // TODO: Cancel download when navigating to another non-manga page
void Program::download_chapter_images_if_needed(Manga *image_plugin) {
if(downloading_chapter_url == images_url)
return;
@@ -1910,10 +1973,35 @@ namespace QuickMedia {
return false;
}
- if(rename(image_filepath_tmp.data.c_str(), image_filepath.data.c_str()) != 0) {
- perror("rename");
- show_notification("Storage", "Failed to save image to file: " + image_filepath_tmp.data, Urgency::CRITICAL);
- return false;
+ bool rename_immediately = true;
+ if(upscale_images) {
+ int screen_width, screen_height;
+ get_screen_resolution(disp, &screen_width, &screen_height);
+
+ int image_width, image_height;
+ if(image_get_resolution(image_filepath_tmp, &image_width, &image_height)) {
+ if(image_height < screen_height * 0.75) {
+ rename_immediately = false;
+ CopyOp copy_op;
+ copy_op.source = image_filepath_tmp;
+ copy_op.destination = image_filepath;
+ std::unique_lock<std::mutex> lock(image_upscale_mutex);
+ images_to_upscale.push_back(std::move(copy_op));
+ image_upscale_cv.notify_one();
+ } else {
+ fprintf(stderr, "Info: not upscaling %s because the file is already large on your monitor (screen height: %d, image height: %d)\n", image_filepath_tmp.data.c_str(), screen_height, image_height);
+ }
+ } else {
+ fprintf(stderr, "Warning: failed to upscale %s because QuickMedia failed to recognize the resolution of the image\n", image_filepath_tmp.data.c_str());
+ }
+ }
+
+ if(rename_immediately) {
+ if(rename(image_filepath_tmp.data.c_str(), image_filepath.data.c_str()) != 0) {
+ perror(image_filepath_tmp.data.c_str());
+ show_notification("Storage", "Failed to save image to file: " + image_filepath.data, Urgency::CRITICAL);
+ return false;
+ }
}
return true;
@@ -1922,6 +2010,7 @@ namespace QuickMedia {
}
void Program::image_page() {
+ image_download_cancel = false;
search_bar->onTextUpdateCallback = nullptr;
search_bar->onTextSubmitCallback = nullptr;
@@ -2024,25 +2113,25 @@ namespace QuickMedia {
if(event.key.code == sf::Keyboard::Up) {
if(image_index > 0) {
--image_index;
- return;
+ goto end_of_images_page;
} else if(image_index == 0 && body->get_selected_item() < (int)body->items.size() - 1) {
// TODO: Make this work if the list is sorted differently than from newest to oldest.
body->filter_search_fuzzy("");
body->select_next_item();
select_episode(body->items[body->get_selected_item()].get(), true);
image_index = 99999; // Start at the page that shows we are at the end of the chapter
- return;
+ goto end_of_images_page;
}
} else if(event.key.code == sf::Keyboard::Down) {
if(image_index < num_images) {
++image_index;
- return;
+ goto end_of_images_page;
} else if(image_index == num_images && body->get_selected_item() > 0) {
// TODO: Make this work if the list is sorted differently than from newest to oldest.
body->filter_search_fuzzy("");
body->select_previous_item();
select_episode(body->items[body->get_selected_item()].get(), true);
- return;
+ goto end_of_images_page;
}
} else if(event.key.code == sf::Keyboard::Escape) {
current_page = Page::EPISODE_LIST;
@@ -2112,9 +2201,17 @@ namespace QuickMedia {
window.display();
}
+
+ end_of_images_page:
+ if(current_page != Page::IMAGES && current_page != Page::IMAGES_CONTINUOUS) {
+ image_download_cancel = true;
+ std::unique_lock<std::mutex> lock(image_upscale_mutex);
+ images_to_upscale.clear();
+ }
}
void Program::image_continuous_page() {
+ image_download_cancel = false;
search_bar->onTextUpdateCallback = nullptr;
search_bar->onTextSubmitCallback = nullptr;
@@ -2182,6 +2279,12 @@ namespace QuickMedia {
}
}
}
+
+ if(current_page != Page::IMAGES && current_page != Page::IMAGES_CONTINUOUS) {
+ image_download_cancel = true;
+ std::unique_lock<std::mutex> lock(image_upscale_mutex);
+ images_to_upscale.clear();
+ }
}
void Program::content_list_page() {