} ExifOrientationType;
#endif
-
-/* size to use when breaking up image pane for rendering */
-#define PR_TILE_SIZE 128
-
typedef struct _ImageTile ImageTile;
typedef struct _QueueData QueueData;
RendererFuncs f;
PixbufRenderer *pr;
- gint tile_cache_max; /* max mb to use for offscreen buffer */
+ gint tile_cache_max; /* max MiB to use for offscreen buffer */
gint tile_width;
gint tile_height;
// d = gdk_drawable_get_depth(pixmap);
// gdk_drawable_get_size(pixmap, &w, &h);
- return PR_TILE_SIZE * PR_TILE_SIZE * 4 / 8;
+ return options->image.tile_size * options->image.tile_size * 4 / 8;
}
static void rt_hidpi_aware_draw(
{
rt_overlay_free(rc, od);
}
+
+ gtk_widget_queue_draw(GTK_WIDGET(rc->pr));
}
#else
void renderer_tiles_overlay_set(void *renderer, gint id, GdkPixbuf *pixbuf, gint x, gint y)
return draw;
}
+/**
+ * @brief
+ * @param has_alpha
+ * @param ignore_alpha
+ * @param src
+ * @param dest
+ * @param pb_x
+ * @param pb_y
+ * @param pb_w
+ * @param pb_h
+ * @param offset_x
+ * @param offset_y
+ * @param scale_x
+ * @param scale_y
+ * @param interp_type
+ * @param check_x
+ * @param check_y
+ * @param wide_image Used as a work-around for a GdkPixbuf problem. Set when image width is > 32767. Problem exhibited with gdk_pixbuf_copy_area() and GDK_INTERP_NEAREST. See #772 on GitHub Geeqie
+ *
+ *
+ */
static void rt_tile_get_region(gboolean has_alpha, gboolean ignore_alpha,
const GdkPixbuf *src, GdkPixbuf *dest,
int pb_x, int pb_y, int pb_w, int pb_h,
double offset_x, double offset_y, double scale_x, double scale_y,
GdkInterpType interp_type,
- int check_x, int check_y)
+ int check_x, int check_y, gboolean wide_image)
{
GdkPixbuf* tmppixbuf;
+ gint srs;
+ gint drs;
+ gint x;
+ gint y;
+ gint c;
+ guchar *psrc;
+ guchar *pdst;
if (!has_alpha)
{
if (scale_x == 1.0 && scale_y == 1.0)
{
- gdk_pixbuf_copy_area(src,
- -offset_x + pb_x, -offset_y + pb_y,
- pb_w, pb_h,
- dest,
- pb_x, pb_y);
+ if (wide_image)
+ {
+ srs = gdk_pixbuf_get_rowstride(src);
+ drs = gdk_pixbuf_get_rowstride(dest);
+ psrc = gdk_pixbuf_get_pixels(src);
+ pdst = gdk_pixbuf_get_pixels(dest);
+ for (y = 0; y < pb_h; y++)
+ {
+ for (x = 0; x < pb_w; x++)
+ {
+ for (c = 0; c < 3; c++)
+ {
+ pdst[(y * drs) + x*3 + c] = psrc[(-(int)offset_y + pb_y + y) * srs + (-(int)offset_x + pb_x+x)*3 + c];
+ }
+ }
+ }
+ }
+ else
+ {
+ gdk_pixbuf_copy_area(src,
+ -offset_x + pb_x, -offset_y + pb_y,
+ pb_w, pb_h,
+ dest,
+ pb_x, pb_y);
+ }
}
else
{
gdk_pixbuf_scale(src, dest,
- pb_x, pb_y, pb_w, pb_h,
- offset_x,
- offset_y,
- scale_x, scale_y,
- interp_type);
+ pb_x, pb_y, pb_w, pb_h,
+ offset_x,
+ offset_y,
+ scale_x, scale_y,
+ (wide_image && interp_type == GDK_INTERP_NEAREST) ? GDK_INTERP_TILES : interp_type);
}
}
else
gboolean has_alpha;
gboolean draw = FALSE;
gint orientation = rt_get_orientation(rt);
+ gboolean wide_image = FALSE;
if (it->render_todo == TILE_RENDER_NONE && it->surface && !new_data) return;
rt_tile_prepare(rt, it);
has_alpha = (pr->pixbuf && gdk_pixbuf_get_has_alpha(pr->pixbuf));
- /* FIXME checker colors for alpha should be configurable,
+ /** @FIXME checker colors for alpha should be configurable,
* also should be drawn for blank = TRUE
*/
* small sizes for anything but GDK_INTERP_NEAREST
*/
if (pr->width < PR_MIN_SCALE_SIZE || pr->height < PR_MIN_SCALE_SIZE) fast = TRUE;
+ if (pr->image_width > 32767) wide_image = TRUE;
rt_tile_get_region(has_alpha, pr->ignore_alpha,
pr->pixbuf, it->pixbuf, pb_x, pb_y, pb_w, pb_h,
(gdouble) 0.0 - src_y,
scale_x, scale_y,
(fast) ? GDK_INTERP_NEAREST : pr->zoom_quality,
- it->x + pb_x, it->y + pb_y);
+ it->x + pb_x, it->y + pb_y, wide_image);
if (rt->stereo_mode & PR_STEREO_ANAGLYPH &&
(pr->stereo_pixbuf_offset_right > 0 || pr->stereo_pixbuf_offset_left > 0))
{
(gdouble) 0.0 - src_y,
scale_x, scale_y,
(fast) ? GDK_INTERP_NEAREST : pr->zoom_quality,
- it->x + pb_x, it->y + pb_y);
+ it->x + pb_x, it->y + pb_y, wide_image);
pr_create_anaglyph(rt->stereo_mode, it->pixbuf, right_pb, pb_x, pb_y, pb_w, pb_h);
/* do not care about freeing spare_tile, it will be reused */
}
{
gint x1, y1;
gint x2, y2;
- GtkWidget *box;
- GdkWindow *window;
cairo_t *cr;
cairo_surface_t *surface;
cr = cairo_create(rt->surface);
surface = rt->surface;
#else
+ GtkWidget *box;
+ GdkWindow *window;
+
box = GTK_WIDGET(pr);
window = gtk_widget_get_window(box);
}
if (h > 0)
{
- /* FIXME, to optimize this, remove overlap */
+ /** @FIXME to optimize this, remove overlap */
rt_queue(rt,
rt->x_scroll, y_off > 0 ? rt->y_scroll + (pr->vis_height - h) : rt->y_scroll,
pr->vis_width, h, TRUE, TILE_RENDER_ALL, FALSE, FALSE);
rt->surface = gdk_window_create_similar_surface(gtk_widget_get_window(widget), CAIRO_CONTENT_COLOR, gtk_widget_get_allocated_width(widget), gtk_widget_get_allocated_height(widget));
cr = cairo_create(rt->surface);
- cairo_set_source_rgb(cr, (gdouble)options->image.border_color.red /65535, (gdouble)options->image.border_color.green / 65535, (gdouble)options->image.border_color.blue / 65535);
+ cairo_set_source_rgb(cr, (gdouble)rt->pr->color.red / 65535, (gdouble)rt->pr->color.green / 65535, (gdouble)rt->pr->color.blue / 65535);
cairo_paint(cr);
cairo_destroy(cr);
}
GList *work;
OverlayData *od;
- cairo_set_source_surface (cr, rt->surface, 0, 0);
- cairo_paint(cr);
+ if (rt->stereo_mode & (PR_STEREO_HORIZ | PR_STEREO_VERT))
+ {
+ cairo_push_group(cr);
+ cairo_set_source_rgb(cr, (double)rt->pr->color.red / 65535, (double)rt->pr->color.green / 65535, (double)rt->pr->color.blue / 65535);
+
+ if (rt->stereo_mode & PR_STEREO_HORIZ)
+ {
+ cairo_rectangle(cr, rt->stereo_off_x, 0, rt->pr->viewport_width, rt->pr->viewport_height);
+ }
+ else
+ {
+ cairo_rectangle(cr, 0, rt->stereo_off_y, rt->pr->viewport_width, rt->pr->viewport_height);
+ }
+ cairo_clip(cr);
+ cairo_paint(cr);
+
+ cairo_rectangle(cr, rt->pr->x_offset + rt->stereo_off_x, rt->pr->y_offset + rt->stereo_off_y, rt->pr->vis_width, rt->pr->vis_height);
+ cairo_clip(cr);
+ cairo_set_source_surface(cr, rt->surface, 0, 0);
+ cairo_paint(cr);
+
+ cairo_pop_group_to_source(cr);
+ cairo_paint(cr);
+ }
+ else
+ {
+ cairo_set_source_surface(cr, rt->surface, 0, 0);
+ cairo_paint(cr);
+ }
work = rt->overlay_list;
while (work)
rt->f.stereo_set = renderer_stereo_set;
- rt->tile_width = PR_TILE_SIZE;
- rt->tile_height = PR_TILE_SIZE;
+ rt->tile_width = options->image.tile_size;
+ rt->tile_height = options->image.tile_size;
rt->tiles = NULL;
rt->tile_cache_size = 0;