From ce1ae1ff69309ec7f1905e928a9d43eb8ae86dbe Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Mon, 26 Sep 2016 14:56:06 +0200 Subject: jpeg-utils: Add support for custom resize options This change brings the possibility to tweak resize options using standard ImageMagick `convert` command syntax. Separate options are offered for thumbnails. --- src/jpeg-utils.cpp | 115 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 10 deletions(-) (limited to 'src/jpeg-utils.cpp') diff --git a/src/jpeg-utils.cpp b/src/jpeg-utils.cpp index 11d2c4e..aaf59fc 100644 --- a/src/jpeg-utils.cpp +++ b/src/jpeg-utils.cpp @@ -467,6 +467,37 @@ autorotate_image (MagickWand *magick_wand) DestroyPixelWand (pixel_wand); } +static gchar ** +parse_cmd_args (const gchar *resize_opts, const gchar *prepend, const gchar *append, const gchar *file_in, const gchar *file_out, unsigned long size_x, unsigned long size_y) +{ + gchar *in; + gchar **s; + gchar *f; + + in = g_strdup_printf ("%s %s %s %s %s", + prepend ? prepend : "", + file_in ? file_in : "", + resize_opts, + file_out ? file_out : "", + append ? append : ""); + while (g_strstr_len (in, -1, "${WIDTH}")) { + f = g_strdup_printf ("%lu", size_x); + str_replace (&in, "${WIDTH}", f); + g_free (f); + } + while (g_strstr_len (in, -1, "${HEIGHT}")) { + f = g_strdup_printf ("%lu", size_y); + str_replace (&in, "${HEIGHT}", f); + g_free (f); + } + /* ImageMagick doesn't like empty elements */ + str_trim_inside (&in); + s = g_strsplit (in, " ", -1); + g_free (in); + + return s; +} + /* * resize_image: resize image pointed by src and save result to dst */ @@ -476,14 +507,20 @@ resize_image (const gchar *src, const gchar *dst, int quality, gboolean thumbnail, gboolean autorotate, - ExifData *exif) + ExifData *exif, + gchar *resize_opts) { MagickWand *magick_wand; + ImageInfo *image_info; + ExceptionInfo *exception_info; ExceptionType severity; unsigned long w, h; unsigned long new_w, new_h; double source_aspect, target_aspect; gchar *description; + gchar **cmd_args; + gchar *res_id = NULL; + gchar *mpr_res_id; g_assert (src != NULL); g_assert (dst != NULL); @@ -494,6 +531,7 @@ resize_image (const gchar *src, const gchar *dst, description = MagickGetException (magick_wand, &severity); log_error ("Error reading image: %s %s %ld %s\n", GetMagickModule(), description); MagickRelinquishMemory (description); + DestroyMagickWand (magick_wand); return FALSE; } @@ -501,10 +539,9 @@ 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 (MagickGetImageWidth (magick_wand) > size_x || MagickGetImageHeight (magick_wand) > size_y) { - /* Process thumbnail if required */ + /* Prepare image before resizing */ if (thumbnail) { if (exif->thumbnail_crop_style != CROP_STYLE_NORMAL) { w = MagickGetImageWidth (magick_wand); @@ -548,12 +585,64 @@ resize_image (const gchar *src, const gchar *dst, break; } } - MagickThumbnailImage (magick_wand, size_x, size_y); - /* FIXME: this strips image ICC profile, should do proper conversion first */ - MagickStripImage (magick_wand); } - else - MagickResizeImage (magick_wand, size_x, size_y, LanczosFilter, 1.0); + + if (resize_opts == NULL) { + /* Perform internal resizing */ + if (thumbnail) { + MagickThumbnailImage (magick_wand, size_x, size_y); + } else { + MagickResizeImage (magick_wand, size_x, size_y, LanczosFilter, 1.0); + } + } else { + /* Perform resizing through ImageMagick commandline parser */ + res_id = g_strdup_printf ("cgg_resize_image_%p", g_thread_self ()); + mpr_res_id = g_strdup_printf ("mpr:%s", res_id); + if (MagickWriteImage (magick_wand, mpr_res_id) == MagickFalse) { + description = MagickGetException (magick_wand, &severity); + log_error ("Error writing mpr image: %s %s %ld %s\n", GetMagickModule(), description); + MagickRelinquishMemory (description); + DestroyMagickWand (magick_wand); + g_free (res_id); + g_free (mpr_res_id); + return FALSE; + } + ClearMagickWand (magick_wand); + + cmd_args = parse_cmd_args (resize_opts, "convert", NULL, mpr_res_id, mpr_res_id, size_x, size_y); + image_info = AcquireImageInfo (); + g_assert (image_info != NULL); + exception_info = AcquireExceptionInfo (); + g_assert (exception_info != NULL); + if (MagickCommandGenesis (image_info, ConvertImageCommand, g_strv_length (cmd_args), cmd_args, NULL, exception_info) == MagickFalse) { + /* MagickCommandGenesis() should've printed verbose error message */ + DestroyImageInfo (image_info); + DestroyExceptionInfo (exception_info); + DestroyMagickWand (magick_wand); + g_free (res_id); + g_free (mpr_res_id); + return FALSE; + } + DestroyImageInfo (image_info); + DestroyExceptionInfo (exception_info); + g_strfreev (cmd_args); + + if (MagickReadImage (magick_wand, mpr_res_id) == MagickFalse) { + description = MagickGetException (magick_wand, &severity); + printf ("Error reading mpr image: %s %s %ld %s\n", GetMagickModule(), description); + MagickRelinquishMemory (description); + DestroyMagickWand (magick_wand); + g_free (res_id); + g_free (mpr_res_id); + return FALSE; + } + g_free (mpr_res_id); + } + } + + if (thumbnail) { + /* FIXME: this strips image ICC profile, should do proper conversion first */ + MagickStripImage (magick_wand); } if ((int) MagickGetImageCompressionQuality (magick_wand) != quality) @@ -563,10 +652,16 @@ resize_image (const gchar *src, const gchar *dst, if (MagickWriteImage (magick_wand, dst) == MagickFalse) { description = MagickGetException (magick_wand, &severity); log_error ("Error writing image: %s %s %ld %s\n", GetMagickModule(), description); - MagickRelinquishMemory (description); + DeleteImageRegistry (res_id); + g_free (res_id); return FALSE; } + if (res_id) { + /* This is potentially dangerous operation - modifying ImageMagick's internal image registry */ + DeleteImageRegistry (res_id); + g_free (res_id); + } magick_wand = DestroyMagickWand (magick_wand); return TRUE; -- cgit v1.2.3