From ced9539fef270fe133cb0ad6fc04c30bd5fa2dfe Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Sun, 7 Apr 2013 18:11:42 +0200 Subject: Add ability to specify thumbnail square crop hint In simple crop square mode it's sometimes viable to specify position of the square. This is vastly useful for portrait pictures so that you don't crop the head off the body. --- sample/src/CIAF_1/index.xml | 9 ++++++++- src/generators.c | 15 ++++++++++---- src/items.c | 49 +++++++++++++++++++++++++++++++++++++++------ src/items.h | 13 +++++++++++- src/jpeg-utils.cpp | 25 +++++++++++++++++++---- src/jpeg-utils.h | 7 +++++-- 6 files changed, 100 insertions(+), 18 deletions(-) diff --git a/sample/src/CIAF_1/index.xml b/sample/src/CIAF_1/index.xml index 5d9ad5a..ed9e150 100644 --- a/sample/src/CIAF_1/index.xml +++ b/sample/src/CIAF_1/index.xml @@ -26,7 +26,10 @@ John Doe Jr. CIAF - Czech International Air Fest 2007 ciaf,aircraft,military,exhibition - + + + + @@ -38,12 +41,14 @@ Photo title This photo uses supplied preview image. Some people (me) can see the difference in sharpness. + Photo title This photo doesn't contain link to original image, but src parameter is specified. + can have CDATA entries here!]]> @@ -114,6 +119,7 @@ + @@ -132,6 +138,7 @@ + diff --git a/src/generators.c b/src/generators.c index 52ec1ac..2038424 100644 --- a/src/generators.c +++ b/src/generators.c @@ -170,6 +170,12 @@ metadata_apply_overrides (ExifData *exif_data, exif_data->external_exif_data = NULL; if (setup->write_supplied_exif && item->metadata_external_exif) exif_data->external_exif_data = g_build_filename (path_info->src_dir, item->metadata_external_exif, NULL); + + exif_data->squared_thumbnail_type = setup->squared_thumbnail_type; + + exif_data->thumbnail_crop_hint = item->thumbnail_crop_hint; + if (exif_data->thumbnail_crop_hint == CROP_HINT_UNDEFINED) + exif_data->thumbnail_crop_hint = items->thumbnail_crop_hint; } @@ -212,6 +218,9 @@ generate_image (TGallerySetup *setup, if (img_src == NULL || img_dst == NULL) continue; + exif_data = exif_data_new_empty (); + metadata_apply_overrides (exif_data, setup, path_info, items, item); + /* Do something when required */ res = res || needs_update (img_src, img_dst); if (! query_update) { @@ -251,7 +260,7 @@ generate_image (TGallerySetup *setup, quality = item->quality; /* Perform resize and strip */ - if (! resize_image (img_src, img_dst, img_w, img_h, quality, is_thumbnail, setup->squared_thumbnail_type, setup->autorotate)) + if (! resize_image (img_src, img_dst, img_w, img_h, quality, is_thumbnail, setup->autorotate, exif_data)) log_error ("generate_image: error resizing image %s\n", img_src); } else { log_error ("generate_image: image %s sizes are %lux%lu\n", img_src, img_w, img_h); @@ -259,12 +268,10 @@ generate_image (TGallerySetup *setup, } } if (! is_thumbnail) { - exif_data = exif_data_new_empty (); - metadata_apply_overrides (exif_data, setup, path_info, items, item); modify_exif (img_dst, exif_data, setup->erase_exif_thumbnail, setup->strip_xmp); - exif_data_free (exif_data); } + exif_data_free (exif_data); g_free (img_src); g_free (img_dst); } diff --git a/src/items.c b/src/items.c index 85f0a26..31ab41f 100644 --- a/src/items.c +++ b/src/items.c @@ -85,6 +85,29 @@ parse_datetime_string (const gchar *str) return rt; } +static TCropHint +parse_thumbnail_crop_hint (const gchar *str) +{ + g_return_val_if_fail (str != NULL, CROP_HINT_UNDEFINED); + + if (g_ascii_strcasecmp (str, "center") == 0) + return CROP_HINT_CENTER; + else + if (g_ascii_strcasecmp (str, "left") == 0) + return CROP_HINT_LEFT; + else + if (g_ascii_strcasecmp (str, "right") == 0) + return CROP_HINT_RIGHT; + else + if (g_ascii_strcasecmp (str, "top") == 0) + return CROP_HINT_TOP; + else + if (g_ascii_strcasecmp (str, "bottom") == 0) + return CROP_HINT_BOTTOM; + else + return CROP_HINT_UNDEFINED; +} + /* * parse_album_xml: XML parser for gallery index.xml files @@ -161,6 +184,12 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info) g_free (s); } + s = xml_file_get_node_attribute (xml, "/gallery/general/thumbnail", "crop"); + if (s != NULL) { + index->thumbnail_crop_hint = parse_thumbnail_crop_hint (s); + g_free (s); + } + index->nofullsize = xml_file_get_node_present (xml, "/gallery/general/nofullsize"); index->fullsize = xml_file_get_node_present (xml, "/gallery/general/fullsize"); @@ -306,6 +335,14 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info) g_free (s2); } + s = g_strdup_printf ("/gallery/items/*[%d]/thumbnail", i + 1); + s2 = xml_file_get_node_attribute (xml, s, "crop"); + g_free (s); + if (s2 != NULL) { + item->thumbnail_crop_hint = parse_thumbnail_crop_hint (s2); + g_free (s2); + } + if (item->path || item->preview) { g_ptr_array_add (index->items, item); } else { @@ -422,15 +459,15 @@ free_album_data (TAlbum *album) * get_album_info: retrieve number of items and protected status in the specified album */ void -get_album_info (const gchar *filename, int *objects_count, gboolean *protected) +get_album_info (const gchar *filename, int *objects_count, gboolean *is_protected) { TXMLFile *xml; int count, hidden; if (objects_count) *objects_count = 0; - if (protected) - *protected = FALSE; + if (is_protected) + *is_protected = FALSE; xml = xml_parser_load (filename); if (xml == NULL) @@ -441,9 +478,9 @@ get_album_info (const gchar *filename, int *objects_count, gboolean *protected) if (objects_count) *objects_count = count - hidden; - if (protected) - *protected = xml_file_get_node_present (xml, "/gallery/general/auth/username") && - xml_file_get_node_present (xml, "/gallery/general/auth/password"); + if (is_protected) + *is_protected = xml_file_get_node_present (xml, "/gallery/general/auth/username") && + xml_file_get_node_present (xml, "/gallery/general/auth/password"); xml_parser_free (xml); } diff --git a/src/items.h b/src/items.h index 331f29e..b502e71 100644 --- a/src/items.h +++ b/src/items.h @@ -39,6 +39,15 @@ typedef enum { AUTH_TYPE_BASIC } TAuthType; +typedef enum { + CROP_HINT_UNDEFINED = 0, + CROP_HINT_CENTER, + CROP_HINT_LEFT, + CROP_HINT_RIGHT, + CROP_HINT_TOP, + CROP_HINT_BOTTOM +} TCropHint; + typedef struct { TGalleryType type; gchar *ID; @@ -66,6 +75,7 @@ typedef struct { TAuthType auth_type; int metadata_tz_shift; /* minutes */ time_t metadata_fake_datetime; + TCropHint thumbnail_crop_hint; } TAlbum; typedef struct { @@ -85,6 +95,7 @@ typedef struct { gchar *metadata_external_exif; int metadata_tz_shift; /* minutes */ time_t metadata_fake_datetime; + TCropHint thumbnail_crop_hint; } TIndexItem; typedef struct { @@ -115,7 +126,7 @@ void free_album_data (TAlbum *index); /* * get_album_info: retrieve number of items and protected status in the specified album */ -void get_album_info (const gchar *filename, int *objects_count, gboolean *protected); +void get_album_info (const gchar *filename, int *objects_count, gboolean *is_protected); /* * get_album_titles: retrieve title, description and first thumbnail from specified album diff --git a/src/jpeg-utils.cpp b/src/jpeg-utils.cpp index d7382c8..be95ec9 100644 --- a/src/jpeg-utils.cpp +++ b/src/jpeg-utils.cpp @@ -432,8 +432,8 @@ resize_image (const gchar *src, const gchar *dst, unsigned long size_x, unsigned long size_y, int quality, gboolean thumbnail, - ThumbnailSquareType squared_thumbnail_type, - gboolean autorotate) + gboolean autorotate, + ExifData *exif) { MagickWand *magick_wand; ExceptionType severity; @@ -460,13 +460,30 @@ resize_image (const gchar *src, const gchar *dst, { /* Process thumbnail if required */ if (thumbnail) { - switch (squared_thumbnail_type) { + switch (exif->squared_thumbnail_type) { case THUMBNAIL_SQUARE_TYPE_SIMPLE: w = MagickGetImageWidth (magick_wand); h = MagickGetImageHeight (magick_wand); amount = MAX (w, h) * SQUARED_SIMPLE_SHAVE_AMOUNT / 100; amount = MIN (w - 2*amount, h - 2*amount); - MagickCropImage (magick_wand, amount, amount, (w - amount) / 2, (h - amount) / 2); + switch (exif->thumbnail_crop_hint) { + case CROP_HINT_UNDEFINED: + case CROP_HINT_CENTER: + MagickCropImage (magick_wand, amount, amount, (w - amount) / 2, (h - amount) / 2); + break; + case CROP_HINT_LEFT: + MagickCropImage (magick_wand, amount, amount, 0, (h - amount) / 2); + break; + case CROP_HINT_RIGHT: + MagickCropImage (magick_wand, amount, amount, w - amount, (h - amount) / 2); + break; + case CROP_HINT_TOP: + MagickCropImage (magick_wand, amount, amount, (w - amount) / 2, 0); + break; + case CROP_HINT_BOTTOM: + MagickCropImage (magick_wand, amount, amount, (w - amount) / 2, h - amount); + break; + } break; default: break; diff --git a/src/jpeg-utils.h b/src/jpeg-utils.h index 0e3cd1f..f8c9b6d 100644 --- a/src/jpeg-utils.h +++ b/src/jpeg-utils.h @@ -20,6 +20,7 @@ #include #include "setup.h" +#include "items.h" G_BEGIN_DECLS @@ -54,6 +55,8 @@ typedef struct { int timezone_shift; time_t fake_datetime; gchar *external_exif_data; + ThumbnailSquareType squared_thumbnail_type; + TCropHint thumbnail_crop_hint; } ExifData; @@ -87,8 +90,8 @@ gboolean resize_image (const gchar *src, const gchar *dst, unsigned long size_x, unsigned long size_y, int quality, gboolean thumbnail, - ThumbnailSquareType squared_thumbnail_type, - gboolean autorotate); + gboolean autorotate, + ExifData *exif); /* * get_image_sizes: retrieve image dimensions -- cgit v1.2.3