diff options
| author | Paul Eggert | 2013-07-04 08:25:54 -0700 |
|---|---|---|
| committer | Paul Eggert | 2013-07-04 08:25:54 -0700 |
| commit | b9ed53d53585d9e1122eb3e452c74db1f2506324 (patch) | |
| tree | 03e6ca8998c87a2f2f6da1de688eeab6e37e93bf /src | |
| parent | cf13177e99d20e8db632ad6ed5defd3818f7d901 (diff) | |
| download | emacs-b9ed53d53585d9e1122eb3e452c74db1f2506324.tar.gz emacs-b9ed53d53585d9e1122eb3e452c74db1f2506324.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 8 | ||||
| -rw-r--r-- | src/image.c | 84 |
2 files changed, 60 insertions, 32 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 9012f5ba16a..478e2bdf37a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,11 @@ | |||
| 1 | 2013-07-04 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Scale ImageMagick images more carefully. | ||
| 4 | * image.c (scale_image_size) [HAVE_IMAGEMAGICK]: New function. | ||
| 5 | (compute_image_size): Use it. Define only if HAVE_IMAGEMAGICK. | ||
| 6 | Be more careful about avoiding undefined behavior after | ||
| 7 | integer overflow and division by zero. | ||
| 8 | |||
| 1 | 2013-07-04 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> | 9 | 2013-07-04 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> |
| 2 | 10 | ||
| 3 | * w32fns.c (Qgeometry, Qworkarea, Qmm_size, Qframes): New variables. | 11 | * 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) | |||
| 7625 | #endif /* HAVE_GIF */ | 7625 | #endif /* HAVE_GIF */ |
| 7626 | 7626 | ||
| 7627 | 7627 | ||
| 7628 | #ifdef HAVE_IMAGEMAGICK | ||
| 7629 | |||
| 7630 | /*********************************************************************** | ||
| 7631 | ImageMagick | ||
| 7632 | ***********************************************************************/ | ||
| 7633 | |||
| 7634 | /* Scale an image size by returning SIZE / DIVISOR * MULTIPLIER, | ||
| 7635 | safely rounded and clipped to int range. */ | ||
| 7636 | |||
| 7637 | static int | ||
| 7638 | scale_image_size (int size, size_t divisor, size_t multiplier) | ||
| 7639 | { | ||
| 7640 | if (divisor != 0) | ||
| 7641 | { | ||
| 7642 | double s = size; | ||
| 7643 | double scaled = s * multiplier / divisor + 0.5; | ||
| 7644 | if (scaled < INT_MAX) | ||
| 7645 | return scaled; | ||
| 7646 | } | ||
| 7647 | return INT_MAX; | ||
| 7648 | } | ||
| 7649 | |||
| 7650 | /* Compute the desired size of an image with native size WIDTH x HEIGHT. | ||
| 7651 | Use SPEC to deduce the size. Store the desired size into | ||
| 7652 | *D_WIDTH x *D_HEIGHT. Store -1 x -1 if the native size is OK. */ | ||
| 7628 | static void | 7653 | static void |
| 7629 | compute_image_size (size_t width, size_t height, | 7654 | compute_image_size (size_t width, size_t height, |
| 7630 | Lisp_Object spec, | 7655 | Lisp_Object spec, |
| @@ -7638,39 +7663,36 @@ compute_image_size (size_t width, size_t height, | |||
| 7638 | unspecified should be calculated from the specified to preserve | 7663 | unspecified should be calculated from the specified to preserve |
| 7639 | aspect ratio. */ | 7664 | aspect ratio. */ |
| 7640 | value = image_spec_value (spec, QCwidth, NULL); | 7665 | value = image_spec_value (spec, QCwidth, NULL); |
| 7641 | desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); | 7666 | desired_width = NATNUMP (value) ? min (XFASTINT (value), INT_MAX) : -1; |
| 7642 | value = image_spec_value (spec, QCheight, NULL); | 7667 | value = image_spec_value (spec, QCheight, NULL); |
| 7643 | desired_height = (INTEGERP (value) ? XFASTINT (value) : -1); | 7668 | desired_height = NATNUMP (value) ? min (XFASTINT (value), INT_MAX) : -1; |
| 7644 | 7669 | ||
| 7645 | if (desired_width == -1) | 7670 | if (desired_width == -1) |
| 7646 | { | 7671 | { |
| 7647 | value = image_spec_value (spec, QCmax_width, NULL); | 7672 | value = image_spec_value (spec, QCmax_width, NULL); |
| 7648 | if (INTEGERP (value) && | 7673 | if (NATNUMP (value)) |
| 7649 | width > XFASTINT (value)) | ||
| 7650 | { | 7674 | { |
| 7651 | /* The image is wider than :max-width. */ | 7675 | int max_width = min (XFASTINT (value), INT_MAX); |
| 7652 | desired_width = XFASTINT (value); | 7676 | if (max_width < width) |
| 7653 | if (desired_height == -1) | ||
| 7654 | { | 7677 | { |
| 7655 | value = image_spec_value (spec, QCmax_height, NULL); | 7678 | /* The image is wider than :max-width. */ |
| 7656 | if (INTEGERP (value)) | 7679 | desired_width = max_width; |
| 7680 | if (desired_height == -1) | ||
| 7657 | { | 7681 | { |
| 7658 | /* We have no specified height, but we have a | 7682 | desired_height = scale_image_size (desired_width, |
| 7659 | :max-height value, so check that we satisfy both | 7683 | width, height); |
| 7660 | conditions. */ | 7684 | value = image_spec_value (spec, QCmax_height, NULL); |
| 7661 | desired_height = (double) desired_width / width * height; | 7685 | if (NATNUMP (value)) |
| 7662 | if (desired_height > XFASTINT (value)) | ||
| 7663 | { | 7686 | { |
| 7664 | desired_height = XFASTINT (value); | 7687 | int max_height = min (XFASTINT (value), INT_MAX); |
| 7665 | desired_width = (double) desired_height / height * width; | 7688 | if (max_height < desired_height) |
| 7689 | { | ||
| 7690 | desired_height = max_height; | ||
| 7691 | desired_width = scale_image_size (desired_height, | ||
| 7692 | height, width); | ||
| 7693 | } | ||
| 7666 | } | 7694 | } |
| 7667 | } | 7695 | } |
| 7668 | else | ||
| 7669 | { | ||
| 7670 | /* We have no specified height and no specified | ||
| 7671 | max-height, so just compute the height. */ | ||
| 7672 | desired_height = (double) desired_width / width * height; | ||
| 7673 | } | ||
| 7674 | } | 7696 | } |
| 7675 | } | 7697 | } |
| 7676 | } | 7698 | } |
| @@ -7678,28 +7700,26 @@ compute_image_size (size_t width, size_t height, | |||
| 7678 | if (desired_height == -1) | 7700 | if (desired_height == -1) |
| 7679 | { | 7701 | { |
| 7680 | value = image_spec_value (spec, QCmax_height, NULL); | 7702 | value = image_spec_value (spec, QCmax_height, NULL); |
| 7681 | if (INTEGERP (value) && | 7703 | if (NATNUMP (value)) |
| 7682 | height > XFASTINT (value)) | 7704 | { |
| 7683 | desired_height = XFASTINT (value); | 7705 | int max_height = min (XFASTINT (value), INT_MAX); |
| 7706 | if (max_height < height) | ||
| 7707 | desired_height = max_height; | ||
| 7708 | } | ||
| 7684 | } | 7709 | } |
| 7685 | 7710 | ||
| 7686 | if (desired_width != -1 && desired_height == -1) | 7711 | if (desired_width != -1 && desired_height == -1) |
| 7687 | /* w known, calculate h. */ | 7712 | /* w known, calculate h. */ |
| 7688 | desired_height = (double) desired_width / width * height; | 7713 | desired_height = scale_image_size (desired_width, width, height); |
| 7689 | 7714 | ||
| 7690 | if (desired_width == -1 && desired_height != -1) | 7715 | if (desired_width == -1 && desired_height != -1) |
| 7691 | /* h known, calculate w. */ | 7716 | /* h known, calculate w. */ |
| 7692 | desired_width = (double) desired_height / height * width; | 7717 | desired_width = scale_image_size (desired_height, height, width); |
| 7693 | 7718 | ||
| 7694 | *d_width = desired_width; | 7719 | *d_width = desired_width; |
| 7695 | *d_height = desired_height; | 7720 | *d_height = desired_height; |
| 7696 | } | 7721 | } |
| 7697 | 7722 | ||
| 7698 | /*********************************************************************** | ||
| 7699 | ImageMagick | ||
| 7700 | ***********************************************************************/ | ||
| 7701 | #if defined (HAVE_IMAGEMAGICK) | ||
| 7702 | |||
| 7703 | static Lisp_Object Qimagemagick; | 7723 | static Lisp_Object Qimagemagick; |
| 7704 | 7724 | ||
| 7705 | static bool imagemagick_image_p (Lisp_Object); | 7725 | static bool imagemagick_image_p (Lisp_Object); |