diff options
| -rw-r--r-- | src/generators.c | 322 | ||||
| -rw-r--r-- | src/items.c | 19 | ||||
| -rw-r--r-- | src/items.h | 5 | ||||
| -rw-r--r-- | src/jpeg-utils.cpp | 8 | ||||
| -rw-r--r-- | src/jpeg-utils.h | 1 | ||||
| -rw-r--r-- | src/setup.c | 17 | ||||
| -rw-r--r-- | src/setup.h | 8 | ||||
| -rw-r--r-- | templates/classic/default.xml | 99 | ||||
| -rw-r--r-- | templates/fluid/fluid.xml | 6 |
9 files changed, 301 insertions, 184 deletions
diff --git a/src/generators.c b/src/generators.c index 1ecb3c6..b9df04c 100644 --- a/src/generators.c +++ b/src/generators.c @@ -186,80 +186,107 @@ get_item_titles (TGallerySetup *setup, *title_desc = g_strstrip (*title_desc); } -static void -get_image_paths (TGallerySetup *setup, - TAlbum *items, - TIndexItem *item, - TPathInfo *path_info, - TImageSize *image_size, - gchar **full_img_src, - gchar **full_img_dst, - gchar **page_img_dst) +static gchar * +get_image_source_path (TGallerySetup *setup, + TAlbum *items, + TIndexItem *item, + TPathInfo *path_info, + TImageSize *image_size) { - gchar *s1, *s2, *s3; - gchar *target_image_dir; - - if (full_img_src) - *full_img_src = NULL; - if (full_img_dst) - *full_img_dst = NULL; - if (page_img_dst) - *page_img_dst = NULL; - - if (full_img_src == NULL && image_size == NULL) - return; + const gchar *s; - s1 = NULL; + s = NULL; /* image_size == NULL means return real image source path */ if (image_size) { /* ignore combinations that are not valid */ if ((items->type == GALLERY_TYPE_INDEX && ! image_size->is_thumbnail) || (image_size->is_thumbnail && item->hidden) || (image_size->is_thumbnail && items->type == GALLERY_TYPE_INDEX && (item->thumbnail == NULL || strlen (item->thumbnail) == 0))) - return; + return NULL; if (image_size->is_thumbnail && items->type == GALLERY_TYPE_INDEX) - s1 = item->thumbnail; + s = item->thumbnail; - if (s1 == NULL && item->image_sizes != NULL) - s1 = g_hash_table_lookup (item->image_sizes, image_size->name); - - /* go through the fallback */ - while (s1 == NULL && image_size->fallback_size != NULL) { - image_size = lookup_image_size_for_name (setup, image_size->fallback_size); - s1 = item->image_sizes ? g_hash_table_lookup (item->image_sizes, image_size->name) : NULL; - } + if (s == NULL && item->image_sizes != NULL) + s = g_hash_table_lookup (item->image_sizes, image_size->name); } - /* we have reached our target image size, s1 == NULL means the image should be resized from the source image */ - if (s1 == NULL) - s1 = item->path; + /* we have reached our target image size, s == NULL means the image should be resized from the source image */ + if (s == NULL) + s = item->path; - if (s1 == NULL) { + if (s == NULL) { log_error ("Unable to find image source for item #%d (\"%s\") for image size \"%s\"\n", get_item_index (items, item), item->title, image_size->name); - return; + return NULL; } - if (full_img_src) - *full_img_src = g_build_filename (path_info->src_dir, s1, NULL); + return g_build_filename (path_info->src_dir, s, NULL); +} - if (image_size) { - target_image_dir = g_strdup_printf ("%s%s", TARGET_IMAGE_DIR_PREFIX, image_size->name); - s2 = g_path_get_basename (s1); - if (image_size->is_thumbnail) { - s3 = g_strdup_printf (THUMBNAIL_NAME_FORMAT, get_item_index (items, item), s2); - g_free (s2); - s2 = s3; - } - if (full_img_dst) - *full_img_dst = g_build_filename (path_info->dest_dir, target_image_dir, s2, NULL); - if (page_img_dst) - *page_img_dst = g_build_filename (target_image_dir, s2, NULL); - g_free (s2); - g_free (target_image_dir); +static gchar * +get_image_dest_path (TGallerySetup *setup, + TAlbum *items, + TIndexItem *item, + TPathInfo *path_info, + TImageSize *image_size, + gboolean page_link) +{ + gchar *src; + gchar *dst; + gchar *s, *s2; + gchar *target_image_dir; + + g_assert (image_size != NULL); + + src = get_image_source_path (setup, items, item, path_info, image_size); + + target_image_dir = g_strdup_printf ("%s%s", TARGET_IMAGE_DIR_PREFIX, image_size->name); + s = g_path_get_basename (src); + if (image_size->is_thumbnail) { + s2 = g_strdup_printf (THUMBNAIL_NAME_FORMAT, get_item_index (items, item), s); + g_free (s); + s = s2; } + if (page_link) + dst = g_build_filename (target_image_dir, s, NULL); + else + dst = g_build_filename (path_info->dest_dir, target_image_dir, s, NULL); + + g_free (s); + g_free (target_image_dir); + g_free (src); + + return dst; } +static gchar * +get_image_dest_path_with_fallback (TGallerySetup *setup, + TAlbum *items, + TIndexItem *item, + TPathInfo *path_info, + TImageSize *image_size, + gboolean page_link) +{ + gchar *dst; + TImageSize *tmp_image_size; + + if (image_size->fallback_size == NULL) + return get_image_dest_path (setup, items, item, path_info, image_size, page_link); + + 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) { + g_free (dst); + tmp_image_size = lookup_image_size_for_name (setup, tmp_image_size->fallback_size); + } + + if (page_link) { + g_free (dst); + dst = get_image_dest_path (setup, items, item, path_info, tmp_image_size, page_link); + } + + return dst; +} static void metadata_apply_overrides (ExifData *exif_data, @@ -330,40 +357,61 @@ struct HaveImageSizeData { TGallerySetup *setup; TAlbum *items; TIndexItem *item; + TPathInfo *path_info; }; static gboolean +have_generated_image (TGallerySetup *setup, + TAlbum *items, + TIndexItem *item, + TPathInfo *path_info, + TImageSize *image_size) +{ + gchar *img_dst; + int res; + + img_dst = get_image_dest_path (setup, items, item, path_info, image_size, FALSE); + if (img_dst == NULL) + return FALSE; + res = g_access (img_dst, R_OK); + g_free (img_dst); + + return (res == 0); +} + +static gboolean have_image_size_cb (gchar **args, gpointer user_data) { struct HaveImageSizeData *data = user_data; + TImageSize *image_size; g_return_val_if_fail (g_strv_length (args) != 2, FALSE); /* incl. trailing NULL */ /* no image size of that name available */ - if (! lookup_image_size_for_name (data->setup, *args)) + image_size = lookup_image_size_for_name (data->setup, *args); + if (image_size == NULL) return FALSE; if (data->item->image_sizes && g_hash_table_lookup (data->item->image_sizes, *args)) return TRUE; - /* FIXME: rework this */ -/* if (data->item->path) - return TRUE; */ - - return FALSE; + /* check for generated image */ + return have_generated_image (data->setup, data->items, data->item, data->path_info, image_size); } static gboolean have_album_image_size_cb (gchar **args, gpointer user_data) { struct HaveImageSizeData *data = user_data; + TImageSize *image_size; TIndexItem *iter_item; int i; g_return_val_if_fail (g_strv_length (args) != 2, FALSE); /* incl. trailing NULL */ /* no image size of that name available */ - if (! lookup_image_size_for_name (data->setup, *args)) + image_size = lookup_image_size_for_name (data->setup, *args); + if (image_size == NULL) return FALSE; for (i = 0; i < data->items->items->len; i++) { @@ -374,9 +422,9 @@ have_album_image_size_cb (gchar **args, gpointer user_data) if (iter_item->image_sizes && g_hash_table_lookup (iter_item->image_sizes, *args)) return TRUE; - /* FIXME: rework this */ -/* if (iter_item->path) - return TRUE; */ + /* check for generated image */ + if (have_generated_image (data->setup, data->items, iter_item, data->path_info, image_size)) + return TRUE; } return FALSE; @@ -399,6 +447,7 @@ generate_image (TGallerySetup *setup, unsigned long img_w, img_h; unsigned long src_img_w, src_img_h; unsigned long tmpw, tmph; + int src_img_quality, img_quality; GList *l; TImageSize *image_size; ExifData *exif_data; @@ -408,19 +457,20 @@ generate_image (TGallerySetup *setup, for (l = g_list_first (setup->design->image_sizes); l; l = g_list_next (l)) { image_size = l->data; - /* fallback mode, don't generate any image and use different image size */ - if (image_size->fallback_size != NULL && (item->image_sizes == NULL || g_hash_table_lookup (item->image_sizes, image_size->name) == NULL)) + img_src = get_image_source_path (setup, items, item, path_info, image_size); + if (img_src == NULL) continue; - - get_image_paths (setup, items, item, path_info, image_size, &img_src, &img_dst, NULL); - if (img_src == NULL || img_dst == 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; + } exif_data = exif_data_new_empty (); metadata_apply_overrides (exif_data, setup, path_info, items, item, image_size); @@ -428,17 +478,16 @@ generate_image (TGallerySetup *setup, /* Do something when required */ res = res || needs_update (img_src, img_dst); if (! query_update) { - /* Determine whether to perform file copy or resize */ - if (! image_size->is_thumbnail && image_size->no_resize && (! item->image_sizes || (item->image_sizes && g_hash_table_lookup (item->image_sizes, image_size->name)))) { + /* 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, setup->autorotate); + 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) { - stats_images_inc (); - + img_quality = image_size->quality; if (image_size->is_thumbnail && image_size->thumb_crop_style != CROP_STYLE_NORMAL) { switch (image_size->thumb_crop_style) { case CROP_STYLE_SQUARED: @@ -463,14 +512,41 @@ generate_image (TGallerySetup *setup, tmpw = image_size->portrait_width; tmph = image_size->portrait_height; } - calculate_sizes (tmpw, tmph, &img_w, &img_h); + /* Check for image size suitability */ + if (! image_size->is_thumbnail && src_img_w + image_size->availability_threshold < tmpw && src_img_h + image_size->availability_threshold < tmph) { +/* 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; + } + /* Calculate dimensions */ + if (src_img_w < tmpw + image_size->no_resize_threshold && src_img_h < tmph + image_size->no_resize_threshold) { +/* printf (" Note: image %s dimensions (%lux%lu) are within bounds (%lux%lu..%lux%lu), passing by...\n", + img_src, src_img_w, src_img_h, tmpw - image_size->availability_threshold, tmph - image_size->availability_threshold, + tmpw + image_size->no_resize_threshold, tmph + image_size->no_resize_threshold); */ + } else { + calculate_sizes (tmpw, tmph, &img_w, &img_h); + 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); + } + /* Calculate compression quality */ + if (src_img_quality >= image_size->quality + image_size->quality_threshold) { + if (setup->warn_resize) + printf (" Warning: lowering compression quality of %s from %d to %d\n", img_src, src_img_quality, img_quality); + } else { + img_quality = src_img_quality; + } } /* Perform resize and strip */ - if (setup->warn_resize && ! image_size->is_thumbnail) - printf (" Warning: resizing image %s from %lux%lu to %lux%lu\n", img_src, src_img_w, src_img_h, img_w, img_h); - if (! resize_image (img_src, img_dst, img_w, img_h, image_size->quality, image_size->is_thumbnail, setup->autorotate, exif_data)) - log_error (" Error resizing image %s\n", img_src); + 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)) + log_error (" Error resizing image %s\n", img_src); + } } else { log_error ("generate_image: image %s sizes are %lux%lu\n", img_src, src_img_w, src_img_h); } @@ -671,7 +747,6 @@ add_next_prev_links (TGallerySetup *setup, int item_index; int i; gchar *s; - gchar *preload_imgname; item_index = get_item_index (items, item); for (i = item_index - 2; i >= 0; i--) { @@ -705,10 +780,11 @@ add_next_prev_links (TGallerySetup *setup, else replace_table_add_key (replace_table, "LINK_PREV", get_index_filename (items, theme, NULL, NULL)); - if (next_item != NULL && setup->preload && image_size != NULL) { - get_image_paths (setup, items, next_item, path_info, image_size, NULL, NULL, &preload_imgname); - } - replace_table_add_key (replace_table, "IMG_SRC_PRELOAD", preload_imgname ? preload_imgname : ""); + s = NULL; + if (next_item != NULL && setup->preload && image_size != NULL) + s = get_image_dest_path_with_fallback (setup, items, next_item, path_info, image_size, TRUE); + replace_table_add_key (replace_table, "IMG_SRC_PRELOAD", s ? s : ""); + g_free (s); } static ExifData * @@ -719,7 +795,7 @@ get_img_exif_data (TGallerySetup *setup, TImageSize *image_size) { ExifData *exif; - gchar *img_orig_src; + gchar *img_src; gchar *img_dst; gchar *s; @@ -735,31 +811,29 @@ get_img_exif_data (TGallerySetup *setup, /* Get EXIF data from the source image */ if (exif == NULL) { - img_orig_src = NULL; - get_image_paths (setup, items, item, path_info, NULL, &img_orig_src, NULL, NULL); - if (img_orig_src != NULL && g_access (img_orig_src, R_OK) == 0) - exif = read_exif (img_orig_src); + img_src = get_image_source_path (setup, items, item, path_info, NULL); + if (img_src != NULL && g_access (img_src, R_OK) == 0) + exif = read_exif (img_src); /* -- silently succeed if (exif == NULL) log_error ("write_html_image: error getting exif data from file \"%s\"\n", img_orig_src); */ - g_free (img_orig_src); + g_free (img_src); } + /* Try supplied image file */ + if (exif == NULL && item->image_sizes != NULL) { + img_src = get_image_source_path (setup, items, item, path_info, image_size); + if (img_src != NULL && g_access (img_src, R_OK) == 0) + exif = read_exif (img_src); + g_free (img_src); + } /* Try destination image size instead, though it might have the metadata stripped */ if (exif == NULL) { - img_orig_src = img_dst = NULL; - get_image_paths (setup, items, item, path_info, image_size, &img_orig_src, &img_dst, NULL); - if (img_orig_src != NULL && g_access (img_orig_src, R_OK) == 0) - exif = read_exif (img_orig_src); - if (exif == NULL && img_dst != NULL && g_access (img_dst, R_OK) == 0) + img_dst = get_image_dest_path (setup, items, item, path_info, image_size, FALSE); + if (img_dst != NULL && g_access (img_dst, R_OK) == 0) exif = read_exif (img_dst); - /* -- silently succeed - if (exif == NULL) - log_error ("write_html_image: error getting exif data from file \"%s\"\n", img_dst); - */ g_free (img_dst); - g_free (img_orig_src); } if (exif != NULL) @@ -790,10 +864,8 @@ process_img_item (TGallerySetup *setup, gchar *s1, *s2, *s3, *s4; gchar *img_dst; gchar *img_dst_page; - gchar *img_orig_dst; - gchar *img_orig_dst_page; gchar *title, *title_desc; - TImageSize *orig_image_size; + TImageSize *tmp_image_size; ExifData *exif = NULL; struct HaveImageSizeData *img_size_data; @@ -822,12 +894,13 @@ process_img_item (TGallerySetup *setup, g_free (s1); } else { - get_image_paths (setup, items, item, path_info, thumb_image_size, NULL, &s2, &s3); + s2 = get_image_dest_path (setup, items, item, path_info, thumb_image_size, FALSE); + s3 = get_image_dest_path (setup, items, item, path_info, thumb_image_size, TRUE); } img_thumb_w = img_thumb_h = 0; if (s2 != NULL) - get_image_sizes (s2, &img_thumb_w, &img_thumb_h, setup->autorotate); + get_image_sizes (s2, &img_thumb_w, &img_thumb_h, NULL, setup->autorotate); if (img_thumb_w == img_thumb_h) replace_table_add_key (replace_table, "THUMB_ORIENTATION", "squared"); @@ -856,36 +929,35 @@ process_img_item (TGallerySetup *setup, /* Image stuff */ if (image_size != NULL) { /* First calculate image paths */ - img_dst = img_dst_page = NULL; - get_image_paths (setup, items, item, path_info, image_size, NULL, &img_dst, &img_dst_page); + img_dst = get_image_dest_path_with_fallback (setup, items, item, path_info, image_size, FALSE); + img_dst_page = get_image_dest_path_with_fallback (setup, items, item, path_info, image_size, TRUE); /* Retrieve image sizes */ - get_image_sizes (img_dst, &img_w, &img_h, setup->autorotate); + get_image_sizes (img_dst, &img_w, &img_h, NULL, setup->autorotate); + exif = get_img_exif_data (setup, path_info, items, item, image_size); replace_table_add_key_int (replace_table, "IMG_SIZE_W", img_w); replace_table_add_key_int (replace_table, "IMG_SIZE_H", img_h); replace_table_add_key (replace_table, "IMG_SRC", img_dst_page); - exif = get_img_exif_data (setup, path_info, items, item, image_size); + g_free (img_dst); + g_free (img_dst_page); - /* TODO: legacy stuff, subject to removal */ - orig_image_size = NULL; + /* Legacy stuff, subject to removal */ + tmp_image_size = NULL; /* Take the last image size from the sorted list */ if (g_list_length (setup->design->image_sizes) > 0) - orig_image_size = (TImageSize *) g_list_last (setup->design->image_sizes); - if (orig_image_size != NULL) { - img_orig_dst = img_orig_dst_page = NULL; - get_image_paths (setup, items, item, path_info, orig_image_size, NULL, &img_orig_dst, &img_orig_dst_page); - get_image_sizes (img_orig_dst, &img_orig_w, &img_orig_h, setup->autorotate); + tmp_image_size = (TImageSize *) (g_list_last (setup->design->image_sizes))->data; + if (tmp_image_size != NULL && tmp_image_size != image_size) { + img_dst = get_image_dest_path_with_fallback (setup, items, item, path_info, tmp_image_size, FALSE); + img_dst_page = get_image_dest_path_with_fallback (setup, items, item, path_info, tmp_image_size, TRUE); + get_image_sizes (img_dst, &img_orig_w, &img_orig_h, NULL, setup->autorotate); g_hash_table_replace (defines, g_strdup ("HAVE_FULLSIZE"), g_strdup ("")); replace_table_add_key_int (replace_table, "IMG_SIZE_FULLSIZE_W", img_orig_w); replace_table_add_key_int (replace_table, "IMG_SIZE_FULLSIZE_H", img_orig_h); - replace_table_add_key (replace_table, "IMG_SRC_FULLSIZE", img_orig_dst_page); - g_free (img_orig_dst); - g_free (img_orig_dst_page); + replace_table_add_key (replace_table, "IMG_SRC_FULLSIZE", img_dst_page); + g_free (img_dst); + g_free (img_dst_page); } - - g_free (img_dst); - g_free (img_dst_page); } /* Get title and description from IPTC/EXIF/JPEG if not defined */ @@ -928,8 +1000,9 @@ process_img_item (TGallerySetup *setup, /* Single image size callback */ img_size_data = g_new0 (struct HaveImageSizeData, 1); img_size_data->setup = setup; - img_size_data->item = item; img_size_data->items = items; + img_size_data->item = item; + img_size_data->path_info = path_info; block_parser_register_function (block_parser, "have_image_size", have_image_size_cb, img_size_data, g_free); } @@ -1048,6 +1121,7 @@ write_html_page (TGallerySetup *setup, img_size_data = g_new0 (struct HaveImageSizeData, 1); img_size_data->setup = setup; img_size_data->items = items; + img_size_data->path_info = path_info; block_parser_register_function (block_parser, "have_album_image_size", have_album_image_size_cb, img_size_data, g_free); /* Picture page tags */ diff --git a/src/items.c b/src/items.c index d475f91..0ddc3b1 100644 --- a/src/items.c +++ b/src/items.c @@ -551,6 +551,25 @@ get_child_gallery_type (const gchar *filename) } /* + * dup_path_info: duplicate pathinfo data + */ +TPathInfo * +dup_path_info (TPathInfo *path_info) +{ + TPathInfo *info; + + info = g_malloc0 (sizeof (TPathInfo)); + info->album_path = g_strdup (path_info->album_path); + info->dest_dir = g_strdup (path_info->dest_dir); + info->dest_root = g_strdup (path_info->dest_root); + info->source_root = g_strdup (path_info->source_root); + info->src_dir = g_strdup (path_info->src_dir); + info->templates_root = g_strdup (path_info->templates_root); + + return info; +} + +/* * free_path_info: free allocated pathinfo data */ void diff --git a/src/items.h b/src/items.h index 2d0df59..24a521f 100644 --- a/src/items.h +++ b/src/items.h @@ -127,6 +127,11 @@ void get_album_titles (const gchar *filename, gchar **title, gchar **description TGalleryType get_child_gallery_type (const gchar *filename); /* + * dup_path_info: duplicate pathinfo data + */ +TPathInfo * dup_path_info (TPathInfo *path_info); + +/* * free_path_info: free allocated pathinfo data */ void free_path_info (TPathInfo *path_info); diff --git a/src/jpeg-utils.cpp b/src/jpeg-utils.cpp index ddac2c7..11d2c4e 100644 --- a/src/jpeg-utils.cpp +++ b/src/jpeg-utils.cpp @@ -556,7 +556,8 @@ resize_image (const gchar *src, const gchar *dst, MagickResizeImage (magick_wand, size_x, size_y, LanczosFilter, 1.0); } - MagickSetImageCompressionQuality (magick_wand, quality); + if ((int) MagickGetImageCompressionQuality (magick_wand) != quality) + MagickSetImageCompressionQuality (magick_wand, quality); /* Write the image and destroy it. */ if (MagickWriteImage (magick_wand, dst) == MagickFalse) { @@ -578,6 +579,7 @@ resize_image (const gchar *src, const gchar *dst, void get_image_sizes (const gchar *img, unsigned long *width, unsigned long *height, + int *quality, gboolean autorotate) { MagickWand *magick_wand; @@ -587,6 +589,8 @@ get_image_sizes (const gchar *img, *width = -1; *height = -1; + if (quality) + *quality = -1; g_assert (img != NULL); @@ -610,6 +614,8 @@ get_image_sizes (const gchar *img, *width = MagickGetImageWidth (magick_wand); *height = MagickGetImageHeight (magick_wand); + if (quality) + *quality = (int) MagickGetImageCompressionQuality (magick_wand); magick_wand = DestroyMagickWand (magick_wand); } diff --git a/src/jpeg-utils.h b/src/jpeg-utils.h index 3c56eaf..405d9b0 100644 --- a/src/jpeg-utils.h +++ b/src/jpeg-utils.h @@ -107,6 +107,7 @@ gboolean resize_image (const gchar *src, const gchar *dst, */ void get_image_sizes (const gchar *img, unsigned long *width, unsigned long *height, + int *quality, gboolean autorotate); /* diff --git a/src/setup.c b/src/setup.c index b2cd800..7b59030 100644 --- a/src/setup.c +++ b/src/setup.c @@ -152,7 +152,7 @@ image_sizes_compare_func (TImageSize *a, TImageSize *b) sa = a->landscape_width + a->landscape_height + a->portrait_width + a->portrait_height + a->square_size; sb = b->landscape_width + b->landscape_height + b->portrait_width + b->portrait_height + b->square_size; - return sb - sa; + return sa - sb; } /* @@ -218,10 +218,6 @@ parse_design_setup_xml (const gchar *filename) } g_free (s); - s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/no_resize", i + 1); - image_size->no_resize = xml_file_get_node_present (xml, s); - g_free (s); - s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/landscape", i + 1); image_size->landscape_width = xml_file_get_node_attribute_long_with_default (xml, s, "w", 0); image_size->landscape_height = xml_file_get_node_attribute_long_with_default (xml, s, "h", 0); @@ -248,6 +244,13 @@ parse_design_setup_xml (const gchar *filename) s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/fallback", i + 1); image_size->fallback_size = xml_file_get_node_attribute (xml, s, "size"); g_free (s); + + s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/threshold", i + 1); + image_size->no_resize_threshold = xml_file_get_node_attribute_long_with_default (xml, s, "no_resize", DEFAULT_NO_RESIZE_THRESHOLD); + image_size->availability_threshold = xml_file_get_node_attribute_long_with_default (xml, s, "availability", DEFAULT_AVAILABILITY_THRESHOLD); + image_size->quality_threshold = xml_file_get_node_attribute_long_with_default (xml, s, "quality", DEFAULT_QUALITY_THRESHOLD); + g_free (s); + } design->image_sizes = g_list_sort (design->image_sizes, (GCompareFunc) image_sizes_compare_func); @@ -368,7 +371,9 @@ makeup_legacy_design (const gchar *filename) image_size->portrait_height = xml_file_get_node_attribute_long_with_default (xml, s, "portrait_h", 0); image_size->square_size = xml_file_get_node_attribute_long_with_default (xml, s, "square", 0); image_size->quality = xml_file_get_node_attribute_long_with_default (xml, s, "quality", -1); - image_size->no_resize = (i != 0); + image_size->no_resize_threshold = DEFAULT_NO_RESIZE_THRESHOLD; + image_size->availability_threshold = DEFAULT_AVAILABILITY_THRESHOLD; + image_size->quality_threshold = DEFAULT_QUALITY_THRESHOLD; image_size->is_thumbnail = (i == 0); image_size->thumb_crop_style = ((i == 0) && squared_thumbs) ? CROP_STYLE_SQUARED : CROP_STYLE_NORMAL; g_free (s); diff --git a/src/setup.h b/src/setup.h index faf02f6..54b89b2 100644 --- a/src/setup.h +++ b/src/setup.h @@ -27,6 +27,10 @@ G_BEGIN_DECLS #define THUMBNAIL_NAME_FORMAT "%.3d_%s" #define TARGET_IMAGE_DIR_PREFIX "_" +#define DEFAULT_NO_RESIZE_THRESHOLD 1 +#define DEFAULT_AVAILABILITY_THRESHOLD 1 +#define DEFAULT_QUALITY_THRESHOLD 5 + #define SETUP_XML "setup.xml" #define SETUP_V2_XML "setup2.xml" #define SETUP_NATIVE_VERSION 200 /* 2.0 */ @@ -104,8 +108,10 @@ typedef struct { int crop_width; int crop_height; int quality; - gboolean no_resize; gchar *fallback_size; + int no_resize_threshold; + int availability_threshold; + int quality_threshold; TCropStyle thumb_crop_style; } TImageSize; diff --git a/templates/classic/default.xml b/templates/classic/default.xml index 8cf709e..6db84ee 100644 --- a/templates/classic/default.xml +++ b/templates/classic/default.xml @@ -3,59 +3,69 @@ <!-- image size definitions --> <image_sizes> - <!-- Every image size automatically corresponds to the <item> tag parameter - of the same name in album source files. E.g. image size named "hires" - would correspond to <item hires=".."> tags. Use the image size parameter - "tagname" to override that. --> + <!-- Every item in an album may carry multiple sizes for the particular image. + The base and source image file is specified by the <item src> tag and + should point to the largest available size. This attribute is mandatory + and serves as a source of metadata (e.g. EXIF). Defined image sizes are + then resized from this source image unless a custom image file is supplied. + Custom image may be supplied from the album XML file in form of an extra + attribute of the <item> tag. Image size names are matched automatically + with these attributes. I.e. image size named "hires" would correspond + to <item hires=".."> attribute. Use the image size parameter "tagname" + to override that name. --> + + <!-- Not all image sizes are always available for every album item and themes + should handle that gracefully. Unless a custom image file is supplied + the image is resized from the base image file pointed to by the <item src> + tag given that its dimensions are larger than desired size. Should the + base image dimensions be smaller, the image size is marked as unavailable + for the particular album item. In case of a custom image file is supplied + for the particular image size, no resizing or size checking is performed + at all and the file is simply copied to destination. --> - <!-- "original", "preview" and "thumbnail" sizes are somewhat special here - in order to keep compatibility with previous versions. --> + <!-- The "preview" size is considered default and should be displayed + on a first visit. --> + <size name="preview" tagname="preview"> + <landscape w="1067" h="600" /> + <portrait w="800" h="800" /> + <quality value="95" /> + </size> <!-- Meaning of "original" is shifted here from previous versions; - it's considered more like a bigger preview size for large screens now. - However it still serves the purpose of supplying metadata (EXIF etc.). --> - <!-- Corresponds with mandatory <item src> tag in album source file. --> - <!-- Note that the series of legacy <nofullsize> and <fullsize> tags control - this image size availability on the page. --> + it's independent now and considered more like a bigger image size for + large screens. --> <size name="original"> <landscape w="1200" h="800" /> <portrait w="1024" h="1024" /> <quality value="97" /> - <!-- With the presence of the "no_resize" tag, no resizing will be done and - image file will be copied as is (this is a default for backwards - compatibility). --> - <no_resize /> - <!-- Normally an image is resized to the given dimensions from the original - image when an image is not supplied from the album XML file for the - particular image size. This tag tells the generator to use the fallback - image size instead when an image has not been supplied. Can be freely - combined with the <no_resize /> tags, in that case it only applies - to supplied images. --> - <!-- In case when the "original" size is not available due to the legacy - <nofullsize> tag present, the "preview" size will be used instead. --> + <!-- Thresholds affect resizing and availability. Value units are pixels + or percent (quality only). --> + <!-- The "no_resize" threshold brings size tolerance before performing + resizing. Only applicable when custom image file is not supplied, + source image whose dimensions are larger than defined image size bounds + yet whose difference is smaller than the "no_resize" threshold is + considered usable and no resizing is performed. This is useful to + prevent resizing similarly sized images which brings nasty pixel + distortion effects. --> + <!-- Similarly, the "availability" threshold specifies how much smaller + image can still be considered usable for the particular image size. + No resizing is peformed either case. This is useful mostly for legacy + reasons for images that have not been exported precisely to the + requested dimensions. --> + <!-- The "quality" threshold indicates how much higher JPEG quality value + is tolerated (in percents). --> + <threshold no_resize="10" availability="100" quality="5" /> + <!-- In case no custom image has been supplied and dimensions of the source + image are smaller than required dimensions, a fallback image size might + be used instead. This is useful to prevent missing images on a page, + with the cost of uneven image sizes displayed. --> <fallback size="preview" /> </size> - <!-- The "preview" size is considered default and should be displayed - on a first visit. --> - <size name="preview" tagname="preview"> - <!-- Note that "preview" sizes can be further overriden by album legacy - <images> tag and also per-image by "width"/"height" <item> tag - attributes. Same goes for quality. --> - <landscape w="1067" h="600" /> - <portrait w="800" h="800" /> - <quality value="95" /> - <!-- Similar to the "original" size where the image has to be always supplied, - the image won't get resized only when an image file is supplied by the - <item preview="..."> tag. Otherwise this tag is ignored and image will - be resized from the "original" size (backwards compatibility). - This rule applies also for any other optional image sizes. --> - <no_resize /> - </size> <!-- Thumbnail section is mandatory. --> <!-- The "type" attribute has to be set to "thumbnail" to be treated as such. --> - <!-- Note that thumbnail images are always resized even for custom supplied files. --> + <!-- Note that thumbnail images are always resized even for custom supplied image. --> <!-- An optional "style" attribute affects cropping: * normal - image is resized to fit the dimension limits, maintaining aspect ratio without any crop (default) @@ -70,15 +80,6 @@ <crop w="180" h="120" /> <!-- valid only for the "fixed" crop style --> <quality value="80" /> </size> - - <!-- Here you can define custom sizes which will be generated from the file - defined in <item src> tag. Currently, there's no way how to supply custom - sized images from album source file (might be changed in the future). --> - <size name="mobile"> - <landscape w="320" h="240" /> - <portrait w="240" h="320" /> - <quality value="90" /> - </size> </image_sizes> <!-- Global support files, common files used by several themes. --> diff --git a/templates/fluid/fluid.xml b/templates/fluid/fluid.xml index b4e528b..49e8547 100644 --- a/templates/fluid/fluid.xml +++ b/templates/fluid/fluid.xml @@ -6,15 +6,15 @@ <landscape w="1423" h="800" /> <portrait w="1000" h="1000" /> <quality value="95" /> - <no_resize /> <fallback size="preview" /> + <threshold no_resize="25" availability="155" quality="5" /> </size> <size name="preview" tagname="preview"> <landscape w="1067" h="600" /> <portrait w="800" h="800" /> <quality value="95" /> - <no_resize /> + <threshold no_resize="10" availability="10" quality="5" /> </size> <size name="thumbnail" type="thumbnail" style="fixed"> @@ -26,8 +26,8 @@ <landscape w="1897" h="1067" /> <portrait w="1200" h="1200" /> <quality value="95" /> - <no_resize /> <fallback size="original" /> + <threshold no_resize="20" availability="20" quality="5" /> </size> </image_sizes> |
