summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/generators.c194
-rw-r--r--src/jpeg-utils.cpp28
-rw-r--r--src/jpeg-utils.h1
-rw-r--r--src/setup.c70
-rw-r--r--src/setup.h14
-rw-r--r--templates/fluid/fluid.xml26
-rw-r--r--templates/fluid/template_album.html6
-rw-r--r--templates/fluid/template_index.html6
8 files changed, 266 insertions, 79 deletions
diff --git a/src/generators.c b/src/generators.c
index 72c51fb..d6984be 100644
--- a/src/generators.c
+++ b/src/generators.c
@@ -21,6 +21,7 @@
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <math.h>
#include <glib.h>
#include <glib/gstdio.h>
@@ -207,7 +208,7 @@ get_image_source_path (TGallerySetup *setup,
if (image_size->is_thumbnail && items->type == GALLERY_TYPE_INDEX)
s = item->thumbnail;
- if (s == NULL && item->image_sizes != NULL)
+ if (s == NULL && ! image_size->is_hidpi && item->image_sizes != NULL)
s = g_hash_table_lookup (item->image_sizes, image_size->name);
}
@@ -239,6 +240,8 @@ get_image_dest_path (TGallerySetup *setup,
g_assert (image_size != NULL);
src = get_image_source_path (setup, items, item, path_info, image_size);
+ if (src == NULL)
+ return NULL;
target_image_dir = g_strdup_printf ("%s%s", TARGET_IMAGE_DIR_PREFIX, image_size->name);
s = g_path_get_basename (src);
@@ -275,7 +278,7 @@ get_image_dest_path_with_fallback (TGallerySetup *setup,
tmp_image_size = image_size;
while ((dst = get_image_dest_path (setup, items, item, path_info, tmp_image_size, FALSE)),
- tmp_image_size->fallback_size && g_access (dst, R_OK) != 0) {
+ tmp_image_size->fallback_size && dst != NULL && g_access (dst, R_OK) != 0) {
g_free (dst);
tmp_image_size = lookup_image_size_for_name (setup, tmp_image_size->fallback_size);
}
@@ -431,63 +434,87 @@ have_album_image_size_cb (gchar **args, gpointer user_data)
}
-/*
- * generate_image: generate needed image sizes
- */
-gboolean
-generate_image (TGallerySetup *setup,
- TAlbum *items,
- TIndexItem *item,
- TPathInfo *path_info,
- gboolean query_update)
+static gboolean
+generate_image_for_size (TGallerySetup *setup,
+ TAlbum *items,
+ TIndexItem *item,
+ TPathInfo *path_info,
+ TImageSize *image_size,
+ gboolean query_update)
{
gboolean res;
gchar *img_src;
gchar *img_dst;
+ gchar *img_ref_dst;
unsigned long img_w, img_h;
unsigned long src_img_w, src_img_h;
unsigned long tmpw, tmph;
+ unsigned long ref_img_w, ref_img_h;
int src_img_quality, img_quality;
- GList *l;
- TImageSize *image_size;
ExifData *exif_data;
-
res = ! query_update;
- for (l = g_list_first (setup->design->image_sizes); l; l = g_list_next (l)) {
- image_size = l->data;
- img_src = get_image_source_path (setup, items, item, path_info, image_size);
- if (img_src == NULL)
- continue;
- if (g_access (img_src, R_OK) != 0) {
- log_error (" Error opening image %s for size \"%s\": %s\n", img_src, image_size->name, g_strerror (errno));
- g_free (img_src);
- res = TRUE;
- continue;
- }
- img_dst = get_image_dest_path (setup, items, item, path_info, image_size, FALSE);
- if (img_dst == NULL) {
- g_free (img_src);
- continue;
- }
+ img_src = get_image_source_path (setup, items, item, path_info, image_size);
+ if (img_src == NULL)
+ return res;
+ if (g_access (img_src, R_OK) != 0) {
+ log_error (" Error opening image %s for size \"%s\": %s\n", img_src, image_size->name, g_strerror (errno));
+ g_free (img_src);
+ return query_update;
+ }
+ img_dst = get_image_dest_path (setup, items, item, path_info, image_size, FALSE);
+ if (img_dst == NULL) {
+ g_free (img_src);
+ return res;
+ }
- exif_data = exif_data_new_empty ();
- metadata_apply_overrides (exif_data, setup, path_info, items, item, image_size);
+ exif_data = exif_data_new_empty ();
+ metadata_apply_overrides (exif_data, setup, path_info, items, item, image_size);
- /* Do something when required */
- res = res || needs_update (img_src, img_dst);
- if (! query_update) {
- /* Always copy supplied image size */
- if (! image_size->is_thumbnail && item->image_sizes && g_hash_table_lookup (item->image_sizes, image_size->name)) {
- if (! copy_file (img_src, img_dst))
- log_error (" Error copying image %s to %s\n", img_src, img_dst);
- }
- /* Resize image */
- else {
- get_image_sizes (img_src, &src_img_w, &src_img_h, &src_img_quality, setup->autorotate);
- if (src_img_w > 0 && src_img_h > 0) {
- img_quality = image_size->quality;
+ /* Do something when required */
+ res = res || needs_update (img_src, img_dst);
+ if (! query_update) {
+ /* Always copy supplied image size */
+ if (! image_size->is_thumbnail && ! image_size->is_hidpi && item->image_sizes && g_hash_table_lookup (item->image_sizes, image_size->name)) {
+ if (! copy_file (img_src, img_dst))
+ log_error (" Error copying image %s to %s\n", img_src, img_dst);
+ }
+ /* Resize image */
+ else {
+ get_image_sizes (img_src, &src_img_w, &src_img_h, &src_img_quality, setup->autorotate);
+ if (src_img_w > 0 && src_img_h > 0) {
+ img_quality = image_size->quality;
+ if (image_size->is_hidpi) {
+ /* Get reference regular size image dimensions */
+ img_ref_dst = get_image_dest_path (setup, items, item, path_info, image_size->hidpi_ref_size, FALSE);
+ if (! img_ref_dst) {
+ g_free (img_src);
+ g_free (img_dst);
+ return res;
+ }
+ ref_img_w = ref_img_h = 0;
+ get_image_sizes (img_ref_dst, &ref_img_w, &ref_img_h, NULL, FALSE);
+ g_free (img_ref_dst);
+ if (ref_img_w <= 0 || ref_img_h <= 0) {
+ g_free (img_src);
+ g_free (img_dst);
+ 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);
+ 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);
+ g_free (img_dst);
+ return res;
+ }
+ if (setup->warn_resize && (img_w > src_img_w || img_h > src_img_h))
+ printf (" Warning: upscaling image %s from %lux%lu to %lux%lu\n", img_src, src_img_w, src_img_h, img_w, img_h);
+
+ } else {
+ /* Not a HiDPI image size */
if (image_size->is_thumbnail && image_size->thumb_crop_style != CROP_STYLE_NORMAL) {
switch (image_size->thumb_crop_style) {
case CROP_STYLE_SQUARED:
@@ -517,7 +544,7 @@ generate_image (TGallerySetup *setup,
/* printf (" 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, tmpw, tmph); */
g_free (img_src);
g_free (img_dst);
- continue;
+ return res;
}
/* Calculate dimensions */
if (src_img_w < tmpw + image_size->no_resize_threshold && src_img_h < tmph + image_size->no_resize_threshold) {
@@ -537,29 +564,66 @@ generate_image (TGallerySetup *setup,
img_quality = src_img_quality;
}
}
+ }
- /* Perform resize and strip */
- stats_images_inc ();
- if (src_img_w == img_w && src_img_h == img_h && src_img_quality == img_quality) {
- 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, 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);
- }
+
+ /* Perform resize and strip */
+ stats_images_inc ();
+ if (src_img_w == img_w && src_img_h == img_h && src_img_quality == img_quality) {
+ if (! copy_file (img_src, img_dst))
+ log_error (" Error copying image %s to %s\n", img_src, img_dst);
} else {
- log_error ("generate_image: image %s sizes are %lux%lu\n", img_src, src_img_w, src_img_h);
+ 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,
+ image_size->is_thumbnail ? setup->design->imgmagick_thumb_opts : setup->design->imgmagick_resize_opts))
+ log_error (" Error resizing image %s\n", img_src);
+ }
+
+ if (setup->warn_resize && image_size->is_hidpi) {
+ get_image_sizes (img_dst, &tmpw, &tmph, NULL, FALSE);
+ if (img_w != tmpw || img_h != tmph)
+ g_print (" Warning: generated image '%s' doesn't have required dimensions: need %lux%lu, got %lux%lu\n", img_dst, img_w, img_h, tmpw, tmph);
}
+ } else {
+ log_error ("generate_image: image %s sizes are %lux%lu\n", img_src, src_img_w, src_img_h);
}
}
- if (! image_size->is_thumbnail) {
- modify_exif (img_dst, exif_data, setup->erase_exif_thumbnail, setup->strip_xmp);
- }
+ }
+ if (! image_size->is_thumbnail) {
+ modify_exif (img_dst, exif_data, setup->erase_exif_thumbnail, setup->strip_xmp);
+ }
- exif_data_free (exif_data);
- g_free (img_src);
- g_free (img_dst);
+ exif_data_free (exif_data);
+ g_free (img_src);
+ g_free (img_dst);
+
+ return res;
+}
+
+/*
+ * generate_image: generate needed image sizes
+ */
+gboolean
+generate_image (TGallerySetup *setup,
+ TAlbum *items,
+ TIndexItem *item,
+ TPathInfo *path_info,
+ gboolean query_update)
+{
+ gboolean res;
+ GList *l;
+ TImageSize *image_size;
+ int i;
+
+ res = ! query_update;
+ for (i = 0; i < 2; i++) {
+ /* process regular sizes first and then hidpi sizes in the second round */
+ for (l = g_list_first (setup->design->image_sizes); l; l = g_list_next (l)) {
+ image_size = l->data;
+ if ((i == 0 && image_size->is_hidpi) || (i == 1 && ! image_size->is_hidpi))
+ continue;
+
+ res = (query_update && res) || generate_image_for_size (setup, items, item, path_info, image_size, query_update);
+ }
}
return res;
}
@@ -872,9 +936,9 @@ process_img_item (TGallerySetup *setup,
struct HaveImageSizeData *img_size_data;
GList *l;
+ album_protected = FALSE;
if (list_mode) {
/* Index stuff */
- album_protected = FALSE;
if (items->type == GALLERY_TYPE_INDEX) {
album_objects_count = 0;
s1 = g_build_filename (path_info->src_dir, item->path, "index.xml", NULL);
@@ -934,7 +998,7 @@ process_img_item (TGallerySetup *setup,
tmp_image_size = l->data;
if (! all_image_sizes && tmp_image_size != image_size)
continue;
- if (tmp_image_size->is_thumbnail)
+ if ((items->type == GALLERY_TYPE_ALBUM && tmp_image_size->is_thumbnail) || (items->type == GALLERY_TYPE_INDEX && ! tmp_image_size->is_thumbnail) || album_protected)
continue;
/* First calculate image paths */
if (all_image_sizes) {
diff --git a/src/jpeg-utils.cpp b/src/jpeg-utils.cpp
index aaf59fc..d7134c2 100644
--- a/src/jpeg-utils.cpp
+++ b/src/jpeg-utils.cpp
@@ -507,6 +507,7 @@ resize_image (const gchar *src, const gchar *dst,
int quality,
gboolean thumbnail,
gboolean autorotate,
+ gboolean hidpi_strict_dimensions,
ExifData *exif,
gchar *resize_opts)
{
@@ -539,7 +540,7 @@ resize_image (const gchar *src, const gchar *dst,
autorotate_image (magick_wand);
/* Don't resize if smaller than desired size */
- if (MagickGetImageWidth (magick_wand) > size_x || MagickGetImageHeight (magick_wand) > size_y)
+ if (hidpi_strict_dimensions || MagickGetImageWidth (magick_wand) > size_x || MagickGetImageHeight (magick_wand) > size_y)
{
/* Prepare image before resizing */
if (thumbnail) {
@@ -587,8 +588,29 @@ resize_image (const gchar *src, const gchar *dst,
}
}
+ /* Shave the source image to match exact dimensions after resize */
+ if (hidpi_strict_dimensions && (! thumbnail || exif->thumbnail_crop_style == CROP_STYLE_NORMAL)) {
+ w = MagickGetImageWidth (magick_wand);
+ h = MagickGetImageHeight (magick_wand);
+ source_aspect = (double) w / (double) h;
+ target_aspect = (double) size_x / (double) size_y;
+ if (source_aspect != target_aspect) {
+ if (target_aspect >= source_aspect) {
+ new_w = w;
+ new_h = lround ((double) w / target_aspect);
+ } else {
+ new_w = lround ((double) h * target_aspect);
+ new_h = h;
+ }
+ MagickCropImage (magick_wand, new_w, new_h, (w - new_w) / 2, (h - new_h) / 2);
+ g_warn_if_fail (MagickGetImageWidth (magick_wand) == new_w);
+ g_warn_if_fail (MagickGetImageHeight (magick_wand) == new_h);
+ }
+ }
+
if (resize_opts == NULL) {
/* Perform internal resizing */
+ /* Note: MagickResizeImage() does no aspect correction, stretching the image to the required dimensions */
if (thumbnail) {
MagickThumbnailImage (magick_wand, size_x, size_y);
} else {
@@ -682,8 +704,8 @@ get_image_sizes (const gchar *img,
ExceptionType severity;
gchar *description;
- *width = -1;
- *height = -1;
+ *width = 0;
+ *height = 0;
if (quality)
*quality = -1;
diff --git a/src/jpeg-utils.h b/src/jpeg-utils.h
index e23dee7..d0664c9 100644
--- a/src/jpeg-utils.h
+++ b/src/jpeg-utils.h
@@ -100,6 +100,7 @@ gboolean resize_image (const gchar *src, const gchar *dst,
int quality,
gboolean thumbnail,
gboolean autorotate,
+ gboolean hidpi_strict_dimensions,
ExifData *exif,
gchar *resize_opts);
diff --git a/src/setup.c b/src/setup.c
index 9780807..cf23044 100644
--- a/src/setup.c
+++ b/src/setup.c
@@ -155,6 +155,35 @@ image_sizes_compare_func (TImageSize *a, TImageSize *b)
return sa - sb;
}
+static gdouble *
+parse_hidpi_sizes (const gchar *s)
+{
+ gchar **split;
+ GArray *arr;
+ gchar *s2;
+ int i;
+ gdouble f;
+
+ if (! s || strlen (s) == 0)
+ return NULL;
+
+ arr = g_array_new (TRUE, TRUE, sizeof (gdouble));
+ split = g_strsplit (s, ",", -1);
+
+ for (i = 0; split[i] != NULL; i++) {
+ s2 = g_strstrip (split[i]);
+ if (s2[strlen(s2) - 1] != 'x')
+ continue;
+ s2[strlen(s2) - 1] = '\0';
+ f = g_ascii_strtod (s2, NULL);
+ g_array_append_val (arr, f);
+ }
+ g_strfreev (split);
+
+ return (gdouble *) g_array_free (arr, FALSE);
+}
+
+
/*
* parse_design_setup_xml: XML parser for design.xml file
*/
@@ -166,7 +195,7 @@ parse_design_setup_xml (const gchar *filename)
gchar *s2;
gchar *s3;
TGalleryDesign *design;
- TImageSize *image_size;
+ TImageSize *image_size, *hidpi_image_size;
TGalleryDesignTheme *theme;
int count, c;
int i, j;
@@ -202,6 +231,17 @@ parse_design_setup_xml (const gchar *filename)
}
+ /* hidpi section */
+ if (xml_file_get_node_attribute_boolean_with_default (xml, "/design_setup/hidpi", "enabled", FALSE)) {
+ design->hidpi_upscale_threshold = xml_file_get_node_attribute_long_with_default (xml, "/design_setup/hidpi/threshold", "upscale", DEFAULT_UPSCALE_THRESHOLD);
+ s = xml_file_get_node_value (xml, "/design_setup/hidpi/sizes/text()");
+ design->hidpi_sizes = parse_hidpi_sizes (s);
+ g_free (s);
+ design->hidpi_quality = xml_file_get_node_attribute_long_with_default (xml, "/design_setup/hidpi/quality", "value", -1);
+ design->hidpi_thumbnail_quality = xml_file_get_node_attribute_long_with_default (xml, "/design_setup/hidpi/quality", "thumbnail", -1);
+ }
+
+
/* image_sizes section */
count = xml_file_node_get_children_count (xml, "/design_setup/image_sizes/size");
for (i = 0; i < count; i++) {
@@ -268,6 +308,33 @@ parse_design_setup_xml (const gchar *filename)
image_size->quality_threshold = xml_file_get_node_attribute_long_with_default (xml, s, "quality", DEFAULT_QUALITY_THRESHOLD);
g_free (s);
+ /* Generate HiDPI sizes */
+ if (design->hidpi_sizes)
+ for (j = 0; design->hidpi_sizes[j] != 0; j++ ) {
+ hidpi_image_size = g_malloc0 (sizeof (TImageSize));
+ memcpy (hidpi_image_size, image_size, sizeof (TImageSize));
+ hidpi_image_size->is_hidpi = TRUE;
+ hidpi_image_size->hidpi_scale_factor = design->hidpi_sizes[j];
+ hidpi_image_size->hidpi_ref_size = image_size;
+ hidpi_image_size->tagname = NULL;
+ hidpi_image_size->fallback_size = NULL;
+ hidpi_image_size->quality_threshold = 0;
+ 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);
+ 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)
+ hidpi_image_size->quality = design->hidpi_thumbnail_quality;
+ design->image_sizes = g_list_append (design->image_sizes, hidpi_image_size);
+ }
}
design->image_sizes = g_list_sort (design->image_sizes, (GCompareFunc) image_sizes_compare_func);
@@ -676,6 +743,7 @@ free_design_setup_data (TGalleryDesign *design)
g_strfreev (design->supplemental_files);
g_free (design->imgmagick_resize_opts);
g_free (design->imgmagick_thumb_opts);
+ g_free (design->hidpi_sizes);
g_free (design);
}
}
diff --git a/src/setup.h b/src/setup.h
index c11efed..730c035 100644
--- a/src/setup.h
+++ b/src/setup.h
@@ -25,11 +25,13 @@ G_BEGIN_DECLS
#define DEFAULT_INDEX_FILENAME "index.html"
#define THUMBNAIL_NAME_FORMAT "%.3d_%s"
+#define HIDPI_NAME_FORMAT "%s_hidpi_%gx"
#define TARGET_IMAGE_DIR_PREFIX "_"
#define DEFAULT_NO_RESIZE_THRESHOLD 1
#define DEFAULT_AVAILABILITY_THRESHOLD 1
#define DEFAULT_QUALITY_THRESHOLD 5
+#define DEFAULT_UPSCALE_THRESHOLD 33
#define SETUP_XML "setup.xml"
#define SETUP_V2_XML "setup2.xml"
@@ -38,6 +40,7 @@ G_BEGIN_DECLS
/* forward declaration */
typedef struct TGalleryDesign TGalleryDesign;
+typedef struct TImageSize TImageSize;
/* Global gallery setup */
typedef struct {
@@ -96,7 +99,7 @@ typedef enum {
CROP_STYLE_FIXED
} TCropStyle;
-typedef struct {
+struct TImageSize {
gchar *name;
gchar *tagname;
gboolean is_thumbnail;
@@ -112,8 +115,11 @@ typedef struct {
int no_resize_threshold;
int availability_threshold;
int quality_threshold;
+ gboolean is_hidpi;
+ gdouble hidpi_scale_factor;
+ TImageSize *hidpi_ref_size;
TCropStyle thumb_crop_style;
-} TImageSize;
+};
typedef struct {
gboolean enabled;
@@ -139,6 +145,10 @@ struct TGalleryDesign {
gchar **supplemental_files;
gchar *imgmagick_resize_opts;
gchar *imgmagick_thumb_opts;
+ int hidpi_upscale_threshold;
+ gdouble *hidpi_sizes;
+ int hidpi_quality;
+ int hidpi_thumbnail_quality;
};
diff --git a/templates/fluid/fluid.xml b/templates/fluid/fluid.xml
index 376d56d..ff4baee 100644
--- a/templates/fluid/fluid.xml
+++ b/templates/fluid/fluid.xml
@@ -31,6 +31,26 @@
</size>
</image_sizes>
+ <!-- Global HiDPI settings -->
+ <!-- For each defined image size new HiDPI image sizes will be generated
+ automatically. Means the resulting HiDPI image files will have their own
+ subdirectory and all existing template macros are available as well.
+ The resulting image size name will be of format "SIZE_NAME_HIDPI_1.5X"
+ where SIZE_NAME is name of the reference image size and "1.5X" is the
+ particular size factor. -->
+ <hidpi enabled="yes">
+ <!-- Specify requested size factors, separated by comma (typically '2x'
+ or '1.5x, 2x'). -->
+ <sizes>2x</sizes>
+ <!-- Optionally allow upscaling. Represents a percentage how much smaller
+ image can still be used for upscaling. Set to 0 to disable upscaling
+ completely. -->
+ <threshold upscale="33" />
+ <!-- Compression artifacts may be less noticeable since the actual pixel
+ pitch is smaller. Lower the compression quality to save bandwidth. -->
+ <quality value="90" thumbnail="60" />
+ </hidpi>
+
<resize>
<!-- Use this section to tweak resizing methods. For the moment ImageMagick
is the only supported method, being used from the beginning of the project,
@@ -42,8 +62,10 @@
arguments defining target dimensions. For the rest of arguments
standard convert(1) command syntax is used. -->
<!-- In case an option string is empty, internal defaults are used. -->
- <resize_options>-set option:filter:blur 0.6 -filter Gaussian -thumbnail ${WIDTH}x${HEIGHT}</resize_options>
- <thumbnail_options>-set option:filter:blur 0.6 -filter Gaussian -thumbnail ${WIDTH}x${HEIGHT}</thumbnail_options>
+ <!-- Please see http://www.imagemagick.org/Usage/resize/#resize for resize
+ modifiers (e.g. we use the '!' flag to correct off-by-one errors). -->
+ <resize_options>-set option:filter:blur 0.6 -filter Gaussian -resize ${WIDTH}x${HEIGHT}!</resize_options>
+ <thumbnail_options>-set option:filter:blur 0.6 -filter Gaussian -thumbnail ${WIDTH}x${HEIGHT}!</thumbnail_options>
</ImageMagick>
</resize>
diff --git a/templates/fluid/template_album.html b/templates/fluid/template_album.html
index 721fc15..dbfb8d5 100644
--- a/templates/fluid/template_album.html
+++ b/templates/fluid/template_album.html
@@ -61,9 +61,9 @@
<div class="photo" id="photo-$(ITEM_INDEX)">
<div class="position_marker" id="i$(ITEM_INDEX)"></div>
<picture>
- <!-- $(ifdef(HAVE_IMG_SIZE_HIRES)) --><source media="(min-width: 2100px)" srcset="$(IMG_SRC__HIRES)"><!-- $(endif(HAVE_IMG_SIZE_HIRES)) -->
- <!-- $(ifdef(HAVE_IMG_SIZE_ORIGINAL)) --><source media="(min-width: 1600px)" srcset="$(IMG_SRC__ORIGINAL)"><!-- $(endif(HAVE_IMG_SIZE_ORIGINAL)) -->
- <source media="(max-width: 1600px)" srcset="$(IMG_SRC)">
+ <!-- $(ifdef(HAVE_IMG_SIZE_HIRES)) --><source media="(min-width: 2100px)" srcset="$(IMG_SRC__HIRES)$(ifdef(HAVE_IMG_SIZE_HIRES_HIDPI_1.5X)), $(IMG_SRC__HIRES_HIDPI_1.5X) 1.5x$(endif(HAVE_IMG_SIZE_HIRES_HIDPI_1.5X))$(ifdef(HAVE_IMG_SIZE_HIRES_HIDPI_2X)), $(IMG_SRC__HIRES_HIDPI_2X) 2x$(endif(HAVE_IMG_SIZE_HIRES_HIDPI_2X))"><!-- $(endif(HAVE_IMG_SIZE_HIRES)) -->
+ <!-- $(ifdef(HAVE_IMG_SIZE_ORIGINAL)) --><source media="(min-width: 1600px)" srcset="$(IMG_SRC__ORIGINAL)$(ifdef(HAVE_IMG_SIZE_ORIGINAL_HIDPI_1.5X)), $(IMG_SRC__ORIGINAL_HIDPI_1.5X) 1.5x$(endif(HAVE_IMG_SIZE_ORIGINAL_HIDPI_1.5X))$(ifdef(HAVE_IMG_SIZE_ORIGINAL_HIDPI_2X)), $(IMG_SRC__ORIGINAL_HIDPI_2X) 2x$(endif(HAVE_IMG_SIZE_ORIGINAL_HIDPI_2X))"><!-- $(endif(HAVE_IMG_SIZE_ORIGINAL)) -->
+ <source media="(max-width: 1600px)" srcset="$(IMG_SRC)$(ifdef(HAVE_IMG_SIZE_PREVIEW_HIDPI_1.5X)), $(IMG_SRC__PREVIEW_HIDPI_1.5X) 1.5x$(endif(HAVE_IMG_SIZE_PREVIEW_HIDPI_1.5X))$(ifdef(HAVE_IMG_SIZE_PREVIEW_HIDPI_2X)), $(IMG_SRC__PREVIEW_HIDPI_2X) 2x$(endif(HAVE_IMG_SIZE_PREVIEW_HIDPI_2X))">
<img src="$(IMG_SRC)" width="$(IMG_SIZE_W)" height="$(IMG_SIZE_H)" alt="" id="$(value(BORDER_STYLE))"/>
</picture>
<div class="photo-content">
diff --git a/templates/fluid/template_index.html b/templates/fluid/template_index.html
index 74833dd..d0b6e8b 100644
--- a/templates/fluid/template_index.html
+++ b/templates/fluid/template_index.html
@@ -42,8 +42,8 @@
<div class="albums">
<!-- $(BEGIN_IMG_LIST) -->
- <!-- $(BEGIN_LIST_PICTURE) -->
- <div class="index_item" style="background-image:url($(IMG_SRC_THUMB))">
+ <!-- $(BEGIN_LIST_PICTURE_ALL_SIZES) -->
+ <div class="index_item" style="background-image:url($(IMG_SRC_THUMB)); background-image:image-set(url($(IMG_SRC_THUMB)) 1x$(ifdef(HAVE_IMG_SIZE_THUMBNAIL_HIDPI_1.5X)), url($(IMG_SRC__THUMBNAIL_HIDPI_1.5X)) 1.5x$(endif(HAVE_IMG_SIZE_THUMBNAIL_HIDPI_1.5X))$(ifdef(HAVE_IMG_SIZE_THUMBNAIL_HIDPI_2X)), url($(IMG_SRC__THUMBNAIL_HIDPI_2X)) 2x$(endif(HAVE_IMG_SIZE_THUMBNAIL_HIDPI_2X))); background-image:-webkit-image-set(url($(IMG_SRC_THUMB)) 1x$(ifdef(HAVE_IMG_SIZE_THUMBNAIL_HIDPI_1.5X)), url($(IMG_SRC__THUMBNAIL_HIDPI_1.5X)) 1.5x$(endif(HAVE_IMG_SIZE_THUMBNAIL_HIDPI_1.5X))$(ifdef(HAVE_IMG_SIZE_THUMBNAIL_HIDPI_2X)), url($(IMG_SRC__THUMBNAIL_HIDPI_2X)) 2x$(endif(HAVE_IMG_SIZE_THUMBNAIL_HIDPI_2X))); background-image:-moz-image-set(url($(IMG_SRC_THUMB)) 1x$(ifdef(HAVE_IMG_SIZE_THUMBNAIL_HIDPI_1.5X)), url($(IMG_SRC__THUMBNAIL_HIDPI_1.5X)) 1.5x$(endif(HAVE_IMG_SIZE_THUMBNAIL_HIDPI_1.5X))$(ifdef(HAVE_IMG_SIZE_THUMBNAIL_HIDPI_2X)), url($(IMG_SRC__THUMBNAIL_HIDPI_2X)) 2x$(endif(HAVE_IMG_SIZE_THUMBNAIL_HIDPI_2X)));">
<div class="position_marker" id="$(IMG_POS_MARKER)"></div>
<a href="$(ALBUM_SUBPATH)">
<span class="album_text"><!-- $(IMG_TITLE) --></span><br />
@@ -52,7 +52,7 @@
<span class="album_note">(<!-- $(ALBUM_NUM_ITEMS) --> items)</span>
</a>
</div>
- <!-- $(END_LIST_PICTURE) -->
+ <!-- $(END_LIST_PICTURE_ALL_SIZES) -->
<!-- $(BEGIN_LIST_SEPARATOR) -->
<div class="separator"><!-- $(LIST_SEPARATOR_TITLE) --></div>
<!-- $(END_LIST_SEPARATOR) -->