From: Paul Eggert Date: Thu, 4 Jul 2013 15:25:54 +0000 (-0700) Subject: Scale ImageMagick images more carefully. X-Git-Tag: emacs-24.3.90~173^2^2~42^2~45^2~387^2~1927 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=b9ed53d53585d9e1122eb3e452c74db1f2506324;p=emacs.git Scale ImageMagick images more carefully. * image.c (scale_image_size) [HAVE_IMAGEMAGICK]: New function. (compute_image_size): Use it. Define only if HAVE_IMAGEMAGICK. Be more careful about avoiding undefined behavior after integer overflow and division by zero. --- diff --git a/src/ChangeLog b/src/ChangeLog index 9012f5ba16a..478e2bdf37a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2013-07-04 Paul Eggert + + Scale ImageMagick images more carefully. + * image.c (scale_image_size) [HAVE_IMAGEMAGICK]: New function. + (compute_image_size): Use it. Define only if HAVE_IMAGEMAGICK. + Be more careful about avoiding undefined behavior after + integer overflow and division by zero. + 2013-07-04 YAMAMOTO Mitsuharu * w32fns.c (Qgeometry, Qworkarea, Qmm_size, Qframes): New variables. diff --git a/src/image.c b/src/image.c index 2f9a8442256..a3e103f9559 100644 --- a/src/image.c +++ b/src/image.c @@ -7625,6 +7625,31 @@ gif_load (struct frame *f, struct image *img) #endif /* HAVE_GIF */ +#ifdef HAVE_IMAGEMAGICK + +/*********************************************************************** + ImageMagick +***********************************************************************/ + +/* Scale an image size by returning SIZE / DIVISOR * MULTIPLIER, + safely rounded and clipped to int range. */ + +static int +scale_image_size (int size, size_t divisor, size_t multiplier) +{ + if (divisor != 0) + { + double s = size; + double scaled = s * multiplier / divisor + 0.5; + if (scaled < INT_MAX) + return scaled; + } + return INT_MAX; +} + +/* Compute the desired size of an image with native size WIDTH x HEIGHT. + Use SPEC to deduce the size. Store the desired size into + *D_WIDTH x *D_HEIGHT. Store -1 x -1 if the native size is OK. */ static void compute_image_size (size_t width, size_t height, Lisp_Object spec, @@ -7638,39 +7663,36 @@ compute_image_size (size_t width, size_t height, unspecified should be calculated from the specified to preserve aspect ratio. */ value = image_spec_value (spec, QCwidth, NULL); - desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); + desired_width = NATNUMP (value) ? min (XFASTINT (value), INT_MAX) : -1; value = image_spec_value (spec, QCheight, NULL); - desired_height = (INTEGERP (value) ? XFASTINT (value) : -1); + desired_height = NATNUMP (value) ? min (XFASTINT (value), INT_MAX) : -1; if (desired_width == -1) { value = image_spec_value (spec, QCmax_width, NULL); - if (INTEGERP (value) && - width > XFASTINT (value)) + if (NATNUMP (value)) { - /* The image is wider than :max-width. */ - desired_width = XFASTINT (value); - if (desired_height == -1) + int max_width = min (XFASTINT (value), INT_MAX); + if (max_width < width) { - value = image_spec_value (spec, QCmax_height, NULL); - if (INTEGERP (value)) + /* The image is wider than :max-width. */ + desired_width = max_width; + if (desired_height == -1) { - /* We have no specified height, but we have a - :max-height value, so check that we satisfy both - conditions. */ - desired_height = (double) desired_width / width * height; - if (desired_height > XFASTINT (value)) + desired_height = scale_image_size (desired_width, + width, height); + value = image_spec_value (spec, QCmax_height, NULL); + if (NATNUMP (value)) { - desired_height = XFASTINT (value); - desired_width = (double) desired_height / height * width; + int max_height = min (XFASTINT (value), INT_MAX); + if (max_height < desired_height) + { + desired_height = max_height; + desired_width = scale_image_size (desired_height, + height, width); + } } } - else - { - /* We have no specified height and no specified - max-height, so just compute the height. */ - desired_height = (double) desired_width / width * height; - } } } } @@ -7678,28 +7700,26 @@ compute_image_size (size_t width, size_t height, if (desired_height == -1) { value = image_spec_value (spec, QCmax_height, NULL); - if (INTEGERP (value) && - height > XFASTINT (value)) - desired_height = XFASTINT (value); + if (NATNUMP (value)) + { + int max_height = min (XFASTINT (value), INT_MAX); + if (max_height < height) + desired_height = max_height; + } } if (desired_width != -1 && desired_height == -1) /* w known, calculate h. */ - desired_height = (double) desired_width / width * height; + desired_height = scale_image_size (desired_width, width, height); if (desired_width == -1 && desired_height != -1) /* h known, calculate w. */ - desired_width = (double) desired_height / height * width; + desired_width = scale_image_size (desired_height, height, width); *d_width = desired_width; *d_height = desired_height; } -/*********************************************************************** - ImageMagick -***********************************************************************/ -#if defined (HAVE_IMAGEMAGICK) - static Lisp_Object Qimagemagick; static bool imagemagick_image_p (Lisp_Object);