Add option to ignore images while recoloring

Ideally we would handle this differently. See the TODO entry in the render
function. But the patch is a start.

Thanks to carlos for the patch.

Closes: #398

Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
This commit is contained in:
Sebastian Ramacher 2014-09-30 19:45:07 +02:00
parent 50ea97468c
commit 9a06b5f61e
6 changed files with 122 additions and 3 deletions

View File

@ -510,6 +510,23 @@ cb_setting_recolor_keep_hue_change(girara_session_t* session, const char* name,
}
}
void
cb_setting_recolor_keep_reverse_video_change(girara_session_t* session, const char* name,
girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
{
g_return_if_fail(value != NULL);
g_return_if_fail(session != NULL);
g_return_if_fail(session->global.data != NULL);
g_return_if_fail(name != NULL);
zathura_t* zathura = session->global.data;
const bool bool_value = *((bool*) value);
if (zathura->sync.render_thread != NULL && zathura_renderer_recolor_reverse_video_enabled(zathura->sync.render_thread) != bool_value) {
zathura_renderer_enable_recolor_reverse_video(zathura->sync.render_thread, bool_value);
render_all(zathura);
}
}
bool
cb_unknown_command(girara_session_t* session, const char* input)

View File

@ -176,6 +176,17 @@ void cb_setting_recolor_change(girara_session_t* session, const char* name,
void cb_setting_recolor_keep_hue_change(girara_session_t* session, const char* name,
girara_setting_type_t type, void* value, void* data);
/**
* Emitted when the 'recolor-reverse-video' setting is changed
*
* @param session Girara session
* @param name Name of the setting ("recolor")
* @param type Type of the setting (BOOLEAN)
* @param value New value
* @param data Custom data
*/
void cb_setting_recolor_keep_reverse_video_change(girara_session_t* session,
const char* name, girara_setting_type_t type, void* value, void* data);
/**
* Unknown command handler which is used to handle the strict numeric goto

View File

@ -186,6 +186,8 @@ config_load_default(zathura_t* zathura)
bool_value = false;
girara_setting_add(gsession, "recolor-keephue", &bool_value, BOOLEAN, false, _("When recoloring keep original hue and adjust lightness only"), cb_setting_recolor_keep_hue_change, NULL);
bool_value = false;
girara_setting_add(gsession, "recolor-reverse-video", &bool_value, BOOLEAN, false, _("When recoloring keep original image colors"), cb_setting_recolor_keep_reverse_video_change, NULL);
bool_value = false;
girara_setting_add(gsession, "scroll-wrap", &bool_value, BOOLEAN, false, _("Wrap scrolling"), NULL, NULL);
bool_value = false;
girara_setting_add(gsession, "scroll-page-aware", &bool_value, BOOLEAN, false, _("Page aware scrolling"), NULL, NULL);

View File

@ -43,6 +43,7 @@ typedef struct private_s {
struct {
bool enabled;
bool hue;
bool reverse_video;
GdkRGBA light;
GdkRGBA dark;
@ -107,6 +108,7 @@ zathura_renderer_init(ZathuraRenderer* renderer)
/* recolor */
priv->recolor.enabled = false;
priv->recolor.hue = true;
priv->recolor.reverse_video = false;
/* page cache */
priv->page_cache.size = 0;
@ -336,6 +338,21 @@ zathura_renderer_enable_recolor_hue(ZathuraRenderer* renderer, bool enable)
GET_PRIVATE(renderer)->recolor.hue = enable;
}
bool
zathura_renderer_recolor_reverse_video_enabled(ZathuraRenderer* renderer)
{
g_return_val_if_fail(ZATHURA_IS_RENDERER(renderer), false);
return GET_PRIVATE(renderer)->recolor.reverse_video;
}
void
zathura_renderer_enable_recolor_reverse_video(ZathuraRenderer* renderer, bool enable)
{
g_return_if_fail(ZATHURA_IS_RENDERER(renderer));
GET_PRIVATE(renderer)->recolor.reverse_video = enable;
}
void
zathura_renderer_set_recolor_colors(ZathuraRenderer* renderer,
const GdkRGBA* light, const GdkRGBA* dark)
@ -563,8 +580,8 @@ colorumax(const double* h, double l, double l1, double l2)
}
static void
recolor(private_t* priv, unsigned int page_width, unsigned int page_height,
cairo_surface_t* surface)
recolor(private_t* priv, zathura_page_t* page, unsigned int page_width,
unsigned int page_height, cairo_surface_t* surface)
{
/* uses a representation of a rgb color as follows:
- a lightness scalar (between 0,1), which is a weighted average of r, g, b,
@ -574,6 +591,12 @@ recolor(private_t* priv, unsigned int page_width, unsigned int page_height,
in the boundary of the rgb cube.
*/
/* TODO: split handling of image handling off
* Ideally we would create a mask surface for the location of the images and
* we would blit the the recolored and unmodified surfaces together to get the
* same effect.
*/
const int rowstride = cairo_image_surface_get_stride(surface);
unsigned char* image = cairo_image_surface_get_data(surface);
@ -591,10 +614,54 @@ recolor(private_t* priv, unsigned int page_width, unsigned int page_height,
rgb2.blue - rgb1.blue
};
girara_list_t* images = NULL;
girara_list_t* rectangles = NULL;
bool found_images = false;
/* If in reverse video mode retrieve images */
if (priv->recolor.reverse_video == true) {
images = zathura_page_images_get(page, NULL);
found_images = (images != NULL);
rectangles = girara_list_new();
if (rectangles == NULL) {
found_images = false;
girara_warning("Failed to retrieve images.\n");
}
if (found_images == true) {
/* Get images bounding boxes */
GIRARA_LIST_FOREACH(images, zathura_image_t*, iter, image_it)
zathura_rectangle_t* rect = g_try_malloc(sizeof(zathura_rectangle_t));
if (rect == NULL) {
break;
}
*rect = recalc_rectangle(page, image_it->position);
girara_list_append(rectangles, rect);
GIRARA_LIST_FOREACH_END(images, zathura_image_t*, iter, image_it);
}
}
for (unsigned int y = 0; y < page_height; y++) {
unsigned char* data = image + y * rowstride;
for (unsigned int x = 0; x < page_width; x++, data += 4) {
/* Check if the pixel belongs to an image when in reverse video mode*/
if (priv->recolor.reverse_video == true && found_images == true){
bool inside_image = false;
GIRARA_LIST_FOREACH(rectangles, zathura_rectangle_t*, iter, rect_it)
if (rect_it->x1 <= x && rect_it->x2 >= x &&
rect_it->y1 <= y && rect_it->y2 >= y) {
inside_image = true;
break;
}
GIRARA_LIST_FOREACH_END(rectangles, zathura_rectangle_t*, iter, rect_it);
/* If it's inside and image don't recolor */
if (inside_image == true) {
continue;
}
}
/* Careful. data color components blue, green, red. */
const double rgb[3] = {
(double) data[2] / 256.,
@ -640,6 +707,13 @@ recolor(private_t* priv, unsigned int page_width, unsigned int page_height,
}
}
if (images != NULL) {
girara_list_free(images);
}
if (rectangles != NULL) {
girara_list_free(rectangles);
}
#undef rgb1
#undef rgb2
}
@ -708,7 +782,7 @@ render(render_job_t* job, ZathuraRenderRequest* request, ZathuraRenderer* render
/* recolor */
if (priv->recolor.enabled == true) {
recolor(priv, page_width, page_height, surface);
recolor(priv, page, page_width, page_height, surface);
}
emit_completed_signal_t* ecs = g_try_malloc0(sizeof(emit_completed_signal_t));

View File

@ -71,6 +71,19 @@ bool zathura_renderer_recolor_hue_enabled(ZathuraRenderer* renderer);
*/
void zathura_renderer_enable_recolor_hue(ZathuraRenderer* renderer,
bool enable);
/**
* Return whether images should be recolored while recoloring.
* @param renderer a renderer object
* @returns true if images should be recolored, false otherwise
*/
bool zathura_renderer_recolor_reverse_video_enabled(ZathuraRenderer* renderer);
/**
* Enable/disable recoloring of images while recoloring.
* @param renderer a renderer object
* @param enable or disable images recoloring
*/
void zathura_renderer_enable_recolor_reverse_video(ZathuraRenderer* renderer,
bool enable);
/**
* Set light and dark colors for recoloring.
* @param renderer a renderer object

View File

@ -744,6 +744,8 @@ document_open(zathura_t* zathura, const char* path, const char* password,
zathura_renderer_enable_recolor(zathura->sync.render_thread, recolor);
girara_setting_get(zathura->ui.session, "recolor-keephue", &recolor);
zathura_renderer_enable_recolor_hue(zathura->sync.render_thread, recolor);
girara_setting_get(zathura->ui.session, "recolor-reverse-video", &recolor);
zathura_renderer_enable_recolor_reverse_video(zathura->sync.render_thread, recolor);
/* get view port size */
GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(