From 90658af48dccad0d9f14c83964f5669cda164e12 Mon Sep 17 00:00:00 2001 From: homm Date: Sat, 29 Nov 2014 03:58:52 +0300 Subject: [PATCH 1/6] new section framework --- docs/index.rst | 1 + docs/releasenotes/2.7.rst | 39 +++++++++++++++++++++++++++++++++++++ docs/releasenotes/index.rst | 7 +++++++ 3 files changed, 47 insertions(+) create mode 100644 docs/releasenotes/2.7.rst create mode 100644 docs/releasenotes/index.rst diff --git a/docs/index.rst b/docs/index.rst index 16e450856..4351438de 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -29,6 +29,7 @@ To install Pillow, please follow the :doc:`installation instructions Date: Sat, 29 Nov 2014 23:04:51 +0300 Subject: [PATCH 2/6] chapters: Antialias renamed to Lanczos Default filter for thumbnails Image transposing --- docs/releasenotes/2.7.rst | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/releasenotes/2.7.rst b/docs/releasenotes/2.7.rst index 2f4581c25..9e762e1df 100644 --- a/docs/releasenotes/2.7.rst +++ b/docs/releasenotes/2.7.rst @@ -10,6 +10,18 @@ Bicubic and Bilinear downscalling Antialias renamed to Lanczos ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +New :py:attr:`PIL.Image.LANCZOS` constant was added instead of +:py:attr:`PIL.Image.ANTIALIAS`. + +When :py:attr:`~PIL.Image.ANTIALIAS` was initially added, it was the only +high-qality filter based on convolutions. It's name was supposed to reflect +this. Starting from 2.7 all resize method are based on convolutions. All of them +are antialias from now. And the real name of :py:attr:`~PIL.Image.ANTIALIAS` +filter is Lanczos filter. + +:py:attr:`~PIL.Image.ANTIALIAS` constant is leaved for backward compatibility +and is an alias for :py:attr:`~PIL.Image.LANCZOS`. + Lanczos upscaling quality ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,9 +34,28 @@ Resize performance Default filter for thumbnails ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In Pillow 2.5 default filter for :py:meth:`~PIL.Image.Image.thumbnail` was +changed from :py:attr:`~PIL.Image.NEAREST` to :py:attr:`~PIL.Image.ANTIALIAS`. +Antialias was chosen because all other filters gave poor quality for reduction. +Starting from Pillow 2.7 :py:attr:`~PIL.Image.ANTIALIAS` replaced with +:py:attr:`~PIL.Image.BICUBIC`, because bicubic is faster and +:py:attr:`~PIL.Image.ANTIALIAS` doesn't give any advantages after +downscaling with libJPEG, which uses supersampling internaly, not convolutions. + Image transposing ----------------- +New method :py:attr:`PIL.Image.TRANSPOSE` was added for +:py:meth:`~PIL.Image.Image.transpose` operation in addition to +:py:attr:`~PIL.Image.FLIP_LEFT_RIGHT`, :py:attr:`~PIL.Image.FLIP_TOP_BOTTOM`, +:py:attr:`~PIL.Image.ROTATE_90`, :py:attr:`~PIL.Image.ROTATE_180`, +:py:attr:`~PIL.Image.ROTATE_270`. :py:attr:`~PIL.Image.TRANSPOSE` is algebra +transpose, when image reflected over its main diagonal. + +Speed of :py:attr:`~PIL.Image.ROTATE_90`, :py:attr:`~PIL.Image.ROTATE_270` +and :py:attr:`~PIL.Image.TRANSPOSE` was significantly improved for large images, +which doesn't fit in processor cache. + Gaussian blur and unsharp mask ------------------------------ From b183f50ebcd01b5b3e7e08ec8df5c2d3aeca0569 Mon Sep 17 00:00:00 2001 From: homm Date: Sun, 30 Nov 2014 03:09:39 +0300 Subject: [PATCH 3/6] chapters: Image resizing filters Bicubic and Bilinear downscaling Lanczos upscaling quality Bicubic upscaling quality --- docs/releasenotes/2.7.rst | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/docs/releasenotes/2.7.rst b/docs/releasenotes/2.7.rst index 9e762e1df..97c57e1b0 100644 --- a/docs/releasenotes/2.7.rst +++ b/docs/releasenotes/2.7.rst @@ -4,14 +4,36 @@ Pillow 2.7 Image resizing filters ---------------------- -Bicubic and Bilinear downscalling +Image resizing methods :py:meth:`~PIL.Image.Image.resize` and +:py:meth:`~PIL.Image.Image.thumbnail` takes `resample` argument, which tells +what filter should be used for resampling. Possible values are: +:py:attr:`PIL.Image.NEAREST`, :py:attr:`PIL.Image.BILINEAR`, +:py:attr:`PIL.Image.BICUBIC` and :py:attr:`PIL.Image.ANTIALIAS`. +Almost all of them was changed in this version. + +Bicubic and Bilinear downscaling ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +From very begining :py:attr:`~PIL.Image.BILINEAR` and +:py:attr:`~PIL.Image.BICUBIC` filters was based on afine transformations +and uses fixed number of pixels from source image for every destination pixel +(that was 2x2 pixels for :py:attr:`~PIL.Image.BILINEAR` and 4x4 for +:py:attr:`~PIL.Image.BICUBIC`). This gave an unsatisfied result for downscaling. +At the same time high quality convolutions-based algorithm with flexeible kernel +was used for :py:attr:`~PIL.Image.ANTIALIAS` filter). + +Starting from 2.7 high quality convolutions-based algorithm is used for all of +these three filters. + +If you have previously used any tricks to maintain quality when downscaling with +:py:attr:`~PIL.Image.BILINEAR` and :py:attr:`~PIL.Image.BICUBIC` filters +(for example, reducing within several steps), they a unnecessary now. + Antialias renamed to Lanczos ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ New :py:attr:`PIL.Image.LANCZOS` constant was added instead of -:py:attr:`PIL.Image.ANTIALIAS`. +:py:attr:`~PIL.Image.ANTIALIAS`. When :py:attr:`~PIL.Image.ANTIALIAS` was initially added, it was the only high-qality filter based on convolutions. It's name was supposed to reflect @@ -25,9 +47,16 @@ and is an alias for :py:attr:`~PIL.Image.LANCZOS`. Lanczos upscaling quality ^^^^^^^^^^^^^^^^^^^^^^^^^ +Image upscaling quality with :py:attr:`PIL.Image.LANCZOS` filter was almost +the same as :py:attr:`PIL.Image.BILINEAR` due to bug. This was fixed. + Bicubic upscaling quality ^^^^^^^^^^^^^^^^^^^^^^^^^ +:py:attr:`~PIL.Image.BICUBIC` filter for affine trnsformations was producing +sharp, slightly pixelated image for upscaling. Bicubic for convolutions is +more soft. + Resize performance ^^^^^^^^^^^^^^^^^^ From ca108113ba9735af19e5ddd572d79b2ea28e1635 Mon Sep 17 00:00:00 2001 From: homm Date: Sun, 30 Nov 2014 20:31:33 +0300 Subject: [PATCH 4/6] chapters: Resize performance --- docs/releasenotes/2.7.rst | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/docs/releasenotes/2.7.rst b/docs/releasenotes/2.7.rst index 97c57e1b0..c9fd9e7af 100644 --- a/docs/releasenotes/2.7.rst +++ b/docs/releasenotes/2.7.rst @@ -47,8 +47,8 @@ and is an alias for :py:attr:`~PIL.Image.LANCZOS`. Lanczos upscaling quality ^^^^^^^^^^^^^^^^^^^^^^^^^ -Image upscaling quality with :py:attr:`PIL.Image.LANCZOS` filter was almost -the same as :py:attr:`PIL.Image.BILINEAR` due to bug. This was fixed. +Image upscaling quality with :py:attr:`~PIL.Image.LANCZOS` filter was almost +the same as :py:attr:`~PIL.Image.BILINEAR` due to bug. This was fixed. Bicubic upscaling quality ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,6 +60,21 @@ more soft. Resize performance ^^^^^^^^^^^^^^^^^^ +In most cases convolution is more expensive algorithm for downscaling because +it tekes in account all pixels of source image. Therefore +:py:attr:`~PIL.Image.BILINEAR` and :py:attr:`~PIL.Image.BICUBIC` filters +performance can be lower than before. On the other hand quality of +:py:attr:`~PIL.Image.BILINEAR` and :py:attr:`~PIL.Image.BICUBIC` was close to +:py:attr:`~PIL.Image.NEAREST`. So if such quality is suitable for your task +you can switch to :py:attr:`~PIL.Image.NEAREST` filter for downscaling, +that will give huge win in performance. + +At the same time performance of convolution resampling for downscaling was +improved in about two times compared to previous version. +Upscaling performance of :py:attr:`~PIL.Image.LANCZOS` filter remained the same. +For :py:attr:`~PIL.Image.BILINEAR` filter it grew in 1.5 times and +for :py:attr:`~PIL.Image.BICUBIC` in 4 times. + Default filter for thumbnails ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -67,7 +82,7 @@ In Pillow 2.5 default filter for :py:meth:`~PIL.Image.Image.thumbnail` was changed from :py:attr:`~PIL.Image.NEAREST` to :py:attr:`~PIL.Image.ANTIALIAS`. Antialias was chosen because all other filters gave poor quality for reduction. Starting from Pillow 2.7 :py:attr:`~PIL.Image.ANTIALIAS` replaced with -:py:attr:`~PIL.Image.BICUBIC`, because bicubic is faster and +:py:attr:`~PIL.Image.BICUBIC`, because it faster and :py:attr:`~PIL.Image.ANTIALIAS` doesn't give any advantages after downscaling with libJPEG, which uses supersampling internaly, not convolutions. From c830b1ffcb4abb9b3b7f8e0c5064994b5eed5253 Mon Sep 17 00:00:00 2001 From: homm Date: Mon, 1 Dec 2014 02:18:11 +0300 Subject: [PATCH 5/6] Gaussian blur and unsharp mask chapters --- docs/releasenotes/2.7.rst | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/releasenotes/2.7.rst b/docs/releasenotes/2.7.rst index c9fd9e7af..001ce831f 100644 --- a/docs/releasenotes/2.7.rst +++ b/docs/releasenotes/2.7.rst @@ -103,12 +103,42 @@ which doesn't fit in processor cache. Gaussian blur and unsharp mask ------------------------------ +:py:meth:`~PIL.ImageFilter.GaussianBlur` implementation was replaced with +sequential applying of series of box filters. New implementation is based on +"Theoretical foundations of Gaussian convolution by extended box filtering" from +Mathematical Image Analysis Group. As :py:meth:`~PIL.ImageFilter.UnsharpMask` +implementations uses Gaussian blur internally, all changes from this chapter +alse applyable to it. + Blur radius ^^^^^^^^^^^ +There was an error in previous version of PIL, when blur radius (the standard +deviation of Gaussian) is actually meant blur diameter. +For example for blurring image with actual radius 5 you were forced +to use value 10. This was fixed. For now the meaning of the radius +is the same as in other software. + +If you used a Gaussian blur with some radius value, you need to devide this +value by two. + Blur Performance ^^^^^^^^^^^^^^^^ +Box filter computation time is constant relative to the radius and depends +on source image size only. Because new Gaussian blur implementation +is based on box filter, it's computation time is also doesn't depends on blur +radius. + +If before execution time for the same test image was 1 second for radius 1, +3.6 seconds for radius 10, 17 seconds for 50. Now blur with any radius on same +image is executed for 0.2 seconds. + Blur quality ^^^^^^^^^^^^ +Previous implementation takes in account only source pixels within +2 * standard deviation radius for every destination pixel. This was not enought, +so qulity was worse compared to other Gaussian blur software. + +The new implementation does not have this drawback. From b0152e1e5b4c4bd1ee381f5b2f2b220296b0532c Mon Sep 17 00:00:00 2001 From: homm Date: Mon, 1 Dec 2014 02:23:31 +0300 Subject: [PATCH 6/6] fix spelling --- docs/releasenotes/2.7.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/releasenotes/2.7.rst b/docs/releasenotes/2.7.rst index 001ce831f..8b6daab6c 100644 --- a/docs/releasenotes/2.7.rst +++ b/docs/releasenotes/2.7.rst @@ -15,11 +15,11 @@ Bicubic and Bilinear downscaling ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From very begining :py:attr:`~PIL.Image.BILINEAR` and -:py:attr:`~PIL.Image.BICUBIC` filters was based on afine transformations +:py:attr:`~PIL.Image.BICUBIC` filters was based on affine transformations and uses fixed number of pixels from source image for every destination pixel (that was 2x2 pixels for :py:attr:`~PIL.Image.BILINEAR` and 4x4 for :py:attr:`~PIL.Image.BICUBIC`). This gave an unsatisfied result for downscaling. -At the same time high quality convolutions-based algorithm with flexeible kernel +At the same time high quality convolutions-based algorithm with flexible kernel was used for :py:attr:`~PIL.Image.ANTIALIAS` filter). Starting from 2.7 high quality convolutions-based algorithm is used for all of @@ -36,7 +36,7 @@ New :py:attr:`PIL.Image.LANCZOS` constant was added instead of :py:attr:`~PIL.Image.ANTIALIAS`. When :py:attr:`~PIL.Image.ANTIALIAS` was initially added, it was the only -high-qality filter based on convolutions. It's name was supposed to reflect +high-quality filter based on convolutions. It's name was supposed to reflect this. Starting from 2.7 all resize method are based on convolutions. All of them are antialias from now. And the real name of :py:attr:`~PIL.Image.ANTIALIAS` filter is Lanczos filter. @@ -53,7 +53,7 @@ the same as :py:attr:`~PIL.Image.BILINEAR` due to bug. This was fixed. Bicubic upscaling quality ^^^^^^^^^^^^^^^^^^^^^^^^^ -:py:attr:`~PIL.Image.BICUBIC` filter for affine trnsformations was producing +:py:attr:`~PIL.Image.BICUBIC` filter for affine transformations produced sharp, slightly pixelated image for upscaling. Bicubic for convolutions is more soft. @@ -61,7 +61,7 @@ Resize performance ^^^^^^^^^^^^^^^^^^ In most cases convolution is more expensive algorithm for downscaling because -it tekes in account all pixels of source image. Therefore +it takes in account all pixels of source image. Therefore :py:attr:`~PIL.Image.BILINEAR` and :py:attr:`~PIL.Image.BICUBIC` filters performance can be lower than before. On the other hand quality of :py:attr:`~PIL.Image.BILINEAR` and :py:attr:`~PIL.Image.BICUBIC` was close to @@ -84,7 +84,7 @@ Antialias was chosen because all other filters gave poor quality for reduction. Starting from Pillow 2.7 :py:attr:`~PIL.Image.ANTIALIAS` replaced with :py:attr:`~PIL.Image.BICUBIC`, because it faster and :py:attr:`~PIL.Image.ANTIALIAS` doesn't give any advantages after -downscaling with libJPEG, which uses supersampling internaly, not convolutions. +downscaling with libJPEG, which uses supersampling internally, not convolutions. Image transposing ----------------- @@ -108,7 +108,7 @@ sequential applying of series of box filters. New implementation is based on "Theoretical foundations of Gaussian convolution by extended box filtering" from Mathematical Image Analysis Group. As :py:meth:`~PIL.ImageFilter.UnsharpMask` implementations uses Gaussian blur internally, all changes from this chapter -alse applyable to it. +also applicable to it. Blur radius ^^^^^^^^^^^ @@ -119,7 +119,7 @@ For example for blurring image with actual radius 5 you were forced to use value 10. This was fixed. For now the meaning of the radius is the same as in other software. -If you used a Gaussian blur with some radius value, you need to devide this +If you used a Gaussian blur with some radius value, you need to divide this value by two. Blur Performance @@ -138,7 +138,7 @@ Blur quality ^^^^^^^^^^^^ Previous implementation takes in account only source pixels within -2 * standard deviation radius for every destination pixel. This was not enought, -so qulity was worse compared to other Gaussian blur software. +2 * standard deviation radius for every destination pixel. This was not enough, +so quality was worse compared to other Gaussian blur software. The new implementation does not have this drawback.