From d3cbbd5b8ab09f3023bbe5067a39935495e59847 Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Fri, 20 Sep 2019 20:12:43 +0200 Subject: generators: Force even base image dimensions for fractional HiDPI sizes In case a dimension of the base image is not even and fractional HiDPI size is to be generated, the resulting image size computes to a non-integer values. Rounding in browsers may vary so let's stick with safe values and force even base image dimensions. This may result in slight crop applied before resize, generally imperceptible. Tested on Chromium 69 and Firefox 52. --- src/generators.c | 28 +++++++++++++++++++++++++--- src/jpeg-utils.c | 4 ++-- src/setup.c | 14 +++++++------- 3 files changed, 34 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/generators.c b/src/generators.c index 5d5ba32..64ca08b 100644 --- a/src/generators.c +++ b/src/generators.c @@ -437,6 +437,19 @@ have_album_image_size_cb (gchar **args, gpointer user_data) return FALSE; } +static gboolean +have_fractional_hidpi_size (TGallerySetup *setup) +{ + int i; + double iptr; + + if (setup->design->hidpi_sizes) + for (i = 0; setup->design->hidpi_sizes[i] != 0; i++) + if (modf (setup->design->hidpi_sizes[i], &iptr) != 0.0) + return TRUE; + return FALSE; +} + static gboolean generate_image_for_size (TGallerySetup *setup, @@ -457,6 +470,7 @@ generate_image_for_size (TGallerySetup *setup, int src_img_quality, img_quality; ExifData *exif_data; int shave_amount; + gboolean hidpi_strict_dimensions; res = ! query_update; @@ -476,6 +490,7 @@ generate_image_for_size (TGallerySetup *setup, exif_data = exif_data_new_empty (); metadata_apply_overrides (exif_data, setup, path_info, items, item, image_size); + hidpi_strict_dimensions = image_size->is_hidpi; /* Do something when required */ res = res || needs_update (img_src, img_dst); @@ -515,8 +530,8 @@ generate_image_for_size (TGallerySetup *setup, return res; } /* Browsers need exactly n-factor of the original size */ - img_w = lround ((gdouble) ref_img_w * image_size->hidpi_scale_factor); - img_h = lround ((gdouble) ref_img_h * image_size->hidpi_scale_factor); + img_w = (gdouble) ref_img_w * image_size->hidpi_scale_factor; + img_h = (gdouble) ref_img_h * image_size->hidpi_scale_factor; if ((gdouble) img_w * (100 - setup->design->hidpi_upscale_threshold) / 100 > src_img_w || (gdouble) img_h * (100 - setup->design->hidpi_upscale_threshold) / 100 > src_img_h) { /* g_print (" Warning: source image %s (%lux%lu) is not large enough for the \"%s\" image size (need %lux%lu)\n", img_src, src_img_w, src_img_h, image_size->name, img_w, img_h); */ g_free (img_src); @@ -568,6 +583,13 @@ generate_image_for_size (TGallerySetup *setup, tmpw + image_size->no_resize_threshold, tmph + image_size->no_resize_threshold); */ } else { calculate_sizes (tmpw, tmph, &img_w, &img_h); + /* For HiDPI sizes that are not integer the base image dimensions must be even */ + if ((img_w % 2 != 0 || img_h % 2 != 0) && have_fractional_hidpi_size (setup)) { + img_w = img_w / 2 * 2; + img_h = img_h / 2 * 2; + /* This flag will take care of a convenient crop of the source image before resize based on the aspect ratio difference */ + hidpi_strict_dimensions = TRUE; + } if (setup->warn_resize) printf (" Warning: resizing image %s from %lux%lu to %lux%lu\n", img_src, src_img_w, src_img_h, img_w, img_h); } @@ -588,7 +610,7 @@ generate_image_for_size (TGallerySetup *setup, if (! copy_file (img_src, img_dst)) log_error (" Error copying image %s to %s\n", img_src, img_dst); } else { - if (! resize_image (img_src, img_dst, img_w, img_h, img_quality, image_size->is_thumbnail, setup->autorotate, image_size->is_hidpi, exif_data, + if (! resize_image (img_src, img_dst, img_w, img_h, img_quality, image_size->is_thumbnail, setup->autorotate, hidpi_strict_dimensions, exif_data, image_size->is_thumbnail ? setup->design->imgmagick_thumb_opts : setup->design->imgmagick_resize_opts)) log_error (" Error resizing image %s\n", img_src); } diff --git a/src/jpeg-utils.c b/src/jpeg-utils.c index aa3a1cc..e992bfa 100644 --- a/src/jpeg-utils.c +++ b/src/jpeg-utils.c @@ -549,9 +549,9 @@ resize_image (const gchar *src, const gchar *dst, if (source_aspect != target_aspect) { if (target_aspect >= source_aspect) { new_w = w; - new_h = lround ((double) w / target_aspect); + new_h = (double) w / target_aspect; } else { - new_w = lround ((double) h * target_aspect); + new_w = (double) h * target_aspect; new_h = h; } MagickCropImage (magick_wand, new_w, new_h, (w - new_w) / 2, (h - new_h) / 2); diff --git a/src/setup.c b/src/setup.c index 266c36e..1ff7ae2 100644 --- a/src/setup.c +++ b/src/setup.c @@ -328,13 +328,13 @@ parse_design_setup_xml (const gchar *filename) hidpi_image_size->no_resize_threshold = 0; hidpi_image_size->availability_threshold = 0; hidpi_image_size->name = g_strdup_printf (HIDPI_NAME_FORMAT, image_size->name, hidpi_image_size->hidpi_scale_factor); - hidpi_image_size->landscape_width = lround ((gdouble) image_size->landscape_width * hidpi_image_size->hidpi_scale_factor); - hidpi_image_size->landscape_height = lround ((gdouble) image_size->landscape_height * hidpi_image_size->hidpi_scale_factor); - hidpi_image_size->portrait_width = lround ((gdouble) image_size->portrait_width * hidpi_image_size->hidpi_scale_factor); - hidpi_image_size->portrait_height = lround ((gdouble) image_size->portrait_height * hidpi_image_size->hidpi_scale_factor); - hidpi_image_size->square_size = lround ((gdouble) image_size->square_size * hidpi_image_size->hidpi_scale_factor); - hidpi_image_size->crop_width = lround ((gdouble) image_size->crop_width * hidpi_image_size->hidpi_scale_factor); - hidpi_image_size->crop_height = lround ((gdouble) image_size->crop_height * hidpi_image_size->hidpi_scale_factor); + hidpi_image_size->landscape_width = (gdouble) image_size->landscape_width * hidpi_image_size->hidpi_scale_factor; + hidpi_image_size->landscape_height = (gdouble) image_size->landscape_height * hidpi_image_size->hidpi_scale_factor; + hidpi_image_size->portrait_width = (gdouble) image_size->portrait_width * hidpi_image_size->hidpi_scale_factor; + hidpi_image_size->portrait_height = (gdouble) image_size->portrait_height * hidpi_image_size->hidpi_scale_factor; + hidpi_image_size->square_size = (gdouble) image_size->square_size * hidpi_image_size->hidpi_scale_factor; + hidpi_image_size->crop_width = (gdouble) image_size->crop_width * hidpi_image_size->hidpi_scale_factor; + hidpi_image_size->crop_height = (gdouble) image_size->crop_height * hidpi_image_size->hidpi_scale_factor; if (! hidpi_image_size->is_thumbnail && design->hidpi_quality > 0) hidpi_image_size->quality = design->hidpi_quality; if (hidpi_image_size->is_thumbnail && design->hidpi_thumbnail_quality > 0) -- cgit v1.2.3