mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-30 23:47:27 +03:00 
			
		
		
		
	Merge branch 'master' of github.com:python-pillow/Pillow into winbuild-rewrite
# Conflicts: # .github/workflows/test-windows.yml # winbuild/config.py # winbuild/build_prepare.py
This commit is contained in:
		
						commit
						9640b48040
					
				|  | @ -30,3 +30,9 @@ repos: | ||||||
|     hooks: |     hooks: | ||||||
|       - id: check-merge-conflict |       - id: check-merge-conflict | ||||||
|       - id: check-yaml |       - id: check-yaml | ||||||
|  | 
 | ||||||
|  |   - repo: https://github.com/Lucas-C/pre-commit-hooks | ||||||
|  |     rev: v1.1.7 | ||||||
|  |     hooks: | ||||||
|  |       - id: remove-tabs | ||||||
|  |         exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.opt$) | ||||||
|  |  | ||||||
							
								
								
									
										67
									
								
								CHANGES.rst
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								CHANGES.rst
									
									
									
									
									
								
							|  | @ -5,6 +5,15 @@ Changelog (Pillow) | ||||||
| 7.2.0 (unreleased) | 7.2.0 (unreleased) | ||||||
| ------------------ | ------------------ | ||||||
| 
 | 
 | ||||||
|  | - Fix repeatedly loading .gbr #4620 | ||||||
|  |   [ElinksFr, radarhere] | ||||||
|  | 
 | ||||||
|  | - JPEG: Truncate icclist instead of setting to None #4613 | ||||||
|  |   [homm] | ||||||
|  | 
 | ||||||
|  | - Fixes default offset for Exif #4594 | ||||||
|  |   [rodrigob, radarhere] | ||||||
|  | 
 | ||||||
| - Fixed bug when unpickling TIFF images #4565 | - Fixed bug when unpickling TIFF images #4565 | ||||||
|   [radarhere] |   [radarhere] | ||||||
| 
 | 
 | ||||||
|  | @ -5310,23 +5319,23 @@ Pre-fork | ||||||
|     + Added keyword options to the "save" method.  The following options |     + Added keyword options to the "save" method.  The following options | ||||||
|       are currently supported: |       are currently supported: | ||||||
| 
 | 
 | ||||||
|           format	option		description |           Format    Option          Description | ||||||
|           -------------------------------------------------------- |           -------------------------------------------------------- | ||||||
|           JPEG	optimize	minimize output file at the |           JPEG      optimize        Minimize output file at the | ||||||
|                     expense of compression speed. |                                     expense of compression speed. | ||||||
| 
 | 
 | ||||||
|           JPEG	progressive	enable progressive output. the |           JPEG      progressive     Enable progressive output. | ||||||
|                     option value is ignored. |                                     The option value is ignored. | ||||||
| 
 | 
 | ||||||
|           JPEG	quality		set compression quality (1-100). |           JPEG      quality         Set compression quality (1-100). | ||||||
|                     the default value is 75. |                                     The default value is 75. | ||||||
| 
 | 
 | ||||||
|           JPEG	smooth		smooth dithered images.  value |           JPEG      smooth          Smooth dithered images. | ||||||
|                     is strength (1-100).  default is |                                     Value is strength (1-100). | ||||||
|                     off (0). |                                     Default is off (0). | ||||||
| 
 | 
 | ||||||
|           PNG	optimize	minimize output file at the |           PNG       optimize        Minimize output file at the | ||||||
|                     expense of compression speed. |                                     expense of compression speed. | ||||||
| 
 | 
 | ||||||
|       Expect more options in future releases.  Also note that |       Expect more options in future releases.  Also note that | ||||||
|       file writers silently ignore unknown options. |       file writers silently ignore unknown options. | ||||||
|  | @ -5347,31 +5356,31 @@ Pre-fork | ||||||
|     + Various improvements to the sample scripts: |     + Various improvements to the sample scripts: | ||||||
| 
 | 
 | ||||||
|       "pilconvert"  Carries out some extra tricks in order to make |       "pilconvert"  Carries out some extra tricks in order to make | ||||||
|             the resulting file as small as possible. |                     the resulting file as small as possible. | ||||||
| 
 | 
 | ||||||
|       "explode"	(NEW) Split an image sequence into individual frames. |       "explode"     (NEW) Split an image sequence into individual frames. | ||||||
| 
 | 
 | ||||||
|       "gifmaker"	(NEW) Convert a sequence file into a GIF animation. |       "gifmaker"    (NEW) Convert a sequence file into a GIF animation. | ||||||
|             Note that the GIF encoder create "uncompressed" GIF |                     Note that the GIF encoder create "uncompressed" GIF | ||||||
|             files, so animations created by this script are |                     files, so animations created by this script are | ||||||
|             rather large (typically 2-5 times the compressed |                     rather large (typically 2-5 times the compressed | ||||||
|             sizes). |                     sizes). | ||||||
| 
 | 
 | ||||||
|       "image2py"	(NEW) Convert a single image to a python module.  See |       "image2py"    (NEW) Convert a single image to a python module.  See | ||||||
|             comments in this script for details. |                     comments in this script for details. | ||||||
| 
 | 
 | ||||||
|       "player"	If multiple images are given on the command line, |       "player"      If multiple images are given on the command line, | ||||||
|             they are interpreted as frames in a sequence.  The |                     they are interpreted as frames in a sequence.  The | ||||||
|             script assumes that they all have the same size. |                     script assumes that they all have the same size. | ||||||
|             Also note that this script now can play FLI/FLC |                     Also note that this script now can play FLI/FLC | ||||||
|             and GIF animations. |                     and GIF animations. | ||||||
| 
 | 
 | ||||||
|             This player can also execute embedded Python |             This player can also execute embedded Python | ||||||
|             animation applets (ARG format only). |             animation applets (ARG format only). | ||||||
| 
 | 
 | ||||||
|       "viewer"	Transparent images ("P" with transparency property, |       "viewer"  Transparent images ("P" with transparency property, | ||||||
|             and "RGBA") are superimposed on the standard Tk back- |                 and "RGBA") are superimposed on the standard Tk back- | ||||||
|             ground. |                 ground. | ||||||
| 
 | 
 | ||||||
|     + Fixed colour argument to "new".  For multilayer images, pass a |     + Fixed colour argument to "new".  For multilayer images, pass a | ||||||
|       tuple: (Red, Green, Blue), (Red, Green, Blue, Alpha), or (Cyan, |       tuple: (Red, Green, Blue), (Red, Green, Blue, Alpha), or (Cyan, | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								Tests/images/icc-after-SOF.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/icc-after-SOF.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 212 B | 
|  | @ -15,3 +15,11 @@ def test_gbr_file(): | ||||||
|     with Image.open("Tests/images/gbr.gbr") as im: |     with Image.open("Tests/images/gbr.gbr") as im: | ||||||
|         with Image.open("Tests/images/gbr.png") as target: |         with Image.open("Tests/images/gbr.png") as target: | ||||||
|             assert_image_equal(target, im) |             assert_image_equal(target, im) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def test_multiple_load_operations(): | ||||||
|  |     with Image.open("Tests/images/gbr.gbr") as im: | ||||||
|  |         im.load() | ||||||
|  |         im.load() | ||||||
|  |         with Image.open("Tests/images/gbr.png") as target: | ||||||
|  |             assert_image_equal(target, im) | ||||||
|  |  | ||||||
|  | @ -500,7 +500,7 @@ class TestFileJpeg: | ||||||
|     def test_load_djpeg(self): |     def test_load_djpeg(self): | ||||||
|         with Image.open(TEST_FILE) as img: |         with Image.open(TEST_FILE) as img: | ||||||
|             img.load_djpeg() |             img.load_djpeg() | ||||||
|             assert_image_similar(img, Image.open(TEST_FILE), 0) |             assert_image_similar(img, Image.open(TEST_FILE), 5) | ||||||
| 
 | 
 | ||||||
|     @pytest.mark.skipif(not cjpeg_available(), reason="cjpeg not available") |     @pytest.mark.skipif(not cjpeg_available(), reason="cjpeg not available") | ||||||
|     def test_save_cjpeg(self, tmp_path): |     def test_save_cjpeg(self, tmp_path): | ||||||
|  | @ -689,6 +689,10 @@ class TestFileJpeg: | ||||||
|             apps_13_lengths = [len(v) for k, v in im.applist if k == "APP13"] |             apps_13_lengths = [len(v) for k, v in im.applist if k == "APP13"] | ||||||
|             assert [65504, 24] == apps_13_lengths |             assert [65504, 24] == apps_13_lengths | ||||||
| 
 | 
 | ||||||
|  |     def test_icc_after_SOF(self): | ||||||
|  |         with Image.open("Tests/images/icc-after-SOF.jpg") as im: | ||||||
|  |             assert im.info["icc_profile"] == b"profile" | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| @pytest.mark.skipif(not is_win32(), reason="Windows only") | @pytest.mark.skipif(not is_win32(), reason="Windows only") | ||||||
| @skip_unless_feature("jpg") | @skip_unless_feature("jpg") | ||||||
|  |  | ||||||
|  | @ -174,8 +174,10 @@ def assert_compare_images(a, b, max_average_diff, max_diff=255): | ||||||
|         average_diff = sum(i * num for i, num in enumerate(ch_hist)) / ( |         average_diff = sum(i * num for i, num in enumerate(ch_hist)) / ( | ||||||
|             a.size[0] * a.size[1] |             a.size[0] * a.size[1] | ||||||
|         ) |         ) | ||||||
|         msg = "average pixel value difference {:.4f} > expected {:.4f} " |         msg = ( | ||||||
|         "for '{}' band".format(average_diff, max_average_diff, band) |             "average pixel value difference {:.4f} > expected {:.4f} " | ||||||
|  |             "for '{}' band".format(average_diff, max_average_diff, band) | ||||||
|  |         ) | ||||||
|         assert max_average_diff >= average_diff, msg |         assert max_average_diff >= average_diff, msg | ||||||
| 
 | 
 | ||||||
|         last_diff = [i for i, num in enumerate(ch_hist) if num > 0][-1] |         last_diff = [i for i, num in enumerate(ch_hist) if num > 0][-1] | ||||||
|  |  | ||||||
|  | @ -261,9 +261,9 @@ class TestPyDecoder: | ||||||
|         with Image.open(out) as reloaded: |         with Image.open(out) as reloaded: | ||||||
|             reloaded_exif = reloaded.getexif() |             reloaded_exif = reloaded.getexif() | ||||||
|             assert reloaded_exif[258] == 8 |             assert reloaded_exif[258] == 8 | ||||||
|             assert 40960 not in exif |             assert 40960 not in reloaded_exif | ||||||
|             assert reloaded_exif[40963] == 455 |             assert reloaded_exif[40963] == 455 | ||||||
|             assert exif[11] == "Pillow test" |             assert reloaded_exif[11] == "Pillow test" | ||||||
| 
 | 
 | ||||||
|         with Image.open("Tests/images/no-dpi-in-exif.jpg") as im:  # Big endian |         with Image.open("Tests/images/no-dpi-in-exif.jpg") as im:  # Big endian | ||||||
|             exif = im.getexif() |             exif = im.getexif() | ||||||
|  | @ -281,9 +281,9 @@ class TestPyDecoder: | ||||||
|         with Image.open(out) as reloaded: |         with Image.open(out) as reloaded: | ||||||
|             reloaded_exif = reloaded.getexif() |             reloaded_exif = reloaded.getexif() | ||||||
|             assert reloaded_exif[258] == 8 |             assert reloaded_exif[258] == 8 | ||||||
|             assert 40960 not in exif |             assert 34665 not in reloaded_exif | ||||||
|             assert reloaded_exif[40963] == 455 |             assert reloaded_exif[40963] == 455 | ||||||
|             assert exif[305] == "Pillow test" |             assert reloaded_exif[305] == "Pillow test" | ||||||
| 
 | 
 | ||||||
|     @skip_unless_feature("webp") |     @skip_unless_feature("webp") | ||||||
|     @skip_unless_feature("webp_anim") |     @skip_unless_feature("webp_anim") | ||||||
|  | @ -302,7 +302,7 @@ class TestPyDecoder: | ||||||
|                     reloaded_exif = reloaded.getexif() |                     reloaded_exif = reloaded.getexif() | ||||||
|                     assert reloaded_exif[258] == 8 |                     assert reloaded_exif[258] == 8 | ||||||
|                     assert reloaded_exif[40963] == 455 |                     assert reloaded_exif[40963] == 455 | ||||||
|                     assert exif[305] == "Pillow test" |                     assert reloaded_exif[305] == "Pillow test" | ||||||
| 
 | 
 | ||||||
|             im.save(out, exif=exif) |             im.save(out, exif=exif) | ||||||
|             check_exif() |             check_exif() | ||||||
|  |  | ||||||
|  | @ -4,12 +4,12 @@ | ||||||
| # Use SVN to just fetch a single Git subdirectory | # Use SVN to just fetch a single Git subdirectory | ||||||
| svn_export() | svn_export() | ||||||
| { | { | ||||||
| 	if [ ! -z $1 ]; then |     if [ ! -z $1 ]; then | ||||||
| 		echo "" |         echo "" | ||||||
| 		echo "Retrying svn export..." |         echo "Retrying svn export..." | ||||||
| 		echo "" |         echo "" | ||||||
| 	fi |     fi | ||||||
| 
 | 
 | ||||||
| 	svn export --force https://github.com/python-pillow/pillow-depends/trunk/test_images ../Tests/images |     svn export --force https://github.com/python-pillow/pillow-depends/trunk/test_images ../Tests/images | ||||||
| } | } | ||||||
| svn_export || svn_export retry || svn_export retry || svn_export retry | svn_export || svn_export retry || svn_export retry || svn_export retry | ||||||
|  |  | ||||||
|  | @ -17,8 +17,8 @@ itself. Such plug-ins usually have names like | ||||||
| Pillow decodes files in 2 stages: | Pillow decodes files in 2 stages: | ||||||
| 
 | 
 | ||||||
| 1. It loops over the available image plugins in the loaded order, and | 1. It loops over the available image plugins in the loaded order, and | ||||||
|    calls the plugin's ``accept`` function with the first 16 bytes of |    calls the plugin's ``_accept`` function with the first 16 bytes of | ||||||
|    the file. If the ``accept`` function returns true, the plugin's |    the file. If the ``_accept`` function returns true, the plugin's | ||||||
|    ``_open`` method is called to set up the image metadata and image |    ``_open`` method is called to set up the image metadata and image | ||||||
|    tiles. The ``_open`` method is not for decoding the actual image |    tiles. The ``_open`` method is not for decoding the actual image | ||||||
|    data. |    data. | ||||||
|  | @ -53,6 +53,11 @@ true color. | ||||||
| 
 | 
 | ||||||
|     from PIL import Image, ImageFile |     from PIL import Image, ImageFile | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |     def _accept(prefix): | ||||||
|  |         return prefix[:4] == b"SPAM" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     class SpamImageFile(ImageFile.ImageFile): |     class SpamImageFile(ImageFile.ImageFile): | ||||||
| 
 | 
 | ||||||
|         format = "SPAM" |         format = "SPAM" | ||||||
|  | @ -60,12 +65,7 @@ true color. | ||||||
| 
 | 
 | ||||||
|         def _open(self): |         def _open(self): | ||||||
| 
 | 
 | ||||||
|             # check header |             header = self.fp.read(128).split() | ||||||
|             header = self.fp.read(128) |  | ||||||
|             if header[:4] != b"SPAM": |  | ||||||
|                 raise SyntaxError("not a SPAM file") |  | ||||||
| 
 |  | ||||||
|             header = header.split() |  | ||||||
| 
 | 
 | ||||||
|             # size in pixels (width, height) |             # size in pixels (width, height) | ||||||
|             self._size = int(header[1]), int(header[2]) |             self._size = int(header[1]), int(header[2]) | ||||||
|  | @ -86,7 +86,7 @@ true color. | ||||||
|                 ("raw", (0, 0) + self.size, 128, (self.mode, 0, 1)) |                 ("raw", (0, 0) + self.size, 128, (self.mode, 0, 1)) | ||||||
|             ] |             ] | ||||||
| 
 | 
 | ||||||
|     Image.register_open(SpamImageFile.format, SpamImageFile) |     Image.register_open(SpamImageFile.format, SpamImageFile, _accept) | ||||||
| 
 | 
 | ||||||
|     Image.register_extension(SpamImageFile.format, ".spam") |     Image.register_extension(SpamImageFile.format, ".spam") | ||||||
|     Image.register_extension(SpamImageFile.format, ".spa") # dos version |     Image.register_extension(SpamImageFile.format, ".spa") # dos version | ||||||
|  | @ -179,7 +179,7 @@ complete list, see the table in the :py:mod:`Unpack.c` module. The following | ||||||
| table describes some commonly used **raw modes**: | table describes some commonly used **raw modes**: | ||||||
| 
 | 
 | ||||||
| +-----------+-----------------------------------------------------------------+ | +-----------+-----------------------------------------------------------------+ | ||||||
| | mode	    | description                                                     | | | mode      | description                                                     | | ||||||
| +===========+=================================================================+ | +===========+=================================================================+ | ||||||
| | ``1``     | 1-bit bilevel, stored with the leftmost pixel in the most       | | | ``1``     | 1-bit bilevel, stored with the leftmost pixel in the most       | | ||||||
| |           | significant bit. 0 means black, 1 means white.                  | | |           | significant bit. 0 means black, 1 means white.                  | | ||||||
|  | @ -223,7 +223,7 @@ You can use the ``raw`` decoder to read images where data is packed in any | ||||||
| standard machine data type, using one of the following raw modes: | standard machine data type, using one of the following raw modes: | ||||||
| 
 | 
 | ||||||
| ============ ======================================= | ============ ======================================= | ||||||
| mode	     description | mode         description | ||||||
| ============ ======================================= | ============ ======================================= | ||||||
| ``F``        32-bit native floating point. | ``F``        32-bit native floating point. | ||||||
| ``F;8``      8-bit unsigned integer. | ``F;8``      8-bit unsigned integer. | ||||||
|  |  | ||||||
|  | @ -329,7 +329,7 @@ In Fedora, the command is:: | ||||||
| 
 | 
 | ||||||
| .. Note:: ``redhat-rpm-config`` is required on Fedora 23, but not earlier versions. | .. Note:: ``redhat-rpm-config`` is required on Fedora 23, but not earlier versions. | ||||||
| 
 | 
 | ||||||
| Prerequisites are installed on **Ubuntu 16.04 LTS** with:: | Prerequisites for **Ubuntu 16.04 LTS - 20.04 LTS** are installed with:: | ||||||
| 
 | 
 | ||||||
|     sudo apt-get install libtiff5-dev libjpeg8-dev libopenjp2-7-dev zlib1g-dev \ |     sudo apt-get install libtiff5-dev libjpeg8-dev libopenjp2-7-dev zlib1g-dev \ | ||||||
|         libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python3-tk \ |         libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python3-tk \ | ||||||
|  | @ -434,7 +434,7 @@ These platforms have been reported to work at the versions mentioned. | ||||||
| +----------------------------------+------------------------------+--------------------------------+-----------------------+ | +----------------------------------+------------------------------+--------------------------------+-----------------------+ | ||||||
| |**Operating system**              |**Tested Python versions**    |**Latest tested Pillow version**|**Tested processors**  | | |**Operating system**              |**Tested Python versions**    |**Latest tested Pillow version**|**Tested processors**  | | ||||||
| +----------------------------------+------------------------------+--------------------------------+-----------------------+ | +----------------------------------+------------------------------+--------------------------------+-----------------------+ | ||||||
| | macOS 10.15 Catalina             | 3.5, 3.6, 3.7, 3.8           | 7.0.0                          |x86-64                 | | | macOS 10.15 Catalina             | 3.5, 3.6, 3.7, 3.8           | 7.1.2                          |x86-64                 | | ||||||
| +----------------------------------+------------------------------+--------------------------------+-----------------------+ | +----------------------------------+------------------------------+--------------------------------+-----------------------+ | ||||||
| | macOS 10.14 Mojave               | 2.7, 3.5, 3.6, 3.7           | 6.0.0                          |x86-64                 | | | macOS 10.14 Mojave               | 2.7, 3.5, 3.6, 3.7           | 6.0.0                          |x86-64                 | | ||||||
| |                                  +------------------------------+--------------------------------+                       + | |                                  +------------------------------+--------------------------------+                       + | ||||||
|  |  | ||||||
|  | @ -58,8 +58,8 @@ Functions | ||||||
|         ``warnings.simplefilter('ignore', Image.DecompressionBombWarning)``. See also `the logging |         ``warnings.simplefilter('ignore', Image.DecompressionBombWarning)``. See also `the logging | ||||||
|         documentation`_ to have warnings output to the logging facility instead of stderr. |         documentation`_ to have warnings output to the logging facility instead of stderr. | ||||||
| 
 | 
 | ||||||
| 	.. _decompression bombs: https://en.wikipedia.org/wiki/Zip_bomb |     .. _decompression bombs: https://en.wikipedia.org/wiki/Zip_bomb | ||||||
| 	.. _the logging documentation: https://docs.python.org/3/library/logging.html#integration-with-the-warnings-module |     .. _the logging documentation: https://docs.python.org/3/library/logging.html#integration-with-the-warnings-module | ||||||
| 
 | 
 | ||||||
| Image processing | Image processing | ||||||
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^ | ||||||
|  |  | ||||||
|  | @ -413,10 +413,10 @@ can be easily displayed in a chromaticity diagram, for example). | ||||||
|         with :py:attr:`.intent_supported`. |         with :py:attr:`.intent_supported`. | ||||||
| 
 | 
 | ||||||
|         :param intent: One of ``ImageCms.INTENT_ABSOLUTE_COLORIMETRIC``, |         :param intent: One of ``ImageCms.INTENT_ABSOLUTE_COLORIMETRIC``, | ||||||
|     		   ``ImageCms.INTENT_PERCEPTUAL``, |                ``ImageCms.INTENT_PERCEPTUAL``, | ||||||
|     		   ``ImageCms.INTENT_RELATIVE_COLORIMETRIC`` |                ``ImageCms.INTENT_RELATIVE_COLORIMETRIC`` | ||||||
|     		   and ``ImageCms.INTENT_SATURATION``. |                and ``ImageCms.INTENT_SATURATION``. | ||||||
|         :param direction: One of ``ImageCms.DIRECTION_INPUT``, |         :param direction: One of ``ImageCms.DIRECTION_INPUT``, | ||||||
|     		      ``ImageCms.DIRECTION_OUTPUT`` |                   ``ImageCms.DIRECTION_OUTPUT`` | ||||||
|     		      and ``ImageCms.DIRECTION_PROOF`` |                   and ``ImageCms.DIRECTION_PROOF`` | ||||||
|         :return: Boolean if the intent and direction is supported. |         :return: Boolean if the intent and direction is supported. | ||||||
|  |  | ||||||
|  | @ -9,13 +9,14 @@ this class store bitmap fonts, and are used with the | ||||||
| :py:meth:`PIL.ImageDraw.Draw.text` method. | :py:meth:`PIL.ImageDraw.Draw.text` method. | ||||||
| 
 | 
 | ||||||
| PIL uses its own font file format to store bitmap fonts. You can use the | PIL uses its own font file format to store bitmap fonts. You can use the | ||||||
| :command:`pilfont` utility to convert BDF and PCF font descriptors (X window | :command:`pilfont` utility from | ||||||
| font formats) to this format. | `pillow-scripts <https://pypi.org/project/pillow-scripts/>`_ | ||||||
|  | to convert BDF and PCF font descriptors (X window font formats) to this format. | ||||||
| 
 | 
 | ||||||
| Starting with version 1.1.4, PIL can be configured to support TrueType and | Starting with version 1.1.4, PIL can be configured to support TrueType and | ||||||
| OpenType fonts (as well as other font formats supported by the FreeType | OpenType fonts (as well as other font formats supported by the FreeType | ||||||
| library). For earlier versions, TrueType support is only available as part of | library). For earlier versions, TrueType support is only available as part of | ||||||
| the imToolkit package | the imToolkit package. | ||||||
| 
 | 
 | ||||||
| Example | Example | ||||||
| ------- | ------- | ||||||
|  |  | ||||||
|  | @ -10,3 +10,4 @@ multi_line_output = 3 | ||||||
| 
 | 
 | ||||||
| [tool:pytest] | [tool:pytest] | ||||||
| addopts = -rs | addopts = -rs | ||||||
|  | testpaths = Tests | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								setup.py
									
									
									
									
									
								
							|  | @ -730,7 +730,11 @@ class pil_build_ext(build_ext): | ||||||
|         if struct.unpack("h", b"\0\1")[0] == 1: |         if struct.unpack("h", b"\0\1")[0] == 1: | ||||||
|             defs.append(("WORDS_BIGENDIAN", None)) |             defs.append(("WORDS_BIGENDIAN", None)) | ||||||
| 
 | 
 | ||||||
|         if sys.platform == "win32" and not (PLATFORM_PYPY or PLATFORM_MINGW): |         if ( | ||||||
|  |             sys.platform == "win32" | ||||||
|  |             and sys.version_info < (3, 9) | ||||||
|  |             and not (PLATFORM_PYPY or PLATFORM_MINGW) | ||||||
|  |         ): | ||||||
|             defs.append(("PILLOW_VERSION", '"\\"%s\\""' % PILLOW_VERSION)) |             defs.append(("PILLOW_VERSION", '"\\"%s\\""' % PILLOW_VERSION)) | ||||||
|         else: |         else: | ||||||
|             defs.append(("PILLOW_VERSION", '"%s"' % PILLOW_VERSION)) |             defs.append(("PILLOW_VERSION", '"%s"' % PILLOW_VERSION)) | ||||||
|  |  | ||||||
|  | @ -84,6 +84,10 @@ class GbrImageFile(ImageFile.ImageFile): | ||||||
|         self._data_size = width * height * color_depth |         self._data_size = width * height * color_depth | ||||||
| 
 | 
 | ||||||
|     def load(self): |     def load(self): | ||||||
|  |         if self.im: | ||||||
|  |             # Already loaded | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|         self.im = Image.core.new(self.mode, self.size) |         self.im = Image.core.new(self.mode, self.size) | ||||||
|         self.frombytes(self.fp.read(self._data_size)) |         self.frombytes(self.fp.read(self._data_size)) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3281,7 +3281,7 @@ class Exif(MutableMapping): | ||||||
|             self._data.update(ifd) |             self._data.update(ifd) | ||||||
|             self._ifds[0x8769] = ifd |             self._ifds[0x8769] = ifd | ||||||
| 
 | 
 | ||||||
|     def tobytes(self, offset=0): |     def tobytes(self, offset=8): | ||||||
|         from . import TiffImagePlugin |         from . import TiffImagePlugin | ||||||
| 
 | 
 | ||||||
|         if self.endian == "<": |         if self.endian == "<": | ||||||
|  |  | ||||||
|  | @ -54,7 +54,7 @@ def invert(image): | ||||||
| def lighter(image1, image2): | def lighter(image1, image2): | ||||||
|     """ |     """ | ||||||
|     Compares the two images, pixel by pixel, and returns a new image containing |     Compares the two images, pixel by pixel, and returns a new image containing | ||||||
|     the lighter values. At least one of the images must have mode "1". |     the lighter values. | ||||||
| 
 | 
 | ||||||
|     .. code-block:: python |     .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  | @ -71,7 +71,7 @@ def lighter(image1, image2): | ||||||
| def darker(image1, image2): | def darker(image1, image2): | ||||||
|     """ |     """ | ||||||
|     Compares the two images, pixel by pixel, and returns a new image containing |     Compares the two images, pixel by pixel, and returns a new image containing | ||||||
|     the darker values. At least one of the images must have mode "1". |     the darker values. | ||||||
| 
 | 
 | ||||||
|     .. code-block:: python |     .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  | @ -88,7 +88,7 @@ def darker(image1, image2): | ||||||
| def difference(image1, image2): | def difference(image1, image2): | ||||||
|     """ |     """ | ||||||
|     Returns the absolute value of the pixel-by-pixel difference between the two |     Returns the absolute value of the pixel-by-pixel difference between the two | ||||||
|     images. At least one of the images must have mode "1". |     images. | ||||||
| 
 | 
 | ||||||
|     .. code-block:: python |     .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  | @ -107,8 +107,7 @@ def multiply(image1, image2): | ||||||
|     Superimposes two images on top of each other. |     Superimposes two images on top of each other. | ||||||
| 
 | 
 | ||||||
|     If you multiply an image with a solid black image, the result is black. If |     If you multiply an image with a solid black image, the result is black. If | ||||||
|     you multiply with a solid white image, the image is unaffected. At least |     you multiply with a solid white image, the image is unaffected. | ||||||
|     one of the images must have mode "1". |  | ||||||
| 
 | 
 | ||||||
|     .. code-block:: python |     .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  | @ -124,8 +123,7 @@ def multiply(image1, image2): | ||||||
| 
 | 
 | ||||||
| def screen(image1, image2): | def screen(image1, image2): | ||||||
|     """ |     """ | ||||||
|     Superimposes two inverted images on top of each other. At least one of the |     Superimposes two inverted images on top of each other. | ||||||
|     images must have mode "1". |  | ||||||
| 
 | 
 | ||||||
|     .. code-block:: python |     .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  | @ -179,7 +177,6 @@ def add(image1, image2, scale=1.0, offset=0): | ||||||
|     """ |     """ | ||||||
|     Adds two images, dividing the result by scale and adding the |     Adds two images, dividing the result by scale and adding the | ||||||
|     offset. If omitted, scale defaults to 1.0, and offset to 0.0. |     offset. If omitted, scale defaults to 1.0, and offset to 0.0. | ||||||
|     At least one of the images must have mode "1". |  | ||||||
| 
 | 
 | ||||||
|     .. code-block:: python |     .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  | @ -196,8 +193,7 @@ def add(image1, image2, scale=1.0, offset=0): | ||||||
| def subtract(image1, image2, scale=1.0, offset=0): | def subtract(image1, image2, scale=1.0, offset=0): | ||||||
|     """ |     """ | ||||||
|     Subtracts two images, dividing the result by scale and adding the offset. |     Subtracts two images, dividing the result by scale and adding the offset. | ||||||
|     If omitted, scale defaults to 1.0, and offset to 0.0. At least one of the |     If omitted, scale defaults to 1.0, and offset to 0.0. | ||||||
|     images must have mode "1". |  | ||||||
| 
 | 
 | ||||||
|     .. code-block:: python |     .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  | @ -212,8 +208,7 @@ def subtract(image1, image2, scale=1.0, offset=0): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def add_modulo(image1, image2): | def add_modulo(image1, image2): | ||||||
|     """Add two images, without clipping the result. At least one of the images |     """Add two images, without clipping the result. | ||||||
|     must have mode "1". |  | ||||||
| 
 | 
 | ||||||
|     .. code-block:: python |     .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  | @ -228,8 +223,7 @@ def add_modulo(image1, image2): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def subtract_modulo(image1, image2): | def subtract_modulo(image1, image2): | ||||||
|     """Subtract two images, without clipping the result. At least one of the |     """Subtract two images, without clipping the result. | ||||||
|     images must have mode "1". |  | ||||||
| 
 | 
 | ||||||
|     .. code-block:: python |     .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  | @ -244,8 +238,12 @@ def subtract_modulo(image1, image2): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def logical_and(image1, image2): | def logical_and(image1, image2): | ||||||
|     """Logical AND between two images. At least one of the images must have |     """Logical AND between two images. | ||||||
|     mode "1". | 
 | ||||||
|  |     Both of the images must have mode "1". If you would like to perform a | ||||||
|  |     logical AND on an image with a mode other than "1", try | ||||||
|  |     :py:meth:`~PIL.ImageChops.multiply` instead, using a black-and-white mask | ||||||
|  |     as the second image. | ||||||
| 
 | 
 | ||||||
|     .. code-block:: python |     .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  | @ -260,8 +258,9 @@ def logical_and(image1, image2): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def logical_or(image1, image2): | def logical_or(image1, image2): | ||||||
|     """Logical OR between two images. At least one of the images must have |     """Logical OR between two images. | ||||||
|     mode "1". | 
 | ||||||
|  |     Both of the images must have mode "1". | ||||||
| 
 | 
 | ||||||
|     .. code-block:: python |     .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  | @ -276,8 +275,9 @@ def logical_or(image1, image2): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def logical_xor(image1, image2): | def logical_xor(image1, image2): | ||||||
|     """Logical XOR between two images. At least one of the images must have |     """Logical XOR between two images. | ||||||
|     mode "1". | 
 | ||||||
|  |     Both of the images must have mode "1". | ||||||
| 
 | 
 | ||||||
|     .. code-block:: python |     .. code-block:: python | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -221,7 +221,7 @@ def SOF(self, marker): | ||||||
|         else: |         else: | ||||||
|             icc_profile = None  # wrong number of fragments |             icc_profile = None  # wrong number of fragments | ||||||
|         self.info["icc_profile"] = icc_profile |         self.info["icc_profile"] = icc_profile | ||||||
|         self.icclist = None |         self.icclist = [] | ||||||
| 
 | 
 | ||||||
|     for i in range(6, len(s), 3): |     for i in range(6, len(s), 3): | ||||||
|         t = s[i : i + 3] |         t = s[i : i + 3] | ||||||
|  | @ -593,9 +593,9 @@ def convert_dict_qtables(qtables): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_sampling(im): | def get_sampling(im): | ||||||
|     # There's no subsampling when image have only 1 layer |     # There's no subsampling when images have only 1 layer | ||||||
|     # (grayscale images) or when they are CMYK (4 layers), |     # (grayscale images) or when they are CMYK (4 layers), | ||||||
|     # so set subsampling to default value. |     # so set subsampling to the default value. | ||||||
|     # |     # | ||||||
|     # NOTE: currently Pillow can't encode JPEG to YCCK format. |     # NOTE: currently Pillow can't encode JPEG to YCCK format. | ||||||
|     # If YCCK support is added in the future, subsampling code will have |     # If YCCK support is added in the future, subsampling code will have | ||||||
|  |  | ||||||
|  | @ -68,8 +68,9 @@ ImagingFind(const char* name) | ||||||
| #else | #else | ||||||
|     id = atol(name); |     id = atol(name); | ||||||
| #endif | #endif | ||||||
|     if (!id) |     if (!id) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return (Imaging) id; |     return (Imaging) id; | ||||||
| } | } | ||||||
|  | @ -119,10 +120,11 @@ PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp, | ||||||
|         block.offset[0] = 0; |         block.offset[0] = 0; | ||||||
|         block.offset[1] = 1; |         block.offset[1] = 1; | ||||||
|         block.offset[2] = 2; |         block.offset[2] = 2; | ||||||
|         if (strcmp(im->mode, "RGBA") == 0) |         if (strcmp(im->mode, "RGBA") == 0) { | ||||||
|             block.offset[3] = 3; /* alpha (or reserved, under 8.2) */ |             block.offset[3] = 3; /* alpha (or reserved, under 8.2) */ | ||||||
|         else |         } else { | ||||||
|             block.offset[3] = 0; /* no alpha */ |             block.offset[3] = 0; /* no alpha */ | ||||||
|  |         } | ||||||
|     } else { |     } else { | ||||||
|         TCL_APPEND_RESULT(interp, "Bad mode", (char*) NULL); |         TCL_APPEND_RESULT(interp, "Bad mode", (char*) NULL); | ||||||
|         return TCL_ERROR; |         return TCL_ERROR; | ||||||
|  | @ -136,10 +138,11 @@ PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp, | ||||||
|     if (TK_LT_85) { /* Tk 8.4 */ |     if (TK_LT_85) { /* Tk 8.4 */ | ||||||
|         TK_PHOTO_PUT_BLOCK_84(photo, &block, 0, 0, block.width, block.height, |         TK_PHOTO_PUT_BLOCK_84(photo, &block, 0, 0, block.width, block.height, | ||||||
|                 TK_PHOTO_COMPOSITE_SET); |                 TK_PHOTO_COMPOSITE_SET); | ||||||
|         if (strcmp(im->mode, "RGBA") == 0) |         if (strcmp(im->mode, "RGBA") == 0) { | ||||||
|             /* Tk workaround: we need apply ToggleComplexAlphaIfNeeded */ |             /* Tk workaround: we need apply ToggleComplexAlphaIfNeeded */ | ||||||
|             /* (fixed in Tk 8.5a3) */ |             /* (fixed in Tk 8.5a3) */ | ||||||
|             TK_PHOTO_SET_SIZE_84(photo, block.width, block.height); |             TK_PHOTO_SET_SIZE_84(photo, block.width, block.height); | ||||||
|  |         } | ||||||
|     } else { |     } else { | ||||||
|         /* Tk >=8.5 */ |         /* Tk >=8.5 */ | ||||||
|         TK_PHOTO_PUT_BLOCK_85(interp, photo, &block, 0, 0, block.width, |         TK_PHOTO_PUT_BLOCK_85(interp, photo, &block, 0, 0, block.width, | ||||||
|  |  | ||||||
							
								
								
									
										585
									
								
								src/_imaging.c
									
									
									
									
									
								
							
							
						
						
									
										585
									
								
								src/_imaging.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -88,8 +88,9 @@ cms_profile_new(cmsHPROFILE profile) | ||||||
|     CmsProfileObject* self; |     CmsProfileObject* self; | ||||||
| 
 | 
 | ||||||
|     self = PyObject_New(CmsProfileObject, &CmsProfile_Type); |     self = PyObject_New(CmsProfileObject, &CmsProfile_Type); | ||||||
|     if (!self) |     if (!self) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     self->profile = profile; |     self->profile = profile; | ||||||
| 
 | 
 | ||||||
|  | @ -102,8 +103,9 @@ cms_profile_open(PyObject* self, PyObject* args) | ||||||
|     cmsHPROFILE hProfile; |     cmsHPROFILE hProfile; | ||||||
| 
 | 
 | ||||||
|     char* sProfile; |     char* sProfile; | ||||||
|     if (!PyArg_ParseTuple(args, "s:profile_open", &sProfile)) |     if (!PyArg_ParseTuple(args, "s:profile_open", &sProfile)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     hProfile = cmsOpenProfileFromFile(sProfile, "r"); |     hProfile = cmsOpenProfileFromFile(sProfile, "r"); | ||||||
|     if (!hProfile) { |     if (!hProfile) { | ||||||
|  | @ -121,8 +123,9 @@ cms_profile_fromstring(PyObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|     char* pProfile; |     char* pProfile; | ||||||
|     Py_ssize_t nProfile; |     Py_ssize_t nProfile; | ||||||
|     if (!PyArg_ParseTuple(args, "y#:profile_frombytes", &pProfile, &nProfile)) |     if (!PyArg_ParseTuple(args, "y#:profile_frombytes", &pProfile, &nProfile)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     hProfile = cmsOpenProfileFromMem(pProfile, nProfile); |     hProfile = cmsOpenProfileFromMem(pProfile, nProfile); | ||||||
|     if (!hProfile) { |     if (!hProfile) { | ||||||
|  | @ -198,8 +201,9 @@ cms_transform_new(cmsHTRANSFORM transform, char* mode_in, char* mode_out) | ||||||
|     CmsTransformObject* self; |     CmsTransformObject* self; | ||||||
| 
 | 
 | ||||||
|     self = PyObject_New(CmsTransformObject, &CmsTransform_Type); |     self = PyObject_New(CmsTransformObject, &CmsTransform_Type); | ||||||
|     if (!self) |     if (!self) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     self->transform = transform; |     self->transform = transform; | ||||||
| 
 | 
 | ||||||
|  | @ -292,17 +296,19 @@ pyCMSgetAuxChannelChannel (cmsUInt32Number format, int auxChannelNdx) | ||||||
| 
 | 
 | ||||||
|     if (T_SWAPFIRST(format) && T_DOSWAP(format)) { |     if (T_SWAPFIRST(format) && T_DOSWAP(format)) { | ||||||
|         // reverse order, before anything but last extra is shifted last
 |         // reverse order, before anything but last extra is shifted last
 | ||||||
|         if (auxChannelNdx == numExtras - 1) |         if (auxChannelNdx == numExtras - 1) { | ||||||
|             return numColors + numExtras - 1; |             return numColors + numExtras - 1; | ||||||
|         else |         } else { | ||||||
|             return numExtras - 2 - auxChannelNdx; |             return numExtras - 2 - auxChannelNdx; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     else if (T_SWAPFIRST(format)) { |     else if (T_SWAPFIRST(format)) { | ||||||
|         // in order, after color channels, but last extra is shifted to first
 |         // in order, after color channels, but last extra is shifted to first
 | ||||||
|         if (auxChannelNdx == numExtras - 1) |         if (auxChannelNdx == numExtras - 1) { | ||||||
|             return 0; |             return 0; | ||||||
|         else |         } else { | ||||||
|             return numColors + 1 + auxChannelNdx; |             return numColors + 1 + auxChannelNdx; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     else if (T_DOSWAP(format)) { |     else if (T_DOSWAP(format)) { | ||||||
|         // reverse order, before anything
 |         // reverse order, before anything
 | ||||||
|  | @ -330,23 +336,26 @@ pyCMScopyAux (cmsHTRANSFORM hTransform, Imaging imDst, const Imaging imSrc) | ||||||
|     int e; |     int e; | ||||||
| 
 | 
 | ||||||
|     // trivially copied
 |     // trivially copied
 | ||||||
|     if (imDst == imSrc) |     if (imDst == imSrc) { | ||||||
|         return; |         return; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     dstLCMSFormat = cmsGetTransformOutputFormat(hTransform); |     dstLCMSFormat = cmsGetTransformOutputFormat(hTransform); | ||||||
|     srcLCMSFormat = cmsGetTransformInputFormat(hTransform); |     srcLCMSFormat = cmsGetTransformInputFormat(hTransform); | ||||||
| 
 | 
 | ||||||
|     // currently, all Pillow formats are chunky formats, but check it anyway
 |     // currently, all Pillow formats are chunky formats, but check it anyway
 | ||||||
|     if (T_PLANAR(dstLCMSFormat) || T_PLANAR(srcLCMSFormat)) |     if (T_PLANAR(dstLCMSFormat) || T_PLANAR(srcLCMSFormat)) { | ||||||
|         return; |         return; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // copy only if channel format is identical, except OPTIMIZED is ignored as it
 |     // copy only if channel format is identical, except OPTIMIZED is ignored as it
 | ||||||
|     // does not affect the aux channel
 |     // does not affect the aux channel
 | ||||||
|     if (T_FLOAT(dstLCMSFormat) != T_FLOAT(srcLCMSFormat) |     if (T_FLOAT(dstLCMSFormat) != T_FLOAT(srcLCMSFormat) | ||||||
|         || T_FLAVOR(dstLCMSFormat) != T_FLAVOR(srcLCMSFormat) |         || T_FLAVOR(dstLCMSFormat) != T_FLAVOR(srcLCMSFormat) | ||||||
|         || T_ENDIAN16(dstLCMSFormat) != T_ENDIAN16(srcLCMSFormat) |         || T_ENDIAN16(dstLCMSFormat) != T_ENDIAN16(srcLCMSFormat) | ||||||
|         || T_BYTES(dstLCMSFormat) != T_BYTES(srcLCMSFormat)) |         || T_BYTES(dstLCMSFormat) != T_BYTES(srcLCMSFormat)) { | ||||||
|       return; |       return; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     numSrcExtras = T_EXTRA(srcLCMSFormat); |     numSrcExtras = T_EXTRA(srcLCMSFormat); | ||||||
|     numDstExtras = T_EXTRA(dstLCMSFormat); |     numDstExtras = T_EXTRA(dstLCMSFormat); | ||||||
|  | @ -367,8 +376,9 @@ pyCMScopyAux (cmsHTRANSFORM hTransform, Imaging imDst, const Imaging imSrc) | ||||||
|             char* pDstExtras = imDst->image[y] + dstChannel * channelSize; |             char* pDstExtras = imDst->image[y] + dstChannel * channelSize; | ||||||
|             const char* pSrcExtras = imSrc->image[y] + srcChannel * channelSize; |             const char* pSrcExtras = imSrc->image[y] + srcChannel * channelSize; | ||||||
| 
 | 
 | ||||||
|             for (x = 0; x < xSize; x++) |             for (x = 0; x < xSize; x++) { | ||||||
|                 memcpy(pDstExtras + x * dstChunkSize, pSrcExtras + x * srcChunkSize, channelSize); |                 memcpy(pDstExtras + x * dstChunkSize, pSrcExtras + x * srcChunkSize, channelSize); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -378,14 +388,16 @@ pyCMSdoTransform(Imaging im, Imaging imOut, cmsHTRANSFORM hTransform) | ||||||
| { | { | ||||||
|     int i; |     int i; | ||||||
| 
 | 
 | ||||||
|     if (im->xsize > imOut->xsize || im->ysize > imOut->ysize) |     if (im->xsize > imOut->xsize || im->ysize > imOut->ysize) { | ||||||
|         return -1; |         return -1; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     Py_BEGIN_ALLOW_THREADS |     Py_BEGIN_ALLOW_THREADS | ||||||
| 
 | 
 | ||||||
|     // transform color channels only
 |     // transform color channels only
 | ||||||
|     for (i = 0; i < im->ysize; i++) |     for (i = 0; i < im->ysize; i++) { | ||||||
|         cmsDoTransform(hTransform, im->image[i], imOut->image[i], im->xsize); |         cmsDoTransform(hTransform, im->image[i], imOut->image[i], im->xsize); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // lcms by default does nothing to the auxiliary channels leaving those
 |     // lcms by default does nothing to the auxiliary channels leaving those
 | ||||||
|     // unchanged. To do "the right thing" here, i.e. maintain identical results
 |     // unchanged. To do "the right thing" here, i.e. maintain identical results
 | ||||||
|  | @ -417,8 +429,9 @@ _buildTransform(cmsHPROFILE hInputProfile, cmsHPROFILE hOutputProfile, char *sIn | ||||||
| 
 | 
 | ||||||
|     Py_END_ALLOW_THREADS |     Py_END_ALLOW_THREADS | ||||||
| 
 | 
 | ||||||
|     if (!hTransform) |     if (!hTransform) { | ||||||
|         PyErr_SetString(PyExc_ValueError, "cannot build transform"); |         PyErr_SetString(PyExc_ValueError, "cannot build transform"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return hTransform; /* if NULL, an exception is set */ |     return hTransform; /* if NULL, an exception is set */ | ||||||
| } | } | ||||||
|  | @ -442,8 +455,9 @@ _buildProofTransform(cmsHPROFILE hInputProfile, cmsHPROFILE hOutputProfile, cmsH | ||||||
| 
 | 
 | ||||||
|     Py_END_ALLOW_THREADS |     Py_END_ALLOW_THREADS | ||||||
| 
 | 
 | ||||||
|     if (!hTransform) |     if (!hTransform) { | ||||||
|         PyErr_SetString(PyExc_ValueError, "cannot build proof transform"); |         PyErr_SetString(PyExc_ValueError, "cannot build proof transform"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return hTransform; /* if NULL, an exception is set */ |     return hTransform; /* if NULL, an exception is set */ | ||||||
| } | } | ||||||
|  | @ -462,13 +476,15 @@ buildTransform(PyObject *self, PyObject *args) { | ||||||
| 
 | 
 | ||||||
|     cmsHTRANSFORM transform = NULL; |     cmsHTRANSFORM transform = NULL; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "O!O!ss|ii:buildTransform", &CmsProfile_Type, &pInputProfile, &CmsProfile_Type, &pOutputProfile, &sInMode, &sOutMode, &iRenderingIntent, &cmsFLAGS)) |     if (!PyArg_ParseTuple(args, "O!O!ss|ii:buildTransform", &CmsProfile_Type, &pInputProfile, &CmsProfile_Type, &pOutputProfile, &sInMode, &sOutMode, &iRenderingIntent, &cmsFLAGS)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     transform = _buildTransform(pInputProfile->profile, pOutputProfile->profile, sInMode, sOutMode, iRenderingIntent, cmsFLAGS); |     transform = _buildTransform(pInputProfile->profile, pOutputProfile->profile, sInMode, sOutMode, iRenderingIntent, cmsFLAGS); | ||||||
| 
 | 
 | ||||||
|     if (!transform) |     if (!transform) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return cms_transform_new(transform, sInMode, sOutMode); |     return cms_transform_new(transform, sInMode, sOutMode); | ||||||
| } | } | ||||||
|  | @ -487,13 +503,15 @@ buildProofTransform(PyObject *self, PyObject *args) | ||||||
| 
 | 
 | ||||||
|     cmsHTRANSFORM transform = NULL; |     cmsHTRANSFORM transform = NULL; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "O!O!O!ss|iii:buildProofTransform", &CmsProfile_Type, &pInputProfile, &CmsProfile_Type, &pOutputProfile, &CmsProfile_Type, &pProofProfile, &sInMode, &sOutMode, &iRenderingIntent, &iProofIntent, &cmsFLAGS)) |     if (!PyArg_ParseTuple(args, "O!O!O!ss|iii:buildProofTransform", &CmsProfile_Type, &pInputProfile, &CmsProfile_Type, &pOutputProfile, &CmsProfile_Type, &pProofProfile, &sInMode, &sOutMode, &iRenderingIntent, &iProofIntent, &cmsFLAGS)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     transform = _buildProofTransform(pInputProfile->profile, pOutputProfile->profile, pProofProfile->profile, sInMode, sOutMode, iRenderingIntent, iProofIntent, cmsFLAGS); |     transform = _buildProofTransform(pInputProfile->profile, pOutputProfile->profile, pProofProfile->profile, sInMode, sOutMode, iRenderingIntent, iProofIntent, cmsFLAGS); | ||||||
| 
 | 
 | ||||||
|     if (!transform) |     if (!transform) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return cms_transform_new(transform, sInMode, sOutMode); |     return cms_transform_new(transform, sInMode, sOutMode); | ||||||
| 
 | 
 | ||||||
|  | @ -509,8 +527,9 @@ cms_transform_apply(CmsTransformObject *self, PyObject *args) | ||||||
| 
 | 
 | ||||||
|     int result; |     int result; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "nn:apply", &idIn, &idOut)) |     if (!PyArg_ParseTuple(args, "nn:apply", &idIn, &idOut)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     im = (Imaging) idIn; |     im = (Imaging) idIn; | ||||||
|     imOut = (Imaging) idOut; |     imOut = (Imaging) idOut; | ||||||
|  | @ -532,8 +551,9 @@ createProfile(PyObject *self, PyObject *args) | ||||||
|     cmsCIExyY whitePoint; |     cmsCIExyY whitePoint; | ||||||
|     cmsBool result; |     cmsBool result; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "s|d:createProfile", &sColorSpace, &dColorTemp)) |     if (!PyArg_ParseTuple(args, "s|d:createProfile", &sColorSpace, &dColorTemp)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (strcmp(sColorSpace, "LAB") == 0) { |     if (strcmp(sColorSpace, "LAB") == 0) { | ||||||
|         if (dColorTemp > 0.0) { |         if (dColorTemp > 0.0) { | ||||||
|  | @ -575,8 +595,9 @@ cms_profile_is_intent_supported(CmsProfileObject *self, PyObject *args) | ||||||
| 
 | 
 | ||||||
|     int intent; |     int intent; | ||||||
|     int direction; |     int direction; | ||||||
|     if (!PyArg_ParseTuple(args, "ii:is_intent_supported", &intent, &direction)) |     if (!PyArg_ParseTuple(args, "ii:is_intent_supported", &intent, &direction)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     result = cmsIsIntentSupported(self->profile, intent, direction); |     result = cmsIsIntentSupported(self->profile, intent, direction); | ||||||
| 
 | 
 | ||||||
|  | @ -602,8 +623,9 @@ cms_get_display_profile_win32(PyObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|     HANDLE handle = 0; |     HANDLE handle = 0; | ||||||
|     int is_dc = 0; |     int is_dc = 0; | ||||||
|     if (!PyArg_ParseTuple(args, "|" F_HANDLE "i:get_display_profile", &handle, &is_dc)) |     if (!PyArg_ParseTuple(args, "|" F_HANDLE "i:get_display_profile", &handle, &is_dc)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     filename_size = sizeof(filename); |     filename_size = sizeof(filename); | ||||||
| 
 | 
 | ||||||
|  | @ -615,8 +637,9 @@ cms_get_display_profile_win32(PyObject* self, PyObject* args) | ||||||
|         ReleaseDC((HWND) handle, dc); |         ReleaseDC((HWND) handle, dc); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (ok) |     if (ok) { | ||||||
|         return PyUnicode_FromStringAndSize(filename, filename_size-1); |         return PyUnicode_FromStringAndSize(filename, filename_size-1); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     Py_INCREF(Py_None); |     Py_INCREF(Py_None); | ||||||
|     return Py_None; |     return Py_None; | ||||||
|  | @ -745,10 +768,11 @@ _profile_read_ciexyz(CmsProfileObject* self, cmsTagSignature info, int multi) | ||||||
|         Py_INCREF(Py_None); |         Py_INCREF(Py_None); | ||||||
|         return Py_None; |         return Py_None; | ||||||
|     } |     } | ||||||
|     if (multi) |     if (multi) { | ||||||
|         return _xyz3_py(XYZ); |         return _xyz3_py(XYZ); | ||||||
|     else |     } else { | ||||||
|         return _xyz_py(XYZ); |         return _xyz_py(XYZ); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static PyObject* | static PyObject* | ||||||
|  | @ -826,8 +850,9 @@ static cmsBool _calculate_rgb_primaries(CmsProfileObject* self, cmsCIEXYZTRIPLE* | ||||||
| 
 | 
 | ||||||
|     // double array of RGB values with max on each identity
 |     // double array of RGB values with max on each identity
 | ||||||
|     hXYZ = cmsCreateXYZProfile(); |     hXYZ = cmsCreateXYZProfile(); | ||||||
|     if (hXYZ == NULL) |     if (hXYZ == NULL) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // transform from our profile to XYZ using doubles for highest precision
 |     // transform from our profile to XYZ using doubles for highest precision
 | ||||||
|     hTransform = cmsCreateTransform(self->profile, TYPE_RGB_DBL, |     hTransform = cmsCreateTransform(self->profile, TYPE_RGB_DBL, | ||||||
|  | @ -835,8 +860,9 @@ static cmsBool _calculate_rgb_primaries(CmsProfileObject* self, cmsCIEXYZTRIPLE* | ||||||
|                                     INTENT_RELATIVE_COLORIMETRIC, |                                     INTENT_RELATIVE_COLORIMETRIC, | ||||||
|                                     cmsFLAGS_NOCACHE | cmsFLAGS_NOOPTIMIZE); |                                     cmsFLAGS_NOCACHE | cmsFLAGS_NOOPTIMIZE); | ||||||
|     cmsCloseProfile(hXYZ); |     cmsCloseProfile(hXYZ); | ||||||
|     if (hTransform == NULL) |     if (hTransform == NULL) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     cmsDoTransform(hTransform, (void*) input, result, 3); |     cmsDoTransform(hTransform, (void*) input, result, 3); | ||||||
|     cmsDeleteTransform(hTransform); |     cmsDeleteTransform(hTransform); | ||||||
|  | @ -881,8 +907,9 @@ _is_intent_supported(CmsProfileObject* self, int clut) | ||||||
| 
 | 
 | ||||||
|         /* Only valid for ICC Intents (otherwise we read invalid memory in lcms cmsio1.c). */ |         /* Only valid for ICC Intents (otherwise we read invalid memory in lcms cmsio1.c). */ | ||||||
|         if (!(intent == INTENT_PERCEPTUAL || intent == INTENT_RELATIVE_COLORIMETRIC |         if (!(intent == INTENT_PERCEPTUAL || intent == INTENT_RELATIVE_COLORIMETRIC | ||||||
|             || intent == INTENT_SATURATION || intent == INTENT_ABSOLUTE_COLORIMETRIC)) |             || intent == INTENT_SATURATION || intent == INTENT_ABSOLUTE_COLORIMETRIC)) { | ||||||
|             continue; |             continue; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         id = PyLong_FromLong((long) intent); |         id = PyLong_FromLong((long) intent); | ||||||
|         entry = Py_BuildValue("(OOO)", |         entry = Py_BuildValue("(OOO)", | ||||||
|  | @ -1276,8 +1303,9 @@ cms_profile_getattr_red_primary(CmsProfileObject* self, void* closure) | ||||||
|     cmsBool result = 0; |     cmsBool result = 0; | ||||||
|     cmsCIEXYZTRIPLE primaries; |     cmsCIEXYZTRIPLE primaries; | ||||||
| 
 | 
 | ||||||
|     if (cmsIsMatrixShaper(self->profile)) |     if (cmsIsMatrixShaper(self->profile)) { | ||||||
|         result = _calculate_rgb_primaries(self, &primaries); |         result = _calculate_rgb_primaries(self, &primaries); | ||||||
|  |     } | ||||||
|     if (! result) { |     if (! result) { | ||||||
|         Py_INCREF(Py_None); |         Py_INCREF(Py_None); | ||||||
|         return Py_None; |         return Py_None; | ||||||
|  | @ -1292,8 +1320,9 @@ cms_profile_getattr_green_primary(CmsProfileObject* self, void* closure) | ||||||
|     cmsBool result = 0; |     cmsBool result = 0; | ||||||
|     cmsCIEXYZTRIPLE primaries; |     cmsCIEXYZTRIPLE primaries; | ||||||
| 
 | 
 | ||||||
|     if (cmsIsMatrixShaper(self->profile)) |     if (cmsIsMatrixShaper(self->profile)) { | ||||||
|         result = _calculate_rgb_primaries(self, &primaries); |         result = _calculate_rgb_primaries(self, &primaries); | ||||||
|  |     } | ||||||
|     if (! result) { |     if (! result) { | ||||||
|         Py_INCREF(Py_None); |         Py_INCREF(Py_None); | ||||||
|         return Py_None; |         return Py_None; | ||||||
|  | @ -1308,8 +1337,9 @@ cms_profile_getattr_blue_primary(CmsProfileObject* self, void* closure) | ||||||
|     cmsBool result = 0; |     cmsBool result = 0; | ||||||
|     cmsCIEXYZTRIPLE primaries; |     cmsCIEXYZTRIPLE primaries; | ||||||
| 
 | 
 | ||||||
|     if (cmsIsMatrixShaper(self->profile)) |     if (cmsIsMatrixShaper(self->profile)) { | ||||||
|         result = _calculate_rgb_primaries(self, &primaries); |         result = _calculate_rgb_primaries(self, &primaries); | ||||||
|  |     } | ||||||
|     if (! result) { |     if (! result) { | ||||||
|         Py_INCREF(Py_None); |         Py_INCREF(Py_None); | ||||||
|         return Py_None; |         return Py_None; | ||||||
|  | @ -1387,12 +1417,13 @@ cms_profile_getattr_icc_measurement_condition (CmsProfileObject* self, void* clo | ||||||
|         return Py_None; |         return Py_None; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (mc->Geometry == 1) |     if (mc->Geometry == 1) { | ||||||
|         geo = "45/0, 0/45"; |         geo = "45/0, 0/45"; | ||||||
|     else if (mc->Geometry == 2) |     } else if (mc->Geometry == 2) { | ||||||
|         geo = "0d, d/0"; |         geo = "0d, d/0"; | ||||||
|     else |     } else { | ||||||
|         geo = "unknown"; |         geo = "unknown"; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return Py_BuildValue("{s:i,s:(ddd),s:s,s:d,s:s}", |     return Py_BuildValue("{s:i,s:(ddd),s:s,s:d,s:s}", | ||||||
|                          "observer", mc->Observer, |                          "observer", mc->Observer, | ||||||
|  | @ -1611,8 +1642,9 @@ PyInit__imagingcms(void) { | ||||||
| 
 | 
 | ||||||
|     m = PyModule_Create(&module_def); |     m = PyModule_Create(&module_def); | ||||||
| 
 | 
 | ||||||
|     if (setup_module(m) < 0) |     if (setup_module(m) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     PyDateTime_IMPORT; |     PyDateTime_IMPORT; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										126
									
								
								src/_imagingft.c
									
									
									
									
									
								
							
							
						
						
									
										126
									
								
								src/_imagingft.c
									
									
									
									
									
								
							|  | @ -137,11 +137,12 @@ geterror(int code) | ||||||
| { | { | ||||||
|     int i; |     int i; | ||||||
| 
 | 
 | ||||||
|     for (i = 0; ft_errors[i].message; i++) |     for (i = 0; ft_errors[i].message; i++) { | ||||||
|         if (ft_errors[i].code == code) { |         if (ft_errors[i].code == code) { | ||||||
|             PyErr_SetString(PyExc_OSError, ft_errors[i].message); |             PyErr_SetString(PyExc_OSError, ft_errors[i].message); | ||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     PyErr_SetString(PyExc_OSError, "unknown freetype error"); |     PyErr_SetString(PyExc_OSError, "unknown freetype error"); | ||||||
|     return NULL; |     return NULL; | ||||||
|  | @ -274,8 +275,9 @@ getfont(PyObject* self_, PyObject* args, PyObject* kw) | ||||||
| 
 | 
 | ||||||
|     self = PyObject_New(FontObject, &Font_Type); |     self = PyObject_New(FontObject, &Font_Type); | ||||||
|     if (!self) { |     if (!self) { | ||||||
|         if (filename) |         if (filename) { | ||||||
|             PyMem_Free(filename); |             PyMem_Free(filename); | ||||||
|  |         } | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -299,8 +301,9 @@ getfont(PyObject* self_, PyObject* args, PyObject* kw) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!error) |     if (!error) { | ||||||
|         error = FT_Set_Pixel_Sizes(self->face, 0, size); |         error = FT_Set_Pixel_Sizes(self->face, 0, size); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!error && encoding && strlen((char*) encoding) == 4) { |     if (!error && encoding && strlen((char*) encoding) == 4) { | ||||||
|         FT_Encoding encoding_tag = FT_MAKE_TAG( |         FT_Encoding encoding_tag = FT_MAKE_TAG( | ||||||
|  | @ -308,8 +311,9 @@ getfont(PyObject* self_, PyObject* args, PyObject* kw) | ||||||
|             ); |             ); | ||||||
|         error = FT_Select_Charmap(self->face, encoding_tag); |         error = FT_Select_Charmap(self->face, encoding_tag); | ||||||
|     } |     } | ||||||
|     if (filename) |     if (filename) { | ||||||
|       PyMem_Free(filename); |       PyMem_Free(filename); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (error) { |     if (error) { | ||||||
|         if (self->font_bytes) { |         if (self->font_bytes) { | ||||||
|  | @ -327,8 +331,9 @@ static int | ||||||
| font_getchar(PyObject* string, int index, FT_ULong* char_out) | font_getchar(PyObject* string, int index, FT_ULong* char_out) | ||||||
| { | { | ||||||
|     if (PyUnicode_Check(string)) { |     if (PyUnicode_Check(string)) { | ||||||
|         if (index >= PyUnicode_GET_LENGTH(string)) |         if (index >= PyUnicode_GET_LENGTH(string)) { | ||||||
|             return 0; |             return 0; | ||||||
|  |         } | ||||||
|         *char_out = PyUnicode_READ_CHAR(string, index); |         *char_out = PyUnicode_READ_CHAR(string, index); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  | @ -401,11 +406,11 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir, PyObject * | ||||||
| 
 | 
 | ||||||
|     direction = RAQM_DIRECTION_DEFAULT; |     direction = RAQM_DIRECTION_DEFAULT; | ||||||
|     if (dir) { |     if (dir) { | ||||||
|         if (strcmp(dir, "rtl") == 0) |         if (strcmp(dir, "rtl") == 0) { | ||||||
|             direction = RAQM_DIRECTION_RTL; |             direction = RAQM_DIRECTION_RTL; | ||||||
|         else if (strcmp(dir, "ltr") == 0) |         } else if (strcmp(dir, "ltr") == 0) { | ||||||
|             direction = RAQM_DIRECTION_LTR; |             direction = RAQM_DIRECTION_LTR; | ||||||
|         else if (strcmp(dir, "ttb") == 0) { |         } else if (strcmp(dir, "ttb") == 0) { | ||||||
|             direction = RAQM_DIRECTION_TTB; |             direction = RAQM_DIRECTION_TTB; | ||||||
|             if (p_raqm.version_atleast == NULL || !(*p_raqm.version_atleast)(0, 7, 0)) { |             if (p_raqm.version_atleast == NULL || !(*p_raqm.version_atleast)(0, 7, 0)) { | ||||||
|                 PyErr_SetString(PyExc_ValueError, "libraqm 0.7 or greater required for 'ttb' direction"); |                 PyErr_SetString(PyExc_ValueError, "libraqm 0.7 or greater required for 'ttb' direction"); | ||||||
|  | @ -443,8 +448,9 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir, PyObject * | ||||||
| 
 | 
 | ||||||
|             if (PyUnicode_Check(item)) { |             if (PyUnicode_Check(item)) { | ||||||
|                 bytes = PyUnicode_AsUTF8String(item); |                 bytes = PyUnicode_AsUTF8String(item); | ||||||
|                 if (bytes == NULL) |                 if (bytes == NULL) { | ||||||
|                     goto failed; |                     goto failed; | ||||||
|  |                 } | ||||||
|                 feature = PyBytes_AS_STRING(bytes); |                 feature = PyBytes_AS_STRING(bytes); | ||||||
|                 size = PyBytes_GET_SIZE(bytes); |                 size = PyBytes_GET_SIZE(bytes); | ||||||
|             } |             } | ||||||
|  | @ -608,8 +614,9 @@ font_getsize(FontObject* self, PyObject* args) | ||||||
|     /* calculate size and bearing for a given string */ |     /* calculate size and bearing for a given string */ | ||||||
| 
 | 
 | ||||||
|     PyObject* string; |     PyObject* string; | ||||||
|     if (!PyArg_ParseTuple(args, "O|zOz:getsize", &string, &dir, &features, &lang)) |     if (!PyArg_ParseTuple(args, "O|zOz:getsize", &string, &dir, &features, &lang)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     count = text_layout(string, self, dir, features, lang, &glyph_info, 0); |     count = text_layout(string, self, dir, features, lang, &glyph_info, 0); | ||||||
|     if (PyErr_Occurred()) { |     if (PyErr_Occurred()) { | ||||||
|  | @ -631,8 +638,9 @@ font_getsize(FontObject* self, PyObject* args) | ||||||
|          *   Yifu Yu<root@jackyyf.com>, 2014-10-15 |          *   Yifu Yu<root@jackyyf.com>, 2014-10-15 | ||||||
|          */ |          */ | ||||||
|         error = FT_Load_Glyph(face, index, FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP); |         error = FT_Load_Glyph(face, index, FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP); | ||||||
|         if (error) |         if (error) { | ||||||
|             return geterror(error); |             return geterror(error); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (i == 0) { |         if (i == 0) { | ||||||
|             if (horizontal_dir) { |             if (horizontal_dir) { | ||||||
|  | @ -657,21 +665,26 @@ font_getsize(FontObject* self, PyObject* args) | ||||||
|             offset = glyph_info[i].x_advance - |             offset = glyph_info[i].x_advance - | ||||||
|                     face->glyph->metrics.width - |                     face->glyph->metrics.width - | ||||||
|                     face->glyph->metrics.horiBearingX; |                     face->glyph->metrics.horiBearingX; | ||||||
|             if (offset < 0) |             if (offset < 0) { | ||||||
|                 x_advanced -= offset; |                 x_advanced -= offset; | ||||||
|             if (x_advanced > x_max) |             } | ||||||
|  |             if (x_advanced > x_max) { | ||||||
|                 x_max = x_advanced; |                 x_max = x_advanced; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             bbox.yMax += glyph_info[i].y_offset; |             bbox.yMax += glyph_info[i].y_offset; | ||||||
|             bbox.yMin += glyph_info[i].y_offset; |             bbox.yMin += glyph_info[i].y_offset; | ||||||
|             if (bbox.yMax > y_max) |             if (bbox.yMax > y_max) { | ||||||
|                 y_max = bbox.yMax; |                 y_max = bbox.yMax; | ||||||
|             if (bbox.yMin < y_min) |             } | ||||||
|  |             if (bbox.yMin < y_min) { | ||||||
|                 y_min = bbox.yMin; |                 y_min = bbox.yMin; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             // find max distance of baseline from top
 |             // find max distance of baseline from top
 | ||||||
|             if (face->glyph->metrics.horiBearingY > yoffset) |             if (face->glyph->metrics.horiBearingY > yoffset) { | ||||||
|                 yoffset = face->glyph->metrics.horiBearingY; |                 yoffset = face->glyph->metrics.horiBearingY; | ||||||
|  |             } | ||||||
|         } else { |         } else { | ||||||
|             y_max -= glyph_info[i].y_advance; |             y_max -= glyph_info[i].y_advance; | ||||||
| 
 | 
 | ||||||
|  | @ -681,14 +694,17 @@ font_getsize(FontObject* self, PyObject* args) | ||||||
|                 offset = -glyph_info[i].y_advance - |                 offset = -glyph_info[i].y_advance - | ||||||
|                         face->glyph->metrics.height - |                         face->glyph->metrics.height - | ||||||
|                         face->glyph->metrics.vertBearingY; |                         face->glyph->metrics.vertBearingY; | ||||||
|                 if (offset < 0) |                 if (offset < 0) { | ||||||
|                     y_max -= offset; |                     y_max -= offset; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (bbox.xMax > x_max) |             if (bbox.xMax > x_max) { | ||||||
|                 x_max = bbox.xMax; |                 x_max = bbox.xMax; | ||||||
|             if (i == 0 || bbox.xMin < x_min) |             } | ||||||
|  |             if (i == 0 || bbox.xMin < x_min) { | ||||||
|                 x_min = bbox.xMin; |                 x_min = bbox.xMin; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         FT_Done_Glyph(glyph); |         FT_Done_Glyph(glyph); | ||||||
|  | @ -702,20 +718,22 @@ font_getsize(FontObject* self, PyObject* args) | ||||||
|     if (face) { |     if (face) { | ||||||
|         if (horizontal_dir) { |         if (horizontal_dir) { | ||||||
|             // left bearing
 |             // left bearing
 | ||||||
|             if (xoffset < 0) |             if (xoffset < 0) { | ||||||
|                 x_max -= xoffset; |                 x_max -= xoffset; | ||||||
|             else |             } else { | ||||||
|                 xoffset = 0; |                 xoffset = 0; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             /* difference between the font ascender and the distance of
 |             /* difference between the font ascender and the distance of
 | ||||||
|              * the baseline from the top */ |              * the baseline from the top */ | ||||||
|             yoffset = PIXEL(self->face->size->metrics.ascender - yoffset); |             yoffset = PIXEL(self->face->size->metrics.ascender - yoffset); | ||||||
|         } else { |         } else { | ||||||
|             // top bearing
 |             // top bearing
 | ||||||
|             if (yoffset < 0) |             if (yoffset < 0) { | ||||||
|                 y_max -= yoffset; |                 y_max -= yoffset; | ||||||
|             else |             } else { | ||||||
|                 yoffset = 0; |                 yoffset = 0; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -800,8 +818,9 @@ font_render(FontObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|         temp = bitmap.rows - glyph_slot->bitmap_top; |         temp = bitmap.rows - glyph_slot->bitmap_top; | ||||||
|         temp -= PIXEL(glyph_info[i].y_offset); |         temp -= PIXEL(glyph_info[i].y_offset); | ||||||
|         if (temp > ascender) |         if (temp > ascender) { | ||||||
|             ascender = temp; |             ascender = temp; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (stroker == NULL) { |     if (stroker == NULL) { | ||||||
|  | @ -855,10 +874,12 @@ font_render(FontObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|         x0 = 0; |         x0 = 0; | ||||||
|         x1 = bitmap.width; |         x1 = bitmap.width; | ||||||
|         if (xx < 0) |         if (xx < 0) { | ||||||
|             x0 = -xx; |             x0 = -xx; | ||||||
|         if (xx + x1 > im->xsize) |         } | ||||||
|  |         if (xx + x1 > im->xsize) { | ||||||
|             x1 = im->xsize - xx; |             x1 = im->xsize - xx; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         source = (unsigned char*) bitmap.buffer; |         source = (unsigned char*) bitmap.buffer; | ||||||
|         for (bitmap_y = 0; bitmap_y < bitmap.rows; bitmap_y++) { |         for (bitmap_y = 0; bitmap_y < bitmap.rows; bitmap_y++) { | ||||||
|  | @ -876,8 +897,9 @@ font_render(FontObject* self, PyObject* args) | ||||||
|                     // use monochrome mask (on palette images, etc)
 |                     // use monochrome mask (on palette images, etc)
 | ||||||
|                     int j, k, m = 128; |                     int j, k, m = 128; | ||||||
|                     for (j = k = 0; j < x1; j++) { |                     for (j = k = 0; j < x1; j++) { | ||||||
|                         if (j >= x0 && (source[k] & m)) |                         if (j >= x0 && (source[k] & m)) { | ||||||
|                             target[j] = 255; |                             target[j] = 255; | ||||||
|  |                         } | ||||||
|                         if (!(m >>= 1)) { |                         if (!(m >>= 1)) { | ||||||
|                             m = 128; |                             m = 128; | ||||||
|                             k++; |                             k++; | ||||||
|  | @ -887,8 +909,9 @@ font_render(FontObject* self, PyObject* args) | ||||||
|                     // use antialiased rendering
 |                     // use antialiased rendering
 | ||||||
|                     int k; |                     int k; | ||||||
|                     for (k = x0; k < x1; k++) { |                     for (k = x0; k < x1; k++) { | ||||||
|                         if (target[k] < source[k]) |                         if (target[k] < source[k]) { | ||||||
|                             target[k] = source[k]; |                             target[k] = source[k]; | ||||||
|  |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -919,8 +942,9 @@ font_render(FontObject* self, PyObject* args) | ||||||
|         PyObject *list_names, *list_name; |         PyObject *list_names, *list_name; | ||||||
| 
 | 
 | ||||||
|         error = FT_Get_MM_Var(self->face, &master); |         error = FT_Get_MM_Var(self->face, &master); | ||||||
|         if (error) |         if (error) { | ||||||
|             return geterror(error); |             return geterror(error); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         num_namedstyles = master->num_namedstyles; |         num_namedstyles = master->num_namedstyles; | ||||||
|         list_names = PyList_New(num_namedstyles); |         list_names = PyList_New(num_namedstyles); | ||||||
|  | @ -928,12 +952,14 @@ font_render(FontObject* self, PyObject* args) | ||||||
|         name_count = FT_Get_Sfnt_Name_Count(self->face); |         name_count = FT_Get_Sfnt_Name_Count(self->face); | ||||||
|         for (i = 0; i < name_count; i++) { |         for (i = 0; i < name_count; i++) { | ||||||
|             error = FT_Get_Sfnt_Name(self->face, i, &name); |             error = FT_Get_Sfnt_Name(self->face, i, &name); | ||||||
|             if (error) |             if (error) { | ||||||
|                 return geterror(error); |                 return geterror(error); | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             for (j = 0; j < num_namedstyles; j++) { |             for (j = 0; j < num_namedstyles; j++) { | ||||||
|                 if (PyList_GetItem(list_names, j) != NULL) |                 if (PyList_GetItem(list_names, j) != NULL) { | ||||||
|                     continue; |                     continue; | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|                 if (master->namedstyle[j].strid == name.name_id) { |                 if (master->namedstyle[j].strid == name.name_id) { | ||||||
|                     list_name = Py_BuildValue("y#", name.string, name.string_len); |                     list_name = Py_BuildValue("y#", name.string, name.string_len); | ||||||
|  | @ -958,8 +984,9 @@ font_render(FontObject* self, PyObject* args) | ||||||
|         FT_SfntName name; |         FT_SfntName name; | ||||||
|         PyObject *list_axes, *list_axis, *axis_name; |         PyObject *list_axes, *list_axis, *axis_name; | ||||||
|         error = FT_Get_MM_Var(self->face, &master); |         error = FT_Get_MM_Var(self->face, &master); | ||||||
|         if (error) |         if (error) { | ||||||
|             return geterror(error); |             return geterror(error); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         num_axis = master->num_axis; |         num_axis = master->num_axis; | ||||||
|         name_count = FT_Get_Sfnt_Name_Count(self->face); |         name_count = FT_Get_Sfnt_Name_Count(self->face); | ||||||
|  | @ -978,8 +1005,9 @@ font_render(FontObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|             for (j = 0; j < name_count; j++) { |             for (j = 0; j < name_count; j++) { | ||||||
|                 error = FT_Get_Sfnt_Name(self->face, j, &name); |                 error = FT_Get_Sfnt_Name(self->face, j, &name); | ||||||
|                 if (error) |                 if (error) { | ||||||
|                     return geterror(error); |                     return geterror(error); | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|                 if (name.name_id == axis.strid) { |                 if (name.name_id == axis.strid) { | ||||||
|                     axis_name = Py_BuildValue("y#", name.string, name.string_len); |                     axis_name = Py_BuildValue("y#", name.string, name.string_len); | ||||||
|  | @ -1002,12 +1030,14 @@ font_render(FontObject* self, PyObject* args) | ||||||
|         int error; |         int error; | ||||||
| 
 | 
 | ||||||
|         int instance_index; |         int instance_index; | ||||||
|         if (!PyArg_ParseTuple(args, "i", &instance_index)) |         if (!PyArg_ParseTuple(args, "i", &instance_index)) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         error = FT_Set_Named_Instance(self->face, instance_index); |         error = FT_Set_Named_Instance(self->face, instance_index); | ||||||
|         if (error) |         if (error) { | ||||||
|             return geterror(error); |             return geterror(error); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         Py_INCREF(Py_None); |         Py_INCREF(Py_None); | ||||||
|         return Py_None; |         return Py_None; | ||||||
|  | @ -1022,8 +1052,9 @@ font_render(FontObject* self, PyObject* args) | ||||||
|         Py_ssize_t i, num_coords; |         Py_ssize_t i, num_coords; | ||||||
|         FT_Fixed *coords; |         FT_Fixed *coords; | ||||||
|         FT_Fixed coord; |         FT_Fixed coord; | ||||||
|         if (!PyArg_ParseTuple(args, "O", &axes)) |         if (!PyArg_ParseTuple(args, "O", &axes)) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (!PyList_Check(axes)) { |         if (!PyList_Check(axes)) { | ||||||
|             PyErr_SetString(PyExc_TypeError, "argument must be a list"); |             PyErr_SetString(PyExc_TypeError, "argument must be a list"); | ||||||
|  | @ -1037,13 +1068,13 @@ font_render(FontObject* self, PyObject* args) | ||||||
|         } |         } | ||||||
|         for (i = 0; i < num_coords; i++) { |         for (i = 0; i < num_coords; i++) { | ||||||
|             item = PyList_GET_ITEM(axes, i); |             item = PyList_GET_ITEM(axes, i); | ||||||
|             if (PyFloat_Check(item)) |             if (PyFloat_Check(item)) { | ||||||
|                 coord = PyFloat_AS_DOUBLE(item); |                 coord = PyFloat_AS_DOUBLE(item); | ||||||
|             else if (PyLong_Check(item)) |             } else if (PyLong_Check(item)) { | ||||||
|                 coord = (float) PyLong_AS_LONG(item); |                 coord = (float) PyLong_AS_LONG(item); | ||||||
|             else if (PyNumber_Check(item)) |             } else if (PyNumber_Check(item)) { | ||||||
|                 coord = PyFloat_AsDouble(item); |                 coord = PyFloat_AsDouble(item); | ||||||
|             else { |             } else { | ||||||
|                 free(coords); |                 free(coords); | ||||||
|                 PyErr_SetString(PyExc_TypeError, "list must contain numbers"); |                 PyErr_SetString(PyExc_TypeError, "list must contain numbers"); | ||||||
|                 return NULL; |                 return NULL; | ||||||
|  | @ -1053,8 +1084,9 @@ font_render(FontObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|         error = FT_Set_Var_Design_Coordinates(self->face, num_coords, coords); |         error = FT_Set_Var_Design_Coordinates(self->face, num_coords, coords); | ||||||
|         free(coords); |         free(coords); | ||||||
|         if (error) |         if (error) { | ||||||
|             return geterror(error); |             return geterror(error); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         Py_INCREF(Py_None); |         Py_INCREF(Py_None); | ||||||
|         return Py_None; |         return Py_None; | ||||||
|  | @ -1090,16 +1122,18 @@ static PyMethodDef font_methods[] = { | ||||||
| static PyObject* | static PyObject* | ||||||
| font_getattr_family(FontObject* self, void* closure) | font_getattr_family(FontObject* self, void* closure) | ||||||
| { | { | ||||||
|     if (self->face->family_name) |     if (self->face->family_name) { | ||||||
|         return PyUnicode_FromString(self->face->family_name); |         return PyUnicode_FromString(self->face->family_name); | ||||||
|  |     } | ||||||
|     Py_RETURN_NONE; |     Py_RETURN_NONE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static PyObject* | static PyObject* | ||||||
| font_getattr_style(FontObject* self, void* closure) | font_getattr_style(FontObject* self, void* closure) | ||||||
| { | { | ||||||
|     if (self->face->style_name) |     if (self->face->style_name) { | ||||||
|         return PyUnicode_FromString(self->face->style_name); |         return PyUnicode_FromString(self->face->style_name); | ||||||
|  |     } | ||||||
|     Py_RETURN_NONE; |     Py_RETURN_NONE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1200,8 +1234,9 @@ setup_module(PyObject* m) { | ||||||
|     /* Ready object type */ |     /* Ready object type */ | ||||||
|     PyType_Ready(&Font_Type); |     PyType_Ready(&Font_Type); | ||||||
| 
 | 
 | ||||||
|     if (FT_Init_FreeType(&library)) |     if (FT_Init_FreeType(&library)) { | ||||||
|         return 0; /* leave it uninitialized */ |         return 0; /* leave it uninitialized */ | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     FT_Library_Version(library, &major, &minor, &patch); |     FT_Library_Version(library, &major, &minor, &patch); | ||||||
| 
 | 
 | ||||||
|  | @ -1230,8 +1265,9 @@ PyInit__imagingft(void) { | ||||||
| 
 | 
 | ||||||
|     m = PyModule_Create(&module_def); |     m = PyModule_Create(&module_def); | ||||||
| 
 | 
 | ||||||
|     if (setup_module(m) < 0) |     if (setup_module(m) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return m; |     return m; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -88,12 +88,14 @@ void name(Imaging out, Imaging im1, Imaging im2)\ | ||||||
| static int powi(int x, int y) | static int powi(int x, int y) | ||||||
| { | { | ||||||
|     double v = pow(x, y) + 0.5; |     double v = pow(x, y) + 0.5; | ||||||
|     if (errno == EDOM) |     if (errno == EDOM) { | ||||||
|         return 0; |         return 0; | ||||||
|     if (v < MIN_INT32) |     } | ||||||
|  |     if (v < MIN_INT32) { | ||||||
|         v = MIN_INT32; |         v = MIN_INT32; | ||||||
|     else if (v > MAX_INT32) |     } else if (v > MAX_INT32) { | ||||||
|         v = MAX_INT32; |         v = MAX_INT32; | ||||||
|  |     } | ||||||
|     return (int) v; |     return (int) v; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -167,8 +169,9 @@ _unop(PyObject* self, PyObject* args) | ||||||
|     void (*unop)(Imaging, Imaging); |     void (*unop)(Imaging, Imaging); | ||||||
| 
 | 
 | ||||||
|     Py_ssize_t op, i0, i1; |     Py_ssize_t op, i0, i1; | ||||||
|     if (!PyArg_ParseTuple(args, "nnn", &op, &i0, &i1)) |     if (!PyArg_ParseTuple(args, "nnn", &op, &i0, &i1)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     out = (Imaging) i0; |     out = (Imaging) i0; | ||||||
|     im1 = (Imaging) i1; |     im1 = (Imaging) i1; | ||||||
|  | @ -190,8 +193,9 @@ _binop(PyObject* self, PyObject* args) | ||||||
|     void (*binop)(Imaging, Imaging, Imaging); |     void (*binop)(Imaging, Imaging, Imaging); | ||||||
| 
 | 
 | ||||||
|     Py_ssize_t op, i0, i1, i2; |     Py_ssize_t op, i0, i1, i2; | ||||||
|     if (!PyArg_ParseTuple(args, "nnnn", &op, &i0, &i1, &i2)) |     if (!PyArg_ParseTuple(args, "nnnn", &op, &i0, &i1, &i2)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     out = (Imaging) i0; |     out = (Imaging) i0; | ||||||
|     im1 = (Imaging) i1; |     im1 = (Imaging) i1; | ||||||
|  | @ -215,8 +219,9 @@ static void | ||||||
| install(PyObject *d, char* name, void* value) | install(PyObject *d, char* name, void* value) | ||||||
| { | { | ||||||
|     PyObject *v = PyLong_FromSsize_t((Py_ssize_t) value); |     PyObject *v = PyLong_FromSsize_t((Py_ssize_t) value); | ||||||
|     if (!v || PyDict_SetItemString(d, name, v)) |     if (!v || PyDict_SetItemString(d, name, v)) { | ||||||
|         PyErr_Clear(); |         PyErr_Clear(); | ||||||
|  |     } | ||||||
|     Py_XDECREF(v); |     Py_XDECREF(v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -286,8 +291,9 @@ PyInit__imagingmath(void) { | ||||||
| 
 | 
 | ||||||
|     m = PyModule_Create(&module_def); |     m = PyModule_Create(&module_def); | ||||||
| 
 | 
 | ||||||
|     if (setup_module(m) < 0) |     if (setup_module(m) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return m; |     return m; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -85,8 +85,9 @@ apply(PyObject *self, PyObject* args) | ||||||
|         /* zero boundary conditions. TBD support other modes */ |         /* zero boundary conditions. TBD support other modes */ | ||||||
|         outrow[0] = outrow[width-1] = 0; |         outrow[0] = outrow[width-1] = 0; | ||||||
|         if (row_idx==0 || row_idx == height-1) { |         if (row_idx==0 || row_idx == height-1) { | ||||||
|             for(col_idx=0; col_idx<width; col_idx++) |             for(col_idx=0; col_idx<width; col_idx++) { | ||||||
|                 outrow[col_idx] = 0; |                 outrow[col_idx] = 0; | ||||||
|  |             } | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -286,8 +287,9 @@ PyInit__imagingmorph(void) { | ||||||
| 
 | 
 | ||||||
|     m = PyModule_Create(&module_def); |     m = PyModule_Create(&module_def); | ||||||
| 
 | 
 | ||||||
|     if (setup_module(m) < 0) |     if (setup_module(m) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return m; |     return m; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -38,12 +38,13 @@ _tkinit(PyObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|     PyObject* arg; |     PyObject* arg; | ||||||
|     int is_interp; |     int is_interp; | ||||||
|     if (!PyArg_ParseTuple(args, "Oi", &arg, &is_interp)) |     if (!PyArg_ParseTuple(args, "Oi", &arg, &is_interp)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (is_interp) |     if (is_interp) { | ||||||
|         interp = (Tcl_Interp*)PyLong_AsVoidPtr(arg); |         interp = (Tcl_Interp*)PyLong_AsVoidPtr(arg); | ||||||
|     else { |     } else { | ||||||
|         TkappObject* app; |         TkappObject* app; | ||||||
|         /* Do it the hard way.  This will break if the TkappObject
 |         /* Do it the hard way.  This will break if the TkappObject
 | ||||||
|         layout changes */ |         layout changes */ | ||||||
|  |  | ||||||
							
								
								
									
										21
									
								
								src/_webp.c
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								src/_webp.c
									
									
									
									
									
								
							|  | @ -724,8 +724,9 @@ PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args) | ||||||
|         WebPData exif_data = {0}; |         WebPData exif_data = {0}; | ||||||
| 
 | 
 | ||||||
|         WebPMux* mux = WebPMuxCreate(&data, copy_data); |         WebPMux* mux = WebPMuxCreate(&data, copy_data); | ||||||
|         if (NULL == mux) |         if (NULL == mux) { | ||||||
|             goto end; |             goto end; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (WEBP_MUX_OK != WebPMuxGetFrame(mux, 1, &image)) |         if (WEBP_MUX_OK != WebPMuxGetFrame(mux, 1, &image)) | ||||||
|         { |         { | ||||||
|  | @ -738,11 +739,13 @@ PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|         vp8_status_code = WebPDecode(webp, size, &config); |         vp8_status_code = WebPDecode(webp, size, &config); | ||||||
| 
 | 
 | ||||||
|         if (WEBP_MUX_OK == WebPMuxGetChunk(mux, "ICCP", &icc_profile_data)) |         if (WEBP_MUX_OK == WebPMuxGetChunk(mux, "ICCP", &icc_profile_data)) { | ||||||
|             icc_profile = PyBytes_FromStringAndSize((const char*)icc_profile_data.bytes, icc_profile_data.size); |             icc_profile = PyBytes_FromStringAndSize((const char*)icc_profile_data.bytes, icc_profile_data.size); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (WEBP_MUX_OK == WebPMuxGetChunk(mux, "EXIF", &exif_data)) |         if (WEBP_MUX_OK == WebPMuxGetChunk(mux, "EXIF", &exif_data)) { | ||||||
|             exif = PyBytes_FromStringAndSize((const char*)exif_data.bytes, exif_data.size); |             exif = PyBytes_FromStringAndSize((const char*)exif_data.bytes, exif_data.size); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         WebPDataClear(&image.bitstream); |         WebPDataClear(&image.bitstream); | ||||||
|         WebPMuxDelete(mux); |         WebPMuxDelete(mux); | ||||||
|  | @ -750,8 +753,9 @@ PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args) | ||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (vp8_status_code != VP8_STATUS_OK) |     if (vp8_status_code != VP8_STATUS_OK) { | ||||||
|         goto end; |         goto end; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (config.output.colorspace < MODE_YUV) { |     if (config.output.colorspace < MODE_YUV) { | ||||||
|         bytes = PyBytes_FromStringAndSize((char*)config.output.u.RGBA.rgba, |         bytes = PyBytes_FromStringAndSize((char*)config.output.u.RGBA.rgba, | ||||||
|  | @ -777,8 +781,9 @@ end: | ||||||
|     Py_XDECREF(icc_profile); |     Py_XDECREF(icc_profile); | ||||||
|     Py_XDECREF(exif); |     Py_XDECREF(exif); | ||||||
| 
 | 
 | ||||||
|     if (Py_None == ret) |     if (Py_None == ret) { | ||||||
|         Py_RETURN_NONE; |         Py_RETURN_NONE; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  | @ -847,8 +852,9 @@ static int setup_module(PyObject* m) { | ||||||
| #ifdef HAVE_WEBPANIM | #ifdef HAVE_WEBPANIM | ||||||
|     /* Ready object types */ |     /* Ready object types */ | ||||||
|     if (PyType_Ready(&WebPAnimDecoder_Type) < 0 || |     if (PyType_Ready(&WebPAnimDecoder_Type) < 0 || | ||||||
|         PyType_Ready(&WebPAnimEncoder_Type) < 0) |         PyType_Ready(&WebPAnimEncoder_Type) < 0) { | ||||||
|         return -1; |         return -1; | ||||||
|  |     } | ||||||
| #endif | #endif | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | @ -866,8 +872,9 @@ PyInit__webp(void) { | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     m = PyModule_Create(&module_def); |     m = PyModule_Create(&module_def); | ||||||
|     if (setup_module(m) < 0) |     if (setup_module(m) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return m; |     return m; | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										168
									
								
								src/decode.c
									
									
									
									
									
								
							
							
						
						
									
										168
									
								
								src/decode.c
									
									
									
									
									
								
							|  | @ -63,12 +63,14 @@ PyImaging_DecoderNew(int contextsize) | ||||||
|     ImagingDecoderObject *decoder; |     ImagingDecoderObject *decoder; | ||||||
|     void *context; |     void *context; | ||||||
| 
 | 
 | ||||||
|     if(PyType_Ready(&ImagingDecoderType) < 0) |     if(PyType_Ready(&ImagingDecoderType) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyObject_New(ImagingDecoderObject, &ImagingDecoderType); |     decoder = PyObject_New(ImagingDecoderObject, &ImagingDecoderType); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Clear the decoder state */ |     /* Clear the decoder state */ | ||||||
|     memset(&decoder->state, 0, sizeof(decoder->state)); |     memset(&decoder->state, 0, sizeof(decoder->state)); | ||||||
|  | @ -81,8 +83,9 @@ PyImaging_DecoderNew(int contextsize) | ||||||
|             (void) PyErr_NoMemory(); |             (void) PyErr_NoMemory(); | ||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
|     } else |     } else { | ||||||
|         context = 0; |         context = 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Initialize decoder context */ |     /* Initialize decoder context */ | ||||||
|     decoder->state.context = context; |     decoder->state.context = context; | ||||||
|  | @ -104,8 +107,9 @@ PyImaging_DecoderNew(int contextsize) | ||||||
| static void | static void | ||||||
| _dealloc(ImagingDecoderObject* decoder) | _dealloc(ImagingDecoderObject* decoder) | ||||||
| { | { | ||||||
|     if (decoder->cleanup) |     if (decoder->cleanup) { | ||||||
|         decoder->cleanup(&decoder->state); |         decoder->cleanup(&decoder->state); | ||||||
|  |     } | ||||||
|     free(decoder->state.buffer); |     free(decoder->state.buffer); | ||||||
|     free(decoder->state.context); |     free(decoder->state.context); | ||||||
|     Py_XDECREF(decoder->lock); |     Py_XDECREF(decoder->lock); | ||||||
|  | @ -121,8 +125,9 @@ _decode(ImagingDecoderObject* decoder, PyObject* args) | ||||||
|     int status; |     int status; | ||||||
|     ImagingSectionCookie cookie; |     ImagingSectionCookie cookie; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "y#", &buffer, &bufsize)) |     if (!PyArg_ParseTuple(args, "y#", &buffer, &bufsize)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!decoder->pulls_fd) { |     if (!decoder->pulls_fd) { | ||||||
|         ImagingSectionEnter(&cookie); |         ImagingSectionEnter(&cookie); | ||||||
|  | @ -164,11 +169,13 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args) | ||||||
|     x0 = y0 = x1 = y1 = 0; |     x0 = y0 = x1 = y1 = 0; | ||||||
| 
 | 
 | ||||||
|     /* FIXME: should publish the ImagingType descriptor */ |     /* FIXME: should publish the ImagingType descriptor */ | ||||||
|     if (!PyArg_ParseTuple(args, "O|(iiii)", &op, &x0, &y0, &x1, &y1)) |     if (!PyArg_ParseTuple(args, "O|(iiii)", &op, &x0, &y0, &x1, &y1)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
|     im = PyImaging_AsImaging(op); |     im = PyImaging_AsImaging(op); | ||||||
|     if (!im) |     if (!im) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->im = im; |     decoder->im = im; | ||||||
| 
 | 
 | ||||||
|  | @ -203,8 +210,9 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args) | ||||||
|         } |         } | ||||||
|         /* malloc check ok, overflow checked above */ |         /* malloc check ok, overflow checked above */ | ||||||
|         state->buffer = (UINT8*) malloc(state->bytes); |         state->buffer = (UINT8*) malloc(state->bytes); | ||||||
|         if (!state->buffer) |         if (!state->buffer) { | ||||||
|             return PyErr_NoMemory(); |             return PyErr_NoMemory(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Keep a reference to the image object, to make sure it doesn't
 |     /* Keep a reference to the image object, to make sure it doesn't
 | ||||||
|  | @ -223,8 +231,9 @@ _setfd(ImagingDecoderObject* decoder, PyObject* args) | ||||||
|     PyObject* fd; |     PyObject* fd; | ||||||
|     ImagingCodecState state; |     ImagingCodecState state; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "O", &fd)) |     if (!PyArg_ParseTuple(args, "O", &fd)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     state = &decoder->state; |     state = &decoder->state; | ||||||
| 
 | 
 | ||||||
|  | @ -330,8 +339,9 @@ PyImaging_BitDecoderNew(PyObject* self, PyObject* args) | ||||||
|     int sign  = 0; |     int sign  = 0; | ||||||
|     int ystep = 1; |     int ystep = 1; | ||||||
|     if (!PyArg_ParseTuple(args, "s|iiiii", &mode, &bits, &pad, &fill, |     if (!PyArg_ParseTuple(args, "s|iiiii", &mode, &bits, &pad, &fill, | ||||||
|                           &sign, &ystep)) |                           &sign, &ystep)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (strcmp(mode, "F") != 0) { |     if (strcmp(mode, "F") != 0) { | ||||||
|         PyErr_SetString(PyExc_ValueError, "bad image mode"); |         PyErr_SetString(PyExc_ValueError, "bad image mode"); | ||||||
|  | @ -339,8 +349,9 @@ PyImaging_BitDecoderNew(PyObject* self, PyObject* args) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(sizeof(BITSTATE)); |     decoder = PyImaging_DecoderNew(sizeof(BITSTATE)); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingBitDecode; |     decoder->decode = ImagingBitDecode; | ||||||
| 
 | 
 | ||||||
|  | @ -368,8 +379,9 @@ PyImaging_BcnDecoderNew(PyObject* self, PyObject* args) | ||||||
|     char* actual; |     char* actual; | ||||||
|     int n = 0; |     int n = 0; | ||||||
|     int ystep = 1; |     int ystep = 1; | ||||||
|     if (!PyArg_ParseTuple(args, "s|ii", &mode, &n, &ystep)) |     if (!PyArg_ParseTuple(args, "s|ii", &mode, &n, &ystep)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     switch (n) { |     switch (n) { | ||||||
|     case 1: /* BC1: 565 color, 1-bit alpha */ |     case 1: /* BC1: 565 color, 1-bit alpha */ | ||||||
|  | @ -394,8 +406,9 @@ PyImaging_BcnDecoderNew(PyObject* self, PyObject* args) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(0); |     decoder = PyImaging_DecoderNew(0); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingBcnDecode; |     decoder->decode = ImagingBcnDecode; | ||||||
|     decoder->state.state = n; |     decoder->state.state = n; | ||||||
|  | @ -415,8 +428,9 @@ PyImaging_FliDecoderNew(PyObject* self, PyObject* args) | ||||||
|     ImagingDecoderObject* decoder; |     ImagingDecoderObject* decoder; | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(0); |     decoder = PyImaging_DecoderNew(0); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingFliDecode; |     decoder->decode = ImagingFliDecode; | ||||||
| 
 | 
 | ||||||
|  | @ -436,8 +450,9 @@ PyImaging_GifDecoderNew(PyObject* self, PyObject* args) | ||||||
|     char* mode; |     char* mode; | ||||||
|     int bits = 8; |     int bits = 8; | ||||||
|     int interlace = 0; |     int interlace = 0; | ||||||
|     if (!PyArg_ParseTuple(args, "s|ii", &mode, &bits, &interlace)) |     if (!PyArg_ParseTuple(args, "s|ii", &mode, &bits, &interlace)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (strcmp(mode, "L") != 0 && strcmp(mode, "P") != 0) { |     if (strcmp(mode, "L") != 0 && strcmp(mode, "P") != 0) { | ||||||
|         PyErr_SetString(PyExc_ValueError, "bad image mode"); |         PyErr_SetString(PyExc_ValueError, "bad image mode"); | ||||||
|  | @ -445,8 +460,9 @@ PyImaging_GifDecoderNew(PyObject* self, PyObject* args) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(sizeof(GIFDECODERSTATE)); |     decoder = PyImaging_DecoderNew(sizeof(GIFDECODERSTATE)); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingGifDecode; |     decoder->decode = ImagingGifDecode; | ||||||
| 
 | 
 | ||||||
|  | @ -468,15 +484,18 @@ PyImaging_HexDecoderNew(PyObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|     char* mode; |     char* mode; | ||||||
|     char* rawmode; |     char* rawmode; | ||||||
|     if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) |     if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(0); |     decoder = PyImaging_DecoderNew(0); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_unpacker(decoder, mode, rawmode) < 0) |     if (get_unpacker(decoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingHexDecode; |     decoder->decode = ImagingHexDecode; | ||||||
| 
 | 
 | ||||||
|  | @ -504,17 +523,20 @@ PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args) | ||||||
|     int fp; |     int fp; | ||||||
|     uint32 ifdoffset; |     uint32 ifdoffset; | ||||||
| 
 | 
 | ||||||
|     if (! PyArg_ParseTuple(args, "sssiI", &mode, &rawmode, &compname, &fp, &ifdoffset)) |     if (! PyArg_ParseTuple(args, "sssiI", &mode, &rawmode, &compname, &fp, &ifdoffset)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     TRACE(("new tiff decoder %s\n", compname)); |     TRACE(("new tiff decoder %s\n", compname)); | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(sizeof(TIFFSTATE)); |     decoder = PyImaging_DecoderNew(sizeof(TIFFSTATE)); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_unpacker(decoder, mode, rawmode) < 0) |     if (get_unpacker(decoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (! ImagingLibTiffInit(&decoder->state, fp, ifdoffset)) { |     if (! ImagingLibTiffInit(&decoder->state, fp, ifdoffset)) { | ||||||
|         Py_DECREF(decoder); |         Py_DECREF(decoder); | ||||||
|  | @ -541,15 +563,18 @@ PyImaging_PackbitsDecoderNew(PyObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|     char* mode; |     char* mode; | ||||||
|     char* rawmode; |     char* rawmode; | ||||||
|     if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) |     if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(0); |     decoder = PyImaging_DecoderNew(0); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_unpacker(decoder, mode, rawmode) < 0) |     if (get_unpacker(decoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingPackbitsDecode; |     decoder->decode = ImagingPackbitsDecode; | ||||||
| 
 | 
 | ||||||
|  | @ -567,12 +592,14 @@ PyImaging_PcdDecoderNew(PyObject* self, PyObject* args) | ||||||
|     ImagingDecoderObject* decoder; |     ImagingDecoderObject* decoder; | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(0); |     decoder = PyImaging_DecoderNew(0); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Unpack from PhotoYCC to RGB */ |     /* Unpack from PhotoYCC to RGB */ | ||||||
|     if (get_unpacker(decoder, "RGB", "YCC;P") < 0) |     if (get_unpacker(decoder, "RGB", "YCC;P") < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingPcdDecode; |     decoder->decode = ImagingPcdDecode; | ||||||
| 
 | 
 | ||||||
|  | @ -592,15 +619,18 @@ PyImaging_PcxDecoderNew(PyObject* self, PyObject* args) | ||||||
|     char* mode; |     char* mode; | ||||||
|     char* rawmode; |     char* rawmode; | ||||||
|     int stride; |     int stride; | ||||||
|     if (!PyArg_ParseTuple(args, "ssi", &mode, &rawmode, &stride)) |     if (!PyArg_ParseTuple(args, "ssi", &mode, &rawmode, &stride)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(0); |     decoder = PyImaging_DecoderNew(0); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_unpacker(decoder, mode, rawmode) < 0) |     if (get_unpacker(decoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->state.bytes = stride; |     decoder->state.bytes = stride; | ||||||
| 
 | 
 | ||||||
|  | @ -623,15 +653,18 @@ PyImaging_RawDecoderNew(PyObject* self, PyObject* args) | ||||||
|     char* rawmode; |     char* rawmode; | ||||||
|     int stride = 0; |     int stride = 0; | ||||||
|     int ystep  = 1; |     int ystep  = 1; | ||||||
|     if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &stride, &ystep)) |     if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &stride, &ystep)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(sizeof(RAWSTATE)); |     decoder = PyImaging_DecoderNew(sizeof(RAWSTATE)); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_unpacker(decoder, mode, rawmode) < 0) |     if (get_unpacker(decoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingRawDecode; |     decoder->decode = ImagingRawDecode; | ||||||
| 
 | 
 | ||||||
|  | @ -656,15 +689,18 @@ PyImaging_SgiRleDecoderNew(PyObject* self, PyObject* args) | ||||||
|     char* rawmode; |     char* rawmode; | ||||||
|     int ystep = 1; |     int ystep = 1; | ||||||
|     int bpc = 1; |     int bpc = 1; | ||||||
|     if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &ystep, &bpc)) |     if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &ystep, &bpc)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(sizeof(SGISTATE)); |     decoder = PyImaging_DecoderNew(sizeof(SGISTATE)); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_unpacker(decoder, mode, rawmode) < 0) |     if (get_unpacker(decoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->pulls_fd = 1; |     decoder->pulls_fd = 1; | ||||||
|     decoder->decode = ImagingSgiRleDecode; |     decoder->decode = ImagingSgiRleDecode; | ||||||
|  | @ -687,15 +723,18 @@ PyImaging_SunRleDecoderNew(PyObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|     char* mode; |     char* mode; | ||||||
|     char* rawmode; |     char* rawmode; | ||||||
|     if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) |     if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(0); |     decoder = PyImaging_DecoderNew(0); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_unpacker(decoder, mode, rawmode) < 0) |     if (get_unpacker(decoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingSunRleDecode; |     decoder->decode = ImagingSunRleDecode; | ||||||
| 
 | 
 | ||||||
|  | @ -716,15 +755,18 @@ PyImaging_TgaRleDecoderNew(PyObject* self, PyObject* args) | ||||||
|     char* rawmode; |     char* rawmode; | ||||||
|     int ystep = 1; |     int ystep = 1; | ||||||
|     int depth = 8; |     int depth = 8; | ||||||
|     if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &ystep, &depth)) |     if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &ystep, &depth)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(0); |     decoder = PyImaging_DecoderNew(0); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_unpacker(decoder, mode, rawmode) < 0) |     if (get_unpacker(decoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingTgaRleDecode; |     decoder->decode = ImagingTgaRleDecode; | ||||||
| 
 | 
 | ||||||
|  | @ -745,11 +787,13 @@ PyImaging_XbmDecoderNew(PyObject* self, PyObject* args) | ||||||
|     ImagingDecoderObject* decoder; |     ImagingDecoderObject* decoder; | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(0); |     decoder = PyImaging_DecoderNew(0); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_unpacker(decoder, "1", "1;R") < 0) |     if (get_unpacker(decoder, "1", "1;R") < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingXbmDecode; |     decoder->decode = ImagingXbmDecode; | ||||||
| 
 | 
 | ||||||
|  | @ -773,15 +817,18 @@ PyImaging_ZipDecoderNew(PyObject* self, PyObject* args) | ||||||
|     char* mode; |     char* mode; | ||||||
|     char* rawmode; |     char* rawmode; | ||||||
|     int interlaced = 0; |     int interlaced = 0; | ||||||
|     if (!PyArg_ParseTuple(args, "ss|i", &mode, &rawmode, &interlaced)) |     if (!PyArg_ParseTuple(args, "ss|i", &mode, &rawmode, &interlaced)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(sizeof(ZIPSTATE)); |     decoder = PyImaging_DecoderNew(sizeof(ZIPSTATE)); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_unpacker(decoder, mode, rawmode) < 0) |     if (get_unpacker(decoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingZipDecode; |     decoder->decode = ImagingZipDecode; | ||||||
|     decoder->cleanup = ImagingZipDecodeCleanup; |     decoder->cleanup = ImagingZipDecodeCleanup; | ||||||
|  | @ -826,15 +873,18 @@ PyImaging_JpegDecoderNew(PyObject* self, PyObject* args) | ||||||
|     int draft = 0; |     int draft = 0; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "ssz|ii", &mode, &rawmode, &jpegmode, |     if (!PyArg_ParseTuple(args, "ssz|ii", &mode, &rawmode, &jpegmode, | ||||||
|                           &scale, &draft)) |                           &scale, &draft)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!jpegmode) |     if (!jpegmode) { | ||||||
|         jpegmode = ""; |         jpegmode = ""; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(sizeof(JPEGSTATE)); |     decoder = PyImaging_DecoderNew(sizeof(JPEGSTATE)); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // libjpeg-turbo supports different output formats.
 |     // libjpeg-turbo supports different output formats.
 | ||||||
|     // We are choosing Pillow's native format (3 color bytes + 1 padding)
 |     // We are choosing Pillow's native format (3 color bytes + 1 padding)
 | ||||||
|  | @ -843,8 +893,9 @@ PyImaging_JpegDecoderNew(PyObject* self, PyObject* args) | ||||||
|         rawmode = "RGBX"; |         rawmode = "RGBX"; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (get_unpacker(decoder, mode, rawmode) < 0) |     if (get_unpacker(decoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->decode = ImagingJpegDecode; |     decoder->decode = ImagingJpegDecode; | ||||||
|     decoder->cleanup = ImagingJpegDecodeCleanup; |     decoder->cleanup = ImagingJpegDecodeCleanup; | ||||||
|  | @ -882,21 +933,24 @@ PyImaging_Jpeg2KDecoderNew(PyObject* self, PyObject* args) | ||||||
|     PY_LONG_LONG length = -1; |     PY_LONG_LONG length = -1; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "ss|iiiL", &mode, &format, |     if (!PyArg_ParseTuple(args, "ss|iiiL", &mode, &format, | ||||||
|                           &reduce, &layers, &fd, &length)) |                           &reduce, &layers, &fd, &length)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (strcmp(format, "j2k") == 0) |     if (strcmp(format, "j2k") == 0) { | ||||||
|         codec_format = OPJ_CODEC_J2K; |         codec_format = OPJ_CODEC_J2K; | ||||||
|     else if (strcmp(format, "jpt") == 0) |     } else if (strcmp(format, "jpt") == 0) { | ||||||
|         codec_format = OPJ_CODEC_JPT; |         codec_format = OPJ_CODEC_JPT; | ||||||
|     else if (strcmp(format, "jp2") == 0) |     } else if (strcmp(format, "jp2") == 0) { | ||||||
|         codec_format = OPJ_CODEC_JP2; |         codec_format = OPJ_CODEC_JP2; | ||||||
|     else |     } else { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder = PyImaging_DecoderNew(sizeof(JPEG2KDECODESTATE)); |     decoder = PyImaging_DecoderNew(sizeof(JPEG2KDECODESTATE)); | ||||||
|     if (decoder == NULL) |     if (decoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     decoder->pulls_fd = 1; |     decoder->pulls_fd = 1; | ||||||
|     decoder->decode = ImagingJpeg2KDecode; |     decoder->decode = ImagingJpeg2KDecode; | ||||||
|  |  | ||||||
							
								
								
									
										134
									
								
								src/display.c
									
									
									
									
									
								
							
							
						
						
									
										134
									
								
								src/display.c
									
									
									
									
									
								
							|  | @ -52,12 +52,14 @@ _new(const char* mode, int xsize, int ysize) | ||||||
| { | { | ||||||
|     ImagingDisplayObject *display; |     ImagingDisplayObject *display; | ||||||
| 
 | 
 | ||||||
|     if (PyType_Ready(&ImagingDisplayType) < 0) |     if (PyType_Ready(&ImagingDisplayType) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     display = PyObject_New(ImagingDisplayObject, &ImagingDisplayType); |     display = PyObject_New(ImagingDisplayObject, &ImagingDisplayType); | ||||||
|     if (display == NULL) |     if (display == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     display->dib = ImagingNewDIB(mode, xsize, ysize); |     display->dib = ImagingNewDIB(mode, xsize, ysize); | ||||||
|     if (!display->dib) { |     if (!display->dib) { | ||||||
|  | @ -71,8 +73,9 @@ _new(const char* mode, int xsize, int ysize) | ||||||
| static void | static void | ||||||
| _delete(ImagingDisplayObject* display) | _delete(ImagingDisplayObject* display) | ||||||
| { | { | ||||||
|     if (display->dib) |     if (display->dib) { | ||||||
|         ImagingDeleteDIB(display->dib); |         ImagingDeleteDIB(display->dib); | ||||||
|  |     } | ||||||
|     PyObject_Del(display); |     PyObject_Del(display); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -80,8 +83,9 @@ static PyObject* | ||||||
| _expose(ImagingDisplayObject* display, PyObject* args) | _expose(ImagingDisplayObject* display, PyObject* args) | ||||||
| { | { | ||||||
|     HDC hdc; |     HDC hdc; | ||||||
|     if (!PyArg_ParseTuple(args, F_HANDLE, &hdc)) |     if (!PyArg_ParseTuple(args, F_HANDLE, &hdc)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingExposeDIB(display->dib, hdc); |     ImagingExposeDIB(display->dib, hdc); | ||||||
| 
 | 
 | ||||||
|  | @ -97,8 +101,9 @@ _draw(ImagingDisplayObject* display, PyObject* args) | ||||||
|     int src[4]; |     int src[4]; | ||||||
|     if (!PyArg_ParseTuple(args, F_HANDLE "(iiii)(iiii)", &hdc, |     if (!PyArg_ParseTuple(args, F_HANDLE "(iiii)(iiii)", &hdc, | ||||||
|                           dst+0, dst+1, dst+2, dst+3, |                           dst+0, dst+1, dst+2, dst+3, | ||||||
|                           src+0, src+1, src+2, src+3)) |                           src+0, src+1, src+2, src+3)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingDrawDIB(display->dib, hdc, dst, src); |     ImagingDrawDIB(display->dib, hdc, dst, src); | ||||||
| 
 | 
 | ||||||
|  | @ -116,16 +121,20 @@ _paste(ImagingDisplayObject* display, PyObject* args) | ||||||
|     PyObject* op; |     PyObject* op; | ||||||
|     int xy[4]; |     int xy[4]; | ||||||
|     xy[0] = xy[1] = xy[2] = xy[3] = 0; |     xy[0] = xy[1] = xy[2] = xy[3] = 0; | ||||||
|     if (!PyArg_ParseTuple(args, "O|(iiii)", &op, xy+0, xy+1, xy+2, xy+3)) |     if (!PyArg_ParseTuple(args, "O|(iiii)", &op, xy+0, xy+1, xy+2, xy+3)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
|     im = PyImaging_AsImaging(op); |     im = PyImaging_AsImaging(op); | ||||||
|     if (!im) |     if (!im) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (xy[2] <= xy[0]) |     if (xy[2] <= xy[0]) { | ||||||
|         xy[2] = xy[0] + im->xsize; |         xy[2] = xy[0] + im->xsize; | ||||||
|     if (xy[3] <= xy[1]) |     } | ||||||
|  |     if (xy[3] <= xy[1]) { | ||||||
|         xy[3] = xy[1] + im->ysize; |         xy[3] = xy[1] + im->ysize; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingPasteDIB(display->dib, im, xy); |     ImagingPasteDIB(display->dib, im, xy); | ||||||
| 
 | 
 | ||||||
|  | @ -139,8 +148,9 @@ _query_palette(ImagingDisplayObject* display, PyObject* args) | ||||||
|     HDC hdc; |     HDC hdc; | ||||||
|     int status; |     int status; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, F_HANDLE, &hdc)) |     if (!PyArg_ParseTuple(args, F_HANDLE, &hdc)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     status = ImagingQueryPaletteDIB(display->dib, hdc); |     status = ImagingQueryPaletteDIB(display->dib, hdc); | ||||||
| 
 | 
 | ||||||
|  | @ -153,8 +163,9 @@ _getdc(ImagingDisplayObject* display, PyObject* args) | ||||||
|     HWND window; |     HWND window; | ||||||
|     HDC dc; |     HDC dc; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, F_HANDLE, &window)) |     if (!PyArg_ParseTuple(args, F_HANDLE, &window)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     dc = GetDC(window); |     dc = GetDC(window); | ||||||
|     if (!dc) { |     if (!dc) { | ||||||
|  | @ -171,8 +182,9 @@ _releasedc(ImagingDisplayObject* display, PyObject* args) | ||||||
|     HWND window; |     HWND window; | ||||||
|     HDC dc; |     HDC dc; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE, &window, &dc)) |     if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE, &window, &dc)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ReleaseDC(window, dc); |     ReleaseDC(window, dc); | ||||||
| 
 | 
 | ||||||
|  | @ -186,8 +198,9 @@ _frombytes(ImagingDisplayObject* display, PyObject* args) | ||||||
|     char* ptr; |     char* ptr; | ||||||
|     int bytes; |     int bytes; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "y#:frombytes", &ptr, &bytes)) |     if (!PyArg_ParseTuple(args, "y#:frombytes", &ptr, &bytes)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (display->dib->ysize * display->dib->linesize != bytes) { |     if (display->dib->ysize * display->dib->linesize != bytes) { | ||||||
|         PyErr_SetString(PyExc_ValueError, "wrong size"); |         PyErr_SetString(PyExc_ValueError, "wrong size"); | ||||||
|  | @ -203,8 +216,9 @@ _frombytes(ImagingDisplayObject* display, PyObject* args) | ||||||
| static PyObject* | static PyObject* | ||||||
| _tobytes(ImagingDisplayObject* display, PyObject* args) | _tobytes(ImagingDisplayObject* display, PyObject* args) | ||||||
| { | { | ||||||
|     if (!PyArg_ParseTuple(args, ":tobytes")) |     if (!PyArg_ParseTuple(args, ":tobytes")) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return PyBytes_FromStringAndSize( |     return PyBytes_FromStringAndSize( | ||||||
|         display->dib->bits, display->dib->ysize * display->dib->linesize |         display->dib->bits, display->dib->ysize * display->dib->linesize | ||||||
|  | @ -284,12 +298,14 @@ PyImaging_DisplayWin32(PyObject* self, PyObject* args) | ||||||
|     char *mode; |     char *mode; | ||||||
|     int xsize, ysize; |     int xsize, ysize; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "s(ii)", &mode, &xsize, &ysize)) |     if (!PyArg_ParseTuple(args, "s(ii)", &mode, &xsize, &ysize)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     display = _new(mode, xsize, ysize); |     display = _new(mode, xsize, ysize); | ||||||
|     if (display == NULL) |     if (display == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return (PyObject*) display; |     return (PyObject*) display; | ||||||
| } | } | ||||||
|  | @ -324,8 +340,9 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args) | ||||||
|     HMODULE user32; |     HMODULE user32; | ||||||
|     Func_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContext_function; |     Func_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContext_function; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "|ii", &includeLayeredWindows, &all_screens)) |     if (!PyArg_ParseTuple(args, "|ii", &includeLayeredWindows, &all_screens)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* step 1: create a memory DC large enough to hold the
 |     /* step 1: create a memory DC large enough to hold the
 | ||||||
|        entire screen */ |        entire screen */ | ||||||
|  | @ -361,25 +378,30 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args) | ||||||
|     FreeLibrary(user32); |     FreeLibrary(user32); | ||||||
| 
 | 
 | ||||||
|     bitmap = CreateCompatibleBitmap(screen, width, height); |     bitmap = CreateCompatibleBitmap(screen, width, height); | ||||||
|     if (!bitmap) |     if (!bitmap) { | ||||||
|         goto error; |         goto error; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!SelectObject(screen_copy, bitmap)) |     if (!SelectObject(screen_copy, bitmap)) { | ||||||
|         goto error; |         goto error; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* step 2: copy bits into memory DC bitmap */ |     /* step 2: copy bits into memory DC bitmap */ | ||||||
| 
 | 
 | ||||||
|     rop = SRCCOPY; |     rop = SRCCOPY; | ||||||
|     if (includeLayeredWindows) |     if (includeLayeredWindows) { | ||||||
|         rop |= CAPTUREBLT; |         rop |= CAPTUREBLT; | ||||||
|     if (!BitBlt(screen_copy, 0, 0, width, height, screen, x, y, rop)) |     } | ||||||
|  |     if (!BitBlt(screen_copy, 0, 0, width, height, screen, x, y, rop)) { | ||||||
|         goto error; |         goto error; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* step 3: extract bits from bitmap */ |     /* step 3: extract bits from bitmap */ | ||||||
| 
 | 
 | ||||||
|     buffer = PyBytes_FromStringAndSize(NULL, height * ((width*3 + 3) & -4)); |     buffer = PyBytes_FromStringAndSize(NULL, height * ((width*3 + 3) & -4)); | ||||||
|     if (!buffer) |     if (!buffer) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     core.bcSize = sizeof(core); |     core.bcSize = sizeof(core); | ||||||
|     core.bcWidth = width; |     core.bcWidth = width; | ||||||
|  | @ -387,8 +409,9 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args) | ||||||
|     core.bcPlanes = 1; |     core.bcPlanes = 1; | ||||||
|     core.bcBitCount = 24; |     core.bcBitCount = 24; | ||||||
|     if (!GetDIBits(screen_copy, bitmap, 0, height, PyBytes_AS_STRING(buffer), |     if (!GetDIBits(screen_copy, bitmap, 0, height, PyBytes_AS_STRING(buffer), | ||||||
|                    (BITMAPINFO*) &core, DIB_RGB_COLORS)) |                    (BITMAPINFO*) &core, DIB_RGB_COLORS)) { | ||||||
|         goto error; |         goto error; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     DeleteObject(bitmap); |     DeleteObject(bitmap); | ||||||
|     DeleteDC(screen_copy); |     DeleteDC(screen_copy); | ||||||
|  | @ -418,12 +441,15 @@ static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam) | ||||||
|     title_size = GetWindowTextLength(hwnd); |     title_size = GetWindowTextLength(hwnd); | ||||||
|     if (title_size > 0) { |     if (title_size > 0) { | ||||||
|         title = PyUnicode_FromStringAndSize(NULL, title_size); |         title = PyUnicode_FromStringAndSize(NULL, title_size); | ||||||
|         if (title) |         if (title) { | ||||||
|             GetWindowTextW(hwnd, PyUnicode_AS_UNICODE(title), title_size+1); |             GetWindowTextW(hwnd, PyUnicode_AS_UNICODE(title), title_size+1); | ||||||
|     } else |         } | ||||||
|  |     } else { | ||||||
|         title = PyUnicode_FromString(""); |         title = PyUnicode_FromString(""); | ||||||
|     if (!title) |     } | ||||||
|  |     if (!title) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* get bounding boxes */ |     /* get bounding boxes */ | ||||||
|     GetClientRect(hwnd, &inner); |     GetClientRect(hwnd, &inner); | ||||||
|  | @ -434,15 +460,17 @@ static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam) | ||||||
|         inner.left, inner.top, inner.right, inner.bottom, |         inner.left, inner.top, inner.right, inner.bottom, | ||||||
|         outer.left, outer.top, outer.right, outer.bottom |         outer.left, outer.top, outer.right, outer.bottom | ||||||
|         ); |         ); | ||||||
|     if (!item) |     if (!item) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     status = PyList_Append(window_list, item); |     status = PyList_Append(window_list, item); | ||||||
| 
 | 
 | ||||||
|     Py_DECREF(item); |     Py_DECREF(item); | ||||||
| 
 | 
 | ||||||
|     if (status < 0) |     if (status < 0) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  | @ -453,8 +481,9 @@ PyImaging_ListWindowsWin32(PyObject* self, PyObject* args) | ||||||
|     PyObject* window_list; |     PyObject* window_list; | ||||||
| 
 | 
 | ||||||
|     window_list = PyList_New(0); |     window_list = PyList_New(0); | ||||||
|     if (!window_list) |     if (!window_list) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     EnumWindows(list_windows_callback, (LPARAM) window_list); |     EnumWindows(list_windows_callback, (LPARAM) window_list); | ||||||
| 
 | 
 | ||||||
|  | @ -556,8 +585,9 @@ windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) | ||||||
|                 GetWindowLongPtr(wnd, sizeof(PyObject*)); |                 GetWindowLongPtr(wnd, sizeof(PyObject*)); | ||||||
|             current_threadstate = PyThreadState_Swap(NULL); |             current_threadstate = PyThreadState_Swap(NULL); | ||||||
|             PyEval_RestoreThread(threadstate); |             PyEval_RestoreThread(threadstate); | ||||||
|         } else |         } else { | ||||||
|             return DefWindowProc(wnd, message, wParam, lParam); |             return DefWindowProc(wnd, message, wParam, lParam); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* process message */ |     /* process message */ | ||||||
|  | @ -575,28 +605,31 @@ windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) | ||||||
|             ps.rcPaint.left, ps.rcPaint.top, |             ps.rcPaint.left, ps.rcPaint.top, | ||||||
|             ps.rcPaint.right, ps.rcPaint.bottom |             ps.rcPaint.right, ps.rcPaint.bottom | ||||||
|             ); |             ); | ||||||
|         if (result) |         if (result) { | ||||||
|             Py_DECREF(result); |             Py_DECREF(result); | ||||||
|         else |         } else { | ||||||
|             callback_error("window damage callback"); |             callback_error("window damage callback"); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         result = PyObject_CallFunction( |         result = PyObject_CallFunction( | ||||||
|             callback, "s" F_HANDLE "iiii", "clear", dc, |             callback, "s" F_HANDLE "iiii", "clear", dc, | ||||||
|             0, 0, rect.right-rect.left, rect.bottom-rect.top |             0, 0, rect.right-rect.left, rect.bottom-rect.top | ||||||
|             ); |             ); | ||||||
|         if (result) |         if (result) { | ||||||
|             Py_DECREF(result); |             Py_DECREF(result); | ||||||
|         else |         } else { | ||||||
|             callback_error("window clear callback"); |             callback_error("window clear callback"); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         result = PyObject_CallFunction( |         result = PyObject_CallFunction( | ||||||
|             callback, "s" F_HANDLE "iiii", "repair", dc, |             callback, "s" F_HANDLE "iiii", "repair", dc, | ||||||
|             0, 0, rect.right-rect.left, rect.bottom-rect.top |             0, 0, rect.right-rect.left, rect.bottom-rect.top | ||||||
|             ); |             ); | ||||||
|         if (result) |         if (result) { | ||||||
|             Py_DECREF(result); |             Py_DECREF(result); | ||||||
|         else |         } else { | ||||||
|             callback_error("window repair callback"); |             callback_error("window repair callback"); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         ReleaseDC(wnd, dc); |         ReleaseDC(wnd, dc); | ||||||
|         EndPaint(wnd, &ps); |         EndPaint(wnd, &ps); | ||||||
|  | @ -610,17 +643,19 @@ windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) | ||||||
|         if (result) { |         if (result) { | ||||||
|             InvalidateRect(wnd, NULL, 1); |             InvalidateRect(wnd, NULL, 1); | ||||||
|             Py_DECREF(result); |             Py_DECREF(result); | ||||||
|         } else |         } else { | ||||||
|             callback_error("window resize callback"); |             callback_error("window resize callback"); | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     case WM_DESTROY: |     case WM_DESTROY: | ||||||
|         /* destroy window */ |         /* destroy window */ | ||||||
|         result = PyObject_CallFunction(callback, "s", "destroy"); |         result = PyObject_CallFunction(callback, "s", "destroy"); | ||||||
|         if (result) |         if (result) { | ||||||
|             Py_DECREF(result); |             Py_DECREF(result); | ||||||
|         else |         } else { | ||||||
|             callback_error("window destroy callback"); |             callback_error("window destroy callback"); | ||||||
|  |         } | ||||||
|         Py_DECREF(callback); |         Py_DECREF(callback); | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|  | @ -646,13 +681,16 @@ PyImaging_CreateWindowWin32(PyObject* self, PyObject* args) | ||||||
|     char* title; |     char* title; | ||||||
|     PyObject* callback; |     PyObject* callback; | ||||||
|     int width = 0, height = 0; |     int width = 0, height = 0; | ||||||
|     if (!PyArg_ParseTuple(args, "sO|ii", &title, &callback, &width, &height)) |     if (!PyArg_ParseTuple(args, "sO|ii", &title, &callback, &width, &height)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (width <= 0) |     if (width <= 0) { | ||||||
|         width = CW_USEDEFAULT; |         width = CW_USEDEFAULT; | ||||||
|     if (height <= 0) |     } | ||||||
|  |     if (height <= 0) { | ||||||
|         height = CW_USEDEFAULT; |         height = CW_USEDEFAULT; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* register toplevel window class */ |     /* register toplevel window class */ | ||||||
|     windowClass.style = CS_CLASSDC; |     windowClass.style = CS_CLASSDC; | ||||||
|  | @ -731,8 +769,9 @@ PyImaging_DrawWmf(PyObject* self, PyObject* args) | ||||||
|     int width, height; |     int width, height; | ||||||
|     int x0, y0, x1, y1; |     int x0, y0, x1, y1; | ||||||
|     if (!PyArg_ParseTuple(args, "y#(ii)(iiii):_load", &data, &datasize, |     if (!PyArg_ParseTuple(args, "y#(ii)(iiii):_load", &data, &datasize, | ||||||
|                           &width, &height, &x0, &x1, &y0, &y1)) |                           &width, &height, &x0, &x1, &y0, &y1)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* step 1: copy metafile contents into METAFILE object */ |     /* step 1: copy metafile contents into METAFILE object */ | ||||||
| 
 | 
 | ||||||
|  | @ -806,8 +845,9 @@ PyImaging_DrawWmf(PyObject* self, PyObject* args) | ||||||
| error: | error: | ||||||
|     DeleteEnhMetaFile(meta); |     DeleteEnhMetaFile(meta); | ||||||
| 
 | 
 | ||||||
|     if (bitmap) |     if (bitmap) { | ||||||
|         DeleteObject(bitmap); |         DeleteObject(bitmap); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     DeleteDC(dc); |     DeleteDC(dc); | ||||||
| 
 | 
 | ||||||
|  | @ -838,8 +878,9 @@ PyImaging_GrabScreenX11(PyObject* self, PyObject* args) | ||||||
|     xcb_generic_error_t* error; |     xcb_generic_error_t* error; | ||||||
|     PyObject* buffer = NULL; |     PyObject* buffer = NULL; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "|z", &display_name)) |     if (!PyArg_ParseTuple(args, "|z", &display_name)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* connect to X and get screen data */ |     /* connect to X and get screen data */ | ||||||
| 
 | 
 | ||||||
|  | @ -893,8 +934,9 @@ PyImaging_GrabScreenX11(PyObject* self, PyObject* args) | ||||||
|     free(reply); |     free(reply); | ||||||
|     xcb_disconnect(connection); |     xcb_disconnect(connection); | ||||||
| 
 | 
 | ||||||
|     if (!buffer) |     if (!buffer) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return Py_BuildValue("(ii)N", width, height, buffer); |     return Py_BuildValue("(ii)N", width, height, buffer); | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										163
									
								
								src/encode.c
									
									
									
									
									
								
							
							
						
						
									
										163
									
								
								src/encode.c
									
									
									
									
									
								
							|  | @ -55,12 +55,14 @@ PyImaging_EncoderNew(int contextsize) | ||||||
|     ImagingEncoderObject *encoder; |     ImagingEncoderObject *encoder; | ||||||
|     void *context; |     void *context; | ||||||
| 
 | 
 | ||||||
|     if(PyType_Ready(&ImagingEncoderType) < 0) |     if(PyType_Ready(&ImagingEncoderType) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder = PyObject_New(ImagingEncoderObject, &ImagingEncoderType); |     encoder = PyObject_New(ImagingEncoderObject, &ImagingEncoderType); | ||||||
|     if (encoder == NULL) |     if (encoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Clear the encoder state */ |     /* Clear the encoder state */ | ||||||
|     memset(&encoder->state, 0, sizeof(encoder->state)); |     memset(&encoder->state, 0, sizeof(encoder->state)); | ||||||
|  | @ -73,8 +75,9 @@ PyImaging_EncoderNew(int contextsize) | ||||||
|             (void) PyErr_NoMemory(); |             (void) PyErr_NoMemory(); | ||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
|     } else |     } else { | ||||||
|         context = 0; |         context = 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Initialize encoder context */ |     /* Initialize encoder context */ | ||||||
|     encoder->state.context = context; |     encoder->state.context = context; | ||||||
|  | @ -93,8 +96,9 @@ PyImaging_EncoderNew(int contextsize) | ||||||
| static void | static void | ||||||
| _dealloc(ImagingEncoderObject* encoder) | _dealloc(ImagingEncoderObject* encoder) | ||||||
| { | { | ||||||
|     if (encoder->cleanup) |     if (encoder->cleanup) { | ||||||
|         encoder->cleanup(&encoder->state); |         encoder->cleanup(&encoder->state); | ||||||
|  |     } | ||||||
|     free(encoder->state.buffer); |     free(encoder->state.buffer); | ||||||
|     free(encoder->state.context); |     free(encoder->state.context); | ||||||
|     Py_XDECREF(encoder->lock); |     Py_XDECREF(encoder->lock); | ||||||
|  | @ -125,19 +129,22 @@ _encode(ImagingEncoderObject* encoder, PyObject* args) | ||||||
| 
 | 
 | ||||||
|     Py_ssize_t bufsize = 16384; |     Py_ssize_t bufsize = 16384; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "|n", &bufsize)) |     if (!PyArg_ParseTuple(args, "|n", &bufsize)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     buf = PyBytes_FromStringAndSize(NULL, bufsize); |     buf = PyBytes_FromStringAndSize(NULL, bufsize); | ||||||
|     if (!buf) |     if (!buf) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     status = encoder->encode(encoder->im, &encoder->state, |     status = encoder->encode(encoder->im, &encoder->state, | ||||||
|                              (UINT8*) PyBytes_AsString(buf), bufsize); |                              (UINT8*) PyBytes_AsString(buf), bufsize); | ||||||
| 
 | 
 | ||||||
|     /* adjust string length to avoid slicing in encoder */ |     /* adjust string length to avoid slicing in encoder */ | ||||||
|     if (_PyBytes_Resize(&buf, (status > 0) ? status : 0) < 0) |     if (_PyBytes_Resize(&buf, (status > 0) ? status : 0) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     result = Py_BuildValue("iiO", status, encoder->state.errcode, buf); |     result = Py_BuildValue("iiO", status, encoder->state.errcode, buf); | ||||||
| 
 | 
 | ||||||
|  | @ -179,14 +186,16 @@ _encode_to_file(ImagingEncoderObject* encoder, PyObject* args) | ||||||
|     Py_ssize_t fh; |     Py_ssize_t fh; | ||||||
|     Py_ssize_t bufsize = 16384; |     Py_ssize_t bufsize = 16384; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "n|n", &fh, &bufsize)) |     if (!PyArg_ParseTuple(args, "n|n", &fh, &bufsize)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Allocate an encoder buffer */ |     /* Allocate an encoder buffer */ | ||||||
|     /* malloc check ok, either constant int, or checked by PyArg_ParseTuple */ |     /* malloc check ok, either constant int, or checked by PyArg_ParseTuple */ | ||||||
|     buf = (UINT8*) malloc(bufsize); |     buf = (UINT8*) malloc(bufsize); | ||||||
|     if (!buf) |     if (!buf) { | ||||||
|         return PyErr_NoMemory(); |         return PyErr_NoMemory(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
| 
 | 
 | ||||||
|  | @ -197,12 +206,13 @@ _encode_to_file(ImagingEncoderObject* encoder, PyObject* args) | ||||||
| 
 | 
 | ||||||
|         status = encoder->encode(encoder->im, &encoder->state, buf, bufsize); |         status = encoder->encode(encoder->im, &encoder->state, buf, bufsize); | ||||||
| 
 | 
 | ||||||
|         if (status > 0) |         if (status > 0) { | ||||||
|             if (write(fh, buf, status) < 0) { |             if (write(fh, buf, status) < 0) { | ||||||
|                 ImagingSectionLeave(&cookie); |                 ImagingSectionLeave(&cookie); | ||||||
|                 free(buf); |                 free(buf); | ||||||
|                 return PyErr_SetFromErrno(PyExc_OSError); |                 return PyErr_SetFromErrno(PyExc_OSError); | ||||||
|             } |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } while (encoder->state.errcode == 0); |     } while (encoder->state.errcode == 0); | ||||||
| 
 | 
 | ||||||
|  | @ -228,11 +238,13 @@ _setimage(ImagingEncoderObject* encoder, PyObject* args) | ||||||
|     x0 = y0 = x1 = y1 = 0; |     x0 = y0 = x1 = y1 = 0; | ||||||
| 
 | 
 | ||||||
|     /* FIXME: should publish the ImagingType descriptor */ |     /* FIXME: should publish the ImagingType descriptor */ | ||||||
|     if (!PyArg_ParseTuple(args, "O|(nnnn)", &op, &x0, &y0, &x1, &y1)) |     if (!PyArg_ParseTuple(args, "O|(nnnn)", &op, &x0, &y0, &x1, &y1)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
|     im = PyImaging_AsImaging(op); |     im = PyImaging_AsImaging(op); | ||||||
|     if (!im) |     if (!im) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder->im = im; |     encoder->im = im; | ||||||
| 
 | 
 | ||||||
|  | @ -264,8 +276,9 @@ _setimage(ImagingEncoderObject* encoder, PyObject* args) | ||||||
|         state->bytes = (state->bits * state->xsize+7)/8; |         state->bytes = (state->bits * state->xsize+7)/8; | ||||||
|         /* malloc check ok, overflow checked above */ |         /* malloc check ok, overflow checked above */ | ||||||
|         state->buffer = (UINT8*) malloc(state->bytes); |         state->buffer = (UINT8*) malloc(state->bytes); | ||||||
|         if (!state->buffer) |         if (!state->buffer) { | ||||||
|             return PyErr_NoMemory(); |             return PyErr_NoMemory(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Keep a reference to the image object, to make sure it doesn't
 |     /* Keep a reference to the image object, to make sure it doesn't
 | ||||||
|  | @ -284,8 +297,9 @@ _setfd(ImagingEncoderObject* encoder, PyObject* args) | ||||||
|     PyObject* fd; |     PyObject* fd; | ||||||
|     ImagingCodecState state; |     ImagingCodecState state; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "O", &fd)) |     if (!PyArg_ParseTuple(args, "O", &fd)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     state = &encoder->state; |     state = &encoder->state; | ||||||
| 
 | 
 | ||||||
|  | @ -386,8 +400,9 @@ PyImaging_EpsEncoderNew(PyObject* self, PyObject* args) | ||||||
|     ImagingEncoderObject* encoder; |     ImagingEncoderObject* encoder; | ||||||
| 
 | 
 | ||||||
|     encoder = PyImaging_EncoderNew(0); |     encoder = PyImaging_EncoderNew(0); | ||||||
|     if (encoder == NULL) |     if (encoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder->encode = ImagingEpsEncode; |     encoder->encode = ImagingEpsEncode; | ||||||
| 
 | 
 | ||||||
|  | @ -408,15 +423,18 @@ PyImaging_GifEncoderNew(PyObject* self, PyObject* args) | ||||||
|     char *rawmode; |     char *rawmode; | ||||||
|     Py_ssize_t bits = 8; |     Py_ssize_t bits = 8; | ||||||
|     Py_ssize_t interlace = 0; |     Py_ssize_t interlace = 0; | ||||||
|     if (!PyArg_ParseTuple(args, "ss|nn", &mode, &rawmode, &bits, &interlace)) |     if (!PyArg_ParseTuple(args, "ss|nn", &mode, &rawmode, &bits, &interlace)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder = PyImaging_EncoderNew(sizeof(GIFENCODERSTATE)); |     encoder = PyImaging_EncoderNew(sizeof(GIFENCODERSTATE)); | ||||||
|     if (encoder == NULL) |     if (encoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_packer(encoder, mode, rawmode) < 0) |     if (get_packer(encoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder->encode = ImagingGifEncode; |     encoder->encode = ImagingGifEncode; | ||||||
| 
 | 
 | ||||||
|  | @ -473,15 +491,18 @@ PyImaging_RawEncoderNew(PyObject* self, PyObject* args) | ||||||
|     Py_ssize_t stride = 0; |     Py_ssize_t stride = 0; | ||||||
|     Py_ssize_t ystep = 1; |     Py_ssize_t ystep = 1; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "ss|nn", &mode, &rawmode, &stride, &ystep)) |     if (!PyArg_ParseTuple(args, "ss|nn", &mode, &rawmode, &stride, &ystep)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder = PyImaging_EncoderNew(0); |     encoder = PyImaging_EncoderNew(0); | ||||||
|     if (encoder == NULL) |     if (encoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_packer(encoder, mode, rawmode) < 0) |     if (get_packer(encoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder->encode = ImagingRawEncode; |     encoder->encode = ImagingRawEncode; | ||||||
| 
 | 
 | ||||||
|  | @ -505,15 +526,18 @@ PyImaging_TgaRleEncoderNew(PyObject* self, PyObject* args) | ||||||
|     char *rawmode; |     char *rawmode; | ||||||
|     Py_ssize_t ystep = 1; |     Py_ssize_t ystep = 1; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "ss|n", &mode, &rawmode, &ystep)) |     if (!PyArg_ParseTuple(args, "ss|n", &mode, &rawmode, &ystep)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder = PyImaging_EncoderNew(0); |     encoder = PyImaging_EncoderNew(0); | ||||||
|     if (encoder == NULL) |     if (encoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_packer(encoder, mode, rawmode) < 0) |     if (get_packer(encoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder->encode = ImagingTgaRleEncode; |     encoder->encode = ImagingTgaRleEncode; | ||||||
| 
 | 
 | ||||||
|  | @ -534,11 +558,13 @@ PyImaging_XbmEncoderNew(PyObject* self, PyObject* args) | ||||||
|     ImagingEncoderObject* encoder; |     ImagingEncoderObject* encoder; | ||||||
| 
 | 
 | ||||||
|     encoder = PyImaging_EncoderNew(0); |     encoder = PyImaging_EncoderNew(0); | ||||||
|     if (encoder == NULL) |     if (encoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_packer(encoder, "1", "1;R") < 0) |     if (get_packer(encoder, "1", "1;R") < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder->encode = ImagingXbmEncode; |     encoder->encode = ImagingXbmEncode; | ||||||
| 
 | 
 | ||||||
|  | @ -569,19 +595,22 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args) | ||||||
|     if (!PyArg_ParseTuple(args, "ss|nnny#", &mode, &rawmode, |     if (!PyArg_ParseTuple(args, "ss|nnny#", &mode, &rawmode, | ||||||
|                           &optimize, |                           &optimize, | ||||||
|                           &compress_level, &compress_type, |                           &compress_level, &compress_type, | ||||||
|                           &dictionary, &dictionary_size)) |                           &dictionary, &dictionary_size)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Copy to avoid referencing Python's memory */ |     /* Copy to avoid referencing Python's memory */ | ||||||
|     if (dictionary && dictionary_size > 0) { |     if (dictionary && dictionary_size > 0) { | ||||||
|         /* malloc check ok, size comes from PyArg_ParseTuple */ |         /* malloc check ok, size comes from PyArg_ParseTuple */ | ||||||
|         char* p = malloc(dictionary_size); |         char* p = malloc(dictionary_size); | ||||||
|         if (!p) |         if (!p) { | ||||||
|             return PyErr_NoMemory(); |             return PyErr_NoMemory(); | ||||||
|  |         } | ||||||
|         memcpy(p, dictionary, dictionary_size); |         memcpy(p, dictionary, dictionary_size); | ||||||
|         dictionary = p; |         dictionary = p; | ||||||
|     } else |     } else { | ||||||
|         dictionary = NULL; |         dictionary = NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder = PyImaging_EncoderNew(sizeof(ZIPSTATE)); |     encoder = PyImaging_EncoderNew(sizeof(ZIPSTATE)); | ||||||
|     if (encoder == NULL) { |     if (encoder == NULL) { | ||||||
|  | @ -597,9 +626,10 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args) | ||||||
|     encoder->encode = ImagingZipEncode; |     encoder->encode = ImagingZipEncode; | ||||||
|     encoder->cleanup = ImagingZipEncodeCleanup; |     encoder->cleanup = ImagingZipEncodeCleanup; | ||||||
| 
 | 
 | ||||||
|     if (rawmode[0] == 'P') |     if (rawmode[0] == 'P') { | ||||||
|         /* disable filtering */ |         /* disable filtering */ | ||||||
|         ((ZIPSTATE*)encoder->state.context)->mode = ZIP_PNG_PALETTE; |         ((ZIPSTATE*)encoder->state.context)->mode = ZIP_PNG_PALETTE; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ((ZIPSTATE*)encoder->state.context)->optimize = optimize; |     ((ZIPSTATE*)encoder->state.context)->optimize = optimize; | ||||||
|     ((ZIPSTATE*)encoder->state.context)->compress_level = compress_level; |     ((ZIPSTATE*)encoder->state.context)->compress_level = compress_level; | ||||||
|  | @ -675,11 +705,13 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) | ||||||
|     TRACE(("new tiff encoder %s fp: %d, filename: %s \n", compname, fp, filename)); |     TRACE(("new tiff encoder %s fp: %d, filename: %s \n", compname, fp, filename)); | ||||||
| 
 | 
 | ||||||
|     encoder = PyImaging_EncoderNew(sizeof(TIFFSTATE)); |     encoder = PyImaging_EncoderNew(sizeof(TIFFSTATE)); | ||||||
|     if (encoder == NULL) |     if (encoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (get_packer(encoder, mode, rawmode) < 0) |     if (get_packer(encoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (! ImagingLibTiffEncodeInit(&encoder->state, filename, fp)) { |     if (! ImagingLibTiffEncodeInit(&encoder->state, filename, fp)) { | ||||||
|         Py_DECREF(encoder); |         Py_DECREF(encoder); | ||||||
|  | @ -1027,12 +1059,14 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) | ||||||
|                           &mode, &rawmode, &quality, |                           &mode, &rawmode, &quality, | ||||||
|                           &progressive, &smooth, &optimize, &streamtype, |                           &progressive, &smooth, &optimize, &streamtype, | ||||||
|                           &xdpi, &ydpi, &subsampling, &qtables, &extra, &extra_size, |                           &xdpi, &ydpi, &subsampling, &qtables, &extra, &extra_size, | ||||||
|                           &rawExif, &rawExifLen)) |                           &rawExif, &rawExifLen)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder = PyImaging_EncoderNew(sizeof(JPEGENCODERSTATE)); |     encoder = PyImaging_EncoderNew(sizeof(JPEGENCODERSTATE)); | ||||||
|     if (encoder == NULL) |     if (encoder == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // libjpeg-turbo supports different output formats.
 |     // libjpeg-turbo supports different output formats.
 | ||||||
|     // We are choosing Pillow's native format (3 color bytes + 1 padding)
 |     // We are choosing Pillow's native format (3 color bytes + 1 padding)
 | ||||||
|  | @ -1041,8 +1075,9 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) | ||||||
|         rawmode = "RGBX"; |         rawmode = "RGBX"; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (get_packer(encoder, mode, rawmode) < 0) |     if (get_packer(encoder, mode, rawmode) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // Freed in JpegEncode, Case 5
 |     // Freed in JpegEncode, Case 5
 | ||||||
|     qarrays = get_qtables_arrays(qtables, &qtablesLen); |     qarrays = get_qtables_arrays(qtables, &qtablesLen); | ||||||
|  | @ -1050,24 +1085,29 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) | ||||||
|     if (extra && extra_size > 0) { |     if (extra && extra_size > 0) { | ||||||
|         /* malloc check ok, length is from python parsearg */ |         /* malloc check ok, length is from python parsearg */ | ||||||
|         char* p = malloc(extra_size); // Freed in JpegEncode, Case 5
 |         char* p = malloc(extra_size); // Freed in JpegEncode, Case 5
 | ||||||
|         if (!p) |         if (!p) { | ||||||
|             return PyErr_NoMemory(); |             return PyErr_NoMemory(); | ||||||
|  |         } | ||||||
|         memcpy(p, extra, extra_size); |         memcpy(p, extra, extra_size); | ||||||
|         extra = p; |         extra = p; | ||||||
|     } else |     } else { | ||||||
|         extra = NULL; |         extra = NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (rawExif && rawExifLen > 0) { |     if (rawExif && rawExifLen > 0) { | ||||||
|         /* malloc check ok, length is from python parsearg */ |         /* malloc check ok, length is from python parsearg */ | ||||||
|         char* pp = malloc(rawExifLen); // Freed in JpegEncode, Case 5
 |         char* pp = malloc(rawExifLen); // Freed in JpegEncode, Case 5
 | ||||||
|         if (!pp) { |         if (!pp) { | ||||||
|             if (extra) free(extra); |             if (extra) { | ||||||
|  |                 free(extra); | ||||||
|  |             } | ||||||
|             return PyErr_NoMemory(); |             return PyErr_NoMemory(); | ||||||
|         } |         } | ||||||
|         memcpy(pp, rawExif, rawExifLen); |         memcpy(pp, rawExif, rawExifLen); | ||||||
|         rawExif = pp; |         rawExif = pp; | ||||||
|     } else |     } else { | ||||||
|         rawExif = NULL; |         rawExif = NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder->encode = ImagingJpegEncode; |     encoder->encode = ImagingJpegEncode; | ||||||
| 
 | 
 | ||||||
|  | @ -1111,10 +1151,12 @@ j2k_decode_coord_tuple(PyObject *tuple, int *x, int *y) | ||||||
|         *x = (int)PyLong_AsLong(PyTuple_GET_ITEM(tuple, 0)); |         *x = (int)PyLong_AsLong(PyTuple_GET_ITEM(tuple, 0)); | ||||||
|         *y = (int)PyLong_AsLong(PyTuple_GET_ITEM(tuple, 1)); |         *y = (int)PyLong_AsLong(PyTuple_GET_ITEM(tuple, 1)); | ||||||
| 
 | 
 | ||||||
|         if (*x < 0) |         if (*x < 0) { | ||||||
|             *x = 0; |             *x = 0; | ||||||
|         if (*y < 0) |         } | ||||||
|  |         if (*y < 0) { | ||||||
|             *y = 0; |             *y = 0; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1144,45 +1186,50 @@ PyImaging_Jpeg2KEncoderNew(PyObject *self, PyObject *args) | ||||||
|                           &quality_mode, &quality_layers, &num_resolutions, |                           &quality_mode, &quality_layers, &num_resolutions, | ||||||
|                           &cblk_size, &precinct_size, |                           &cblk_size, &precinct_size, | ||||||
|                           &irreversible, &progression, &cinema_mode, |                           &irreversible, &progression, &cinema_mode, | ||||||
|                           &fd)) |                           &fd)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (strcmp (format, "j2k") == 0) |     if (strcmp (format, "j2k") == 0) { | ||||||
|         codec_format = OPJ_CODEC_J2K; |         codec_format = OPJ_CODEC_J2K; | ||||||
|     else if (strcmp (format, "jpt") == 0) |     } else if (strcmp (format, "jpt") == 0) { | ||||||
|         codec_format = OPJ_CODEC_JPT; |         codec_format = OPJ_CODEC_JPT; | ||||||
|     else if (strcmp (format, "jp2") == 0) |     } else if (strcmp (format, "jp2") == 0) { | ||||||
|         codec_format = OPJ_CODEC_JP2; |         codec_format = OPJ_CODEC_JP2; | ||||||
|     else |     } else { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (strcmp(progression, "LRCP") == 0) |     if (strcmp(progression, "LRCP") == 0) { | ||||||
|         prog_order = OPJ_LRCP; |         prog_order = OPJ_LRCP; | ||||||
|     else if (strcmp(progression, "RLCP") == 0) |     } else if (strcmp(progression, "RLCP") == 0) { | ||||||
|         prog_order = OPJ_RLCP; |         prog_order = OPJ_RLCP; | ||||||
|     else if (strcmp(progression, "RPCL") == 0) |     } else if (strcmp(progression, "RPCL") == 0) { | ||||||
|         prog_order = OPJ_RPCL; |         prog_order = OPJ_RPCL; | ||||||
|     else if (strcmp(progression, "PCRL") == 0) |     } else if (strcmp(progression, "PCRL") == 0) { | ||||||
|         prog_order = OPJ_PCRL; |         prog_order = OPJ_PCRL; | ||||||
|     else if (strcmp(progression, "CPRL") == 0) |     } else if (strcmp(progression, "CPRL") == 0) { | ||||||
|         prog_order = OPJ_CPRL; |         prog_order = OPJ_CPRL; | ||||||
|     else |     } else { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (strcmp(cinema_mode, "no") == 0) |     if (strcmp(cinema_mode, "no") == 0) { | ||||||
|         cine_mode = OPJ_OFF; |         cine_mode = OPJ_OFF; | ||||||
|     else if (strcmp(cinema_mode, "cinema2k-24") == 0) |     } else if (strcmp(cinema_mode, "cinema2k-24") == 0) { | ||||||
|         cine_mode = OPJ_CINEMA2K_24; |         cine_mode = OPJ_CINEMA2K_24; | ||||||
|     else if (strcmp(cinema_mode, "cinema2k-48") == 0) |     } else if (strcmp(cinema_mode, "cinema2k-48") == 0) { | ||||||
|         cine_mode = OPJ_CINEMA2K_48; |         cine_mode = OPJ_CINEMA2K_48; | ||||||
|     else if (strcmp(cinema_mode, "cinema4k-24") == 0) |     } else if (strcmp(cinema_mode, "cinema4k-24") == 0) { | ||||||
|         cine_mode = OPJ_CINEMA4K_24; |         cine_mode = OPJ_CINEMA4K_24; | ||||||
|     else |     } else { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder = PyImaging_EncoderNew(sizeof(JPEG2KENCODESTATE)); |     encoder = PyImaging_EncoderNew(sizeof(JPEG2KENCODESTATE)); | ||||||
|     if (!encoder) |     if (!encoder) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     encoder->encode = ImagingJpeg2KEncode; |     encoder->encode = ImagingJpeg2KEncode; | ||||||
|     encoder->cleanup = ImagingJpeg2KEncodeCleanup; |     encoder->cleanup = ImagingJpeg2KEncodeCleanup; | ||||||
|  |  | ||||||
|  | @ -22,8 +22,9 @@ static inline UINT32 | ||||||
| hash(const char* mode) | hash(const char* mode) | ||||||
| { | { | ||||||
|     UINT32 i = ACCESS_TABLE_HASH; |     UINT32 i = ACCESS_TABLE_HASH; | ||||||
|     while (*mode) |     while (*mode) { | ||||||
|         i = ((i<<5) + i) ^ (UINT8) *mode++; |         i = ((i<<5) + i) ^ (UINT8) *mode++; | ||||||
|  |     } | ||||||
|     return i % ACCESS_TABLE_SIZE; |     return i % ACCESS_TABLE_SIZE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -149,10 +150,11 @@ get_pixel_32B(Imaging im, int x, int y, void* color) | ||||||
| static void | static void | ||||||
| put_pixel(Imaging im, int x, int y, const void* color) | put_pixel(Imaging im, int x, int y, const void* color) | ||||||
| { | { | ||||||
|     if (im->image8) |     if (im->image8) { | ||||||
|         im->image8[y][x] = *((UINT8*) color); |         im->image8[y][x] = *((UINT8*) color); | ||||||
|     else |     } else { | ||||||
|         memcpy(&im->image32[y][x], color, sizeof(INT32)); |         memcpy(&im->image32[y][x], color, sizeof(INT32)); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -237,8 +239,9 @@ ImagingAccess | ||||||
| ImagingAccessNew(Imaging im) | ImagingAccessNew(Imaging im) | ||||||
| { | { | ||||||
|     ImagingAccess access = &access_table[hash(im->mode)]; |     ImagingAccess access = &access_table[hash(im->mode)]; | ||||||
|     if (im->mode[0] != access->mode[0] || strcmp(im->mode, access->mode) != 0) |     if (im->mode[0] != access->mode[0] || strcmp(im->mode, access->mode) != 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
|     return access; |     return access; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,19 +33,22 @@ ImagingAlphaComposite(Imaging imDst, Imaging imSrc) | ||||||
|     if (!imDst || !imSrc || |     if (!imDst || !imSrc || | ||||||
|         strcmp(imDst->mode, "RGBA") || |         strcmp(imDst->mode, "RGBA") || | ||||||
|         imDst->type != IMAGING_TYPE_UINT8 || |         imDst->type != IMAGING_TYPE_UINT8 || | ||||||
|         imDst->bands != 4) |         imDst->bands != 4) { | ||||||
|         return ImagingError_ModeError(); |         return ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (strcmp(imDst->mode, imSrc->mode) || |     if (strcmp(imDst->mode, imSrc->mode) || | ||||||
|         imDst->type  != imSrc->type  || |         imDst->type  != imSrc->type  || | ||||||
|         imDst->bands != imSrc->bands || |         imDst->bands != imSrc->bands || | ||||||
|         imDst->xsize != imSrc->xsize || |         imDst->xsize != imSrc->xsize || | ||||||
|         imDst->ysize != imSrc->ysize) |         imDst->ysize != imSrc->ysize) { | ||||||
|         return ImagingError_Mismatch(); |         return ImagingError_Mismatch(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty(imDst->mode, imDst->xsize, imDst->ysize); |     imOut = ImagingNewDirty(imDst->mode, imDst->xsize, imDst->ysize); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     for (y = 0; y < imDst->ysize; y++) { |     for (y = 0; y < imDst->ysize; y++) { | ||||||
|         rgba8* dst = (rgba8*) imDst->image[y]; |         rgba8* dst = (rgba8*) imDst->image[y]; | ||||||
|  |  | ||||||
|  | @ -26,23 +26,28 @@ ImagingGetBand(Imaging imIn, int band) | ||||||
|     int x, y; |     int x, y; | ||||||
| 
 | 
 | ||||||
|     /* Check arguments */ |     /* Check arguments */ | ||||||
|     if (!imIn || imIn->type != IMAGING_TYPE_UINT8) |     if (!imIn || imIn->type != IMAGING_TYPE_UINT8) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (band < 0 || band >= imIn->bands) |     if (band < 0 || band >= imIn->bands) { | ||||||
|         return (Imaging) ImagingError_ValueError("band index out of range"); |         return (Imaging) ImagingError_ValueError("band index out of range"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Shortcuts */ |     /* Shortcuts */ | ||||||
|     if (imIn->bands == 1) |     if (imIn->bands == 1) { | ||||||
|         return ImagingCopy(imIn); |         return ImagingCopy(imIn); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Special case for LXXA etc */ |     /* Special case for LXXA etc */ | ||||||
|     if (imIn->bands == 2 && band == 1) |     if (imIn->bands == 2 && band == 1) { | ||||||
|         band = 3; |         band = 3; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty("L", imIn->xsize, imIn->ysize); |     imOut = ImagingNewDirty("L", imIn->xsize, imIn->ysize); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Extract band from image */ |     /* Extract band from image */ | ||||||
|     for (y = 0; y < imIn->ysize; y++) { |     for (y = 0; y < imIn->ysize; y++) { | ||||||
|  | @ -173,24 +178,29 @@ ImagingPutBand(Imaging imOut, Imaging imIn, int band) | ||||||
|     int x, y; |     int x, y; | ||||||
| 
 | 
 | ||||||
|     /* Check arguments */ |     /* Check arguments */ | ||||||
|     if (!imIn || imIn->bands != 1 || !imOut) |     if (!imIn || imIn->bands != 1 || !imOut) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (band < 0 || band >= imOut->bands) |     if (band < 0 || band >= imOut->bands) { | ||||||
|         return (Imaging) ImagingError_ValueError("band index out of range"); |         return (Imaging) ImagingError_ValueError("band index out of range"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (imIn->type  != imOut->type  || |     if (imIn->type  != imOut->type  || | ||||||
|         imIn->xsize != imOut->xsize || |         imIn->xsize != imOut->xsize || | ||||||
|         imIn->ysize != imOut->ysize) |         imIn->ysize != imOut->ysize) { | ||||||
|         return (Imaging) ImagingError_Mismatch(); |         return (Imaging) ImagingError_Mismatch(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Shortcuts */ |     /* Shortcuts */ | ||||||
|     if (imOut->bands == 1) |     if (imOut->bands == 1) { | ||||||
|         return ImagingCopy2(imOut, imIn); |         return ImagingCopy2(imOut, imIn); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Special case for LXXA etc */ |     /* Special case for LXXA etc */ | ||||||
|     if (imOut->bands == 2 && band == 1) |     if (imOut->bands == 2 && band == 1) { | ||||||
|         band = 3; |         band = 3; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Insert band into image */ |     /* Insert band into image */ | ||||||
|     for (y = 0; y < imIn->ysize; y++) { |     for (y = 0; y < imIn->ysize; y++) { | ||||||
|  | @ -211,15 +221,18 @@ ImagingFillBand(Imaging imOut, int band, int color) | ||||||
|     int x, y; |     int x, y; | ||||||
| 
 | 
 | ||||||
|     /* Check arguments */ |     /* Check arguments */ | ||||||
|     if (!imOut || imOut->type != IMAGING_TYPE_UINT8) |     if (!imOut || imOut->type != IMAGING_TYPE_UINT8) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (band < 0 || band >= imOut->bands) |     if (band < 0 || band >= imOut->bands) { | ||||||
|         return (Imaging) ImagingError_ValueError("band index out of range"); |         return (Imaging) ImagingError_ValueError("band index out of range"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Special case for LXXA etc */ |     /* Special case for LXXA etc */ | ||||||
|     if (imOut->bands == 2 && band == 1) |     if (imOut->bands == 2 && band == 1) { | ||||||
|         band = 3; |         band = 3; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     color = CLIP8(color); |     color = CLIP8(color); | ||||||
| 
 | 
 | ||||||
|  | @ -263,16 +276,18 @@ ImagingMerge(const char* mode, Imaging bands[4]) | ||||||
|     bandsCount = i; |     bandsCount = i; | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty(mode, firstBand->xsize, firstBand->ysize); |     imOut = ImagingNewDirty(mode, firstBand->xsize, firstBand->ysize); | ||||||
|     if ( ! imOut) |     if ( ! imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (imOut->bands != bandsCount) { |     if (imOut->bands != bandsCount) { | ||||||
|         ImagingDelete(imOut); |         ImagingDelete(imOut); | ||||||
|         return (Imaging) ImagingError_ValueError("wrong number of bands"); |         return (Imaging) ImagingError_ValueError("wrong number of bands"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (imOut->bands == 1) |     if (imOut->bands == 1) { | ||||||
|         return ImagingCopy2(imOut, firstBand); |         return ImagingCopy2(imOut, firstBand); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (imOut->bands == 2) { |     if (imOut->bands == 2) { | ||||||
|         for (y = 0; y < imOut->ysize; y++) { |         for (y = 0; y < imOut->ysize; y++) { | ||||||
|  |  | ||||||
|  | @ -610,15 +610,21 @@ static int bc6_unquantize(UINT16 v, int prec, int sign) { | ||||||
|     int x; |     int x; | ||||||
|     if (!sign) { |     if (!sign) { | ||||||
|         x = v; |         x = v; | ||||||
|         if (prec >= 15) return x; |         if (prec >= 15) { | ||||||
|         if (x == 0) return 0; |             return x; | ||||||
|  |         } | ||||||
|  |         if (x == 0) { | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|         if (x == ((1 << prec) - 1)) { |         if (x == ((1 << prec) - 1)) { | ||||||
|             return 0xffff; |             return 0xffff; | ||||||
|         } |         } | ||||||
|         return ((x << 15) + 0x4000) >> (prec - 1); |         return ((x << 15) + 0x4000) >> (prec - 1); | ||||||
|     } else { |     } else { | ||||||
|         x = (INT16)v; |         x = (INT16)v; | ||||||
|         if (prec >= 16) return x; |         if (prec >= 16) { | ||||||
|  |             return x; | ||||||
|  |         } | ||||||
|         if (x < 0) { |         if (x < 0) { | ||||||
|             s = 1; |             s = 1; | ||||||
|             x = -x; |             x = -x; | ||||||
|  | @ -820,7 +826,9 @@ static int decode_bcn(Imaging im, ImagingCodecState state, const UINT8* src, int | ||||||
|             put_block(im, state, (const char *)col, sizeof(col[0]), C); \ |             put_block(im, state, (const char *)col, sizeof(col[0]), C); \ | ||||||
|             ptr += SZ; \ |             ptr += SZ; \ | ||||||
|             bytes -= SZ; \ |             bytes -= SZ; \ | ||||||
|             if (state->y >= ymax) return -1; \ |             if (state->y >= ymax) {\ | ||||||
|  |                 return -1; \ | ||||||
|  |             }\ | ||||||
|         } \ |         } \ | ||||||
|         break |         break | ||||||
| 
 | 
 | ||||||
|  | @ -836,7 +844,9 @@ static int decode_bcn(Imaging im, ImagingCodecState state, const UINT8* src, int | ||||||
|                 put_block(im, state, (const char *)col, sizeof(col[0]), C); |                 put_block(im, state, (const char *)col, sizeof(col[0]), C); | ||||||
|                 ptr += 16; |                 ptr += 16; | ||||||
|                 bytes -= 16; |                 bytes -= 16; | ||||||
|                 if (state->y >= ymax) return -1; \ |                 if (state->y >= ymax) {\ | ||||||
|  |                     return -1; \ | ||||||
|  |                 }\ | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         DECODE_LOOP(7, 16, rgba); |         DECODE_LOOP(7, 16, rgba); | ||||||
|  |  | ||||||
|  | @ -43,15 +43,17 @@ ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
| 
 | 
 | ||||||
|         bitstate->mask = (1<<bitstate->bits)-1; |         bitstate->mask = (1<<bitstate->bits)-1; | ||||||
| 
 | 
 | ||||||
|         if (bitstate->sign) |         if (bitstate->sign) { | ||||||
|             bitstate->signmask = (1<<(bitstate->bits-1)); |             bitstate->signmask = (1<<(bitstate->bits-1)); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         /* check image orientation */ |         /* check image orientation */ | ||||||
|         if (state->ystep < 0) { |         if (state->ystep < 0) { | ||||||
|             state->y = state->ysize-1; |             state->y = state->ysize-1; | ||||||
|             state->ystep = -1; |             state->ystep = -1; | ||||||
|         } else |         } else { | ||||||
|             state->ystep = 1; |             state->ystep = 1; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         state->state = 1; |         state->state = 1; | ||||||
| 
 | 
 | ||||||
|  | @ -67,12 +69,13 @@ ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|         bytes--; |         bytes--; | ||||||
| 
 | 
 | ||||||
|         /* get a byte from the input stream and insert in the bit buffer */ |         /* get a byte from the input stream and insert in the bit buffer */ | ||||||
|         if (bitstate->fill&1) |         if (bitstate->fill&1) { | ||||||
|             /* fill MSB first */ |             /* fill MSB first */ | ||||||
|             bitstate->bitbuffer |= (unsigned long) byte << bitstate->bitcount; |             bitstate->bitbuffer |= (unsigned long) byte << bitstate->bitcount; | ||||||
|         else |         } else { | ||||||
|             /* fill LSB first */ |             /* fill LSB first */ | ||||||
|             bitstate->bitbuffer = (bitstate->bitbuffer << 8) | byte; |             bitstate->bitbuffer = (bitstate->bitbuffer << 8) | byte; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         bitstate->bitcount += 8; |         bitstate->bitcount += 8; | ||||||
| 
 | 
 | ||||||
|  | @ -85,35 +88,39 @@ ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|             if (bitstate->fill&2) { |             if (bitstate->fill&2) { | ||||||
|                 /* store LSB first */ |                 /* store LSB first */ | ||||||
|                 data = bitstate->bitbuffer & bitstate->mask; |                 data = bitstate->bitbuffer & bitstate->mask; | ||||||
|                 if (bitstate->bitcount > 32) |                 if (bitstate->bitcount > 32) { | ||||||
|                     /* bitbuffer overflow; restore it from last input byte */ |                     /* bitbuffer overflow; restore it from last input byte */ | ||||||
|                     bitstate->bitbuffer = byte >> (8 - (bitstate->bitcount - |                     bitstate->bitbuffer = byte >> (8 - (bitstate->bitcount - | ||||||
|                                                         bitstate->bits)); |                                                         bitstate->bits)); | ||||||
|                 else |                 } else { | ||||||
|                     bitstate->bitbuffer >>= bitstate->bits; |                     bitstate->bitbuffer >>= bitstate->bits; | ||||||
|             } else |                 } | ||||||
|  |             } else { | ||||||
|                 /* store MSB first */ |                 /* store MSB first */ | ||||||
|                 data = (bitstate->bitbuffer >> (bitstate->bitcount - |                 data = (bitstate->bitbuffer >> (bitstate->bitcount - | ||||||
|                                                 bitstate->bits)) |                                                 bitstate->bits)) | ||||||
|                        & bitstate->mask; |                        & bitstate->mask; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             bitstate->bitcount -= bitstate->bits; |             bitstate->bitcount -= bitstate->bits; | ||||||
| 
 | 
 | ||||||
|             if (bitstate->lutsize > 0) { |             if (bitstate->lutsize > 0) { | ||||||
|                 /* map through lookup table */ |                 /* map through lookup table */ | ||||||
|                 if (data <= 0) |                 if (data <= 0) { | ||||||
|                     pixel = bitstate->lut[0]; |                     pixel = bitstate->lut[0]; | ||||||
|                 else if (data >= bitstate->lutsize) |                 } else if (data >= bitstate->lutsize) { | ||||||
|                     pixel = bitstate->lut[bitstate->lutsize-1]; |                     pixel = bitstate->lut[bitstate->lutsize-1]; | ||||||
|                 else |                 } else { | ||||||
|                     pixel = bitstate->lut[data]; |                     pixel = bitstate->lut[data]; | ||||||
|  |                 } | ||||||
|             } else { |             } else { | ||||||
|                 /* convert */ |                 /* convert */ | ||||||
|                 if (data & bitstate->signmask) |                 if (data & bitstate->signmask) { | ||||||
|                     /* image memory contains signed data */ |                     /* image memory contains signed data */ | ||||||
|                     pixel = (FLOAT32) (INT32) (data | ~bitstate->mask); |                     pixel = (FLOAT32) (INT32) (data | ~bitstate->mask); | ||||||
|                 else |                 } else { | ||||||
|                     pixel = (FLOAT32) data; |                     pixel = (FLOAT32) data; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             *(FLOAT32*)(&im->image32[state->y][state->x]) = pixel; |             *(FLOAT32*)(&im->image32[state->y][state->x]) = pixel; | ||||||
|  | @ -128,8 +135,9 @@ ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|                 } |                 } | ||||||
|                 state->x = 0; |                 state->x = 0; | ||||||
|                 /* reset bit buffer */ |                 /* reset bit buffer */ | ||||||
|                 if (bitstate->pad > 0) |                 if (bitstate->pad > 0) { | ||||||
|                     bitstate->bitcount = 0; |                     bitstate->bitcount = 0; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -28,24 +28,28 @@ ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha) | ||||||
|     /* Check arguments */ |     /* Check arguments */ | ||||||
|     if (!imIn1 || !imIn2 || imIn1->type != IMAGING_TYPE_UINT8 |     if (!imIn1 || !imIn2 || imIn1->type != IMAGING_TYPE_UINT8 | ||||||
|         || imIn1->palette || strcmp(imIn1->mode, "1") == 0 |         || imIn1->palette || strcmp(imIn1->mode, "1") == 0 | ||||||
|         || imIn2->palette || strcmp(imIn2->mode, "1") == 0) |         || imIn2->palette || strcmp(imIn2->mode, "1") == 0) { | ||||||
|         return ImagingError_ModeError(); |         return ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (imIn1->type  != imIn2->type  || |     if (imIn1->type  != imIn2->type  || | ||||||
|         imIn1->bands != imIn2->bands || |         imIn1->bands != imIn2->bands || | ||||||
|         imIn1->xsize != imIn2->xsize || |         imIn1->xsize != imIn2->xsize || | ||||||
|         imIn1->ysize != imIn2->ysize) |         imIn1->ysize != imIn2->ysize) { | ||||||
|         return ImagingError_Mismatch(); |         return ImagingError_Mismatch(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Shortcuts */ |     /* Shortcuts */ | ||||||
|     if (alpha == 0.0) |     if (alpha == 0.0) { | ||||||
|         return ImagingCopy(imIn1); |         return ImagingCopy(imIn1); | ||||||
|     else if (alpha == 1.0) |     } else if (alpha == 1.0) { | ||||||
|         return ImagingCopy(imIn2); |         return ImagingCopy(imIn2); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty(imIn1->mode, imIn1->xsize, imIn1->ysize); |     imOut = ImagingNewDirty(imIn1->mode, imIn1->xsize, imIn1->ysize); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (alpha >= 0 && alpha <= 1.0) { |     if (alpha >= 0 && alpha <= 1.0) { | ||||||
|         /* Interpolate between bands */ |         /* Interpolate between bands */ | ||||||
|  | @ -53,9 +57,10 @@ ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha) | ||||||
|             UINT8* in1 = (UINT8*) imIn1->image[y]; |             UINT8* in1 = (UINT8*) imIn1->image[y]; | ||||||
|             UINT8* in2 = (UINT8*) imIn2->image[y]; |             UINT8* in2 = (UINT8*) imIn2->image[y]; | ||||||
|             UINT8* out = (UINT8*) imOut->image[y]; |             UINT8* out = (UINT8*) imOut->image[y]; | ||||||
|             for (x = 0; x < imIn1->linesize; x++) |             for (x = 0; x < imIn1->linesize; x++) { | ||||||
|                 out[x] = (UINT8) |                 out[x] = (UINT8) | ||||||
|                     ((int) in1[x] + alpha * ((int) in2[x] - (int) in1[x])); |                     ((int) in1[x] + alpha * ((int) in2[x] - (int) in1[x])); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         /* Extrapolation; must make sure to clip resulting values */ |         /* Extrapolation; must make sure to clip resulting values */ | ||||||
|  | @ -66,12 +71,13 @@ ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha) | ||||||
|             for (x = 0; x < imIn1->linesize; x++) { |             for (x = 0; x < imIn1->linesize; x++) { | ||||||
|                 float temp = (float) |                 float temp = (float) | ||||||
|                     ((int) in1[x] + alpha * ((int) in2[x] - (int) in1[x])); |                     ((int) in1[x] + alpha * ((int) in2[x] - (int) in1[x])); | ||||||
|                 if (temp <= 0.0) |                 if (temp <= 0.0) { | ||||||
|                     out[x] = 0; |                     out[x] = 0; | ||||||
|                 else if (temp >= 255.0) |                 } else if (temp >= 255.0) { | ||||||
|                     out[x] = 255; |                     out[x] = 255; | ||||||
|                 else |                 } else { | ||||||
|                     out[x] = (UINT8) temp; |                     out[x] = (UINT8) temp; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -184,8 +184,9 @@ ImagingHorizontalBoxBlur(Imaging imOut, Imaging imIn, float floatRadius) | ||||||
|     int edgeB = MAX(imIn->xsize - radius - 1, 0); |     int edgeB = MAX(imIn->xsize - radius - 1, 0); | ||||||
| 
 | 
 | ||||||
|     UINT32 *lineOut = calloc(imIn->xsize, sizeof(UINT32)); |     UINT32 *lineOut = calloc(imIn->xsize, sizeof(UINT32)); | ||||||
|     if (lineOut == NULL) |     if (lineOut == NULL) { | ||||||
|         return ImagingError_MemoryError(); |         return ImagingError_MemoryError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // printf(">>> %d %d %d\n", radius, ww, fw);
 |     // printf(">>> %d %d %d\n", radius, ww, fw);
 | ||||||
| 
 | 
 | ||||||
|  | @ -248,11 +249,13 @@ ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n) | ||||||
|         imIn->type  != imOut->type  || |         imIn->type  != imOut->type  || | ||||||
|         imIn->bands != imOut->bands || |         imIn->bands != imOut->bands || | ||||||
|         imIn->xsize != imOut->xsize || |         imIn->xsize != imOut->xsize || | ||||||
|         imIn->ysize != imOut->ysize) |         imIn->ysize != imOut->ysize) { | ||||||
|         return ImagingError_Mismatch(); |         return ImagingError_Mismatch(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (imIn->type != IMAGING_TYPE_UINT8) |     if (imIn->type != IMAGING_TYPE_UINT8) { | ||||||
|         return ImagingError_ModeError(); |         return ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!(strcmp(imIn->mode, "RGB") == 0 || |     if (!(strcmp(imIn->mode, "RGB") == 0 || | ||||||
|           strcmp(imIn->mode, "RGBA") == 0 || |           strcmp(imIn->mode, "RGBA") == 0 || | ||||||
|  | @ -261,12 +264,14 @@ ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n) | ||||||
|           strcmp(imIn->mode, "CMYK") == 0 || |           strcmp(imIn->mode, "CMYK") == 0 || | ||||||
|           strcmp(imIn->mode, "L") == 0 || |           strcmp(imIn->mode, "L") == 0 || | ||||||
|           strcmp(imIn->mode, "LA") == 0 || |           strcmp(imIn->mode, "LA") == 0 || | ||||||
|           strcmp(imIn->mode, "La") == 0)) |           strcmp(imIn->mode, "La") == 0)) { | ||||||
|         return ImagingError_ModeError(); |         return ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imTransposed = ImagingNewDirty(imIn->mode, imIn->ysize, imIn->xsize); |     imTransposed = ImagingNewDirty(imIn->mode, imIn->ysize, imIn->xsize); | ||||||
|     if (!imTransposed) |     if (!imTransposed) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Apply blur in one dimension.
 |     /* Apply blur in one dimension.
 | ||||||
|        Use imOut as a destination at first pass, |        Use imOut as a destination at first pass, | ||||||
|  |  | ||||||
|  | @ -23,20 +23,22 @@ | ||||||
|     int x, y;\ |     int x, y;\ | ||||||
|     Imaging imOut;\ |     Imaging imOut;\ | ||||||
|     imOut = create(imIn1, imIn2, mode);\ |     imOut = create(imIn1, imIn2, mode);\ | ||||||
|     if (!imOut)\ |     if (!imOut) {\ | ||||||
|         return NULL;\ |         return NULL;\ | ||||||
|  |     }\ | ||||||
|     for (y = 0; y < imOut->ysize; y++) {\ |     for (y = 0; y < imOut->ysize; y++) {\ | ||||||
|         UINT8* out = (UINT8*) imOut->image[y];\ |         UINT8* out = (UINT8*) imOut->image[y];\ | ||||||
|         UINT8* in1 = (UINT8*) imIn1->image[y];\ |         UINT8* in1 = (UINT8*) imIn1->image[y];\ | ||||||
|         UINT8* in2 = (UINT8*) imIn2->image[y];\ |         UINT8* in2 = (UINT8*) imIn2->image[y];\ | ||||||
|         for (x = 0; x < imOut->linesize; x++) {\ |         for (x = 0; x < imOut->linesize; x++) {\ | ||||||
|             int temp = operation;\ |             int temp = operation;\ | ||||||
|             if (temp <= 0)\ |             if (temp <= 0) {\ | ||||||
|                 out[x] = 0;\ |                 out[x] = 0;\ | ||||||
|             else if (temp >= 255)\ |             } else if (temp >= 255) {\ | ||||||
|                 out[x] = 255;\ |                 out[x] = 255;\ | ||||||
|             else\ |             } else {\ | ||||||
|                 out[x] = temp;\ |                 out[x] = temp;\ | ||||||
|  |             }\ | ||||||
|         }\ |         }\ | ||||||
|     }\ |     }\ | ||||||
|     return imOut; |     return imOut; | ||||||
|  | @ -45,8 +47,9 @@ | ||||||
|     int x, y;\ |     int x, y;\ | ||||||
|     Imaging imOut;\ |     Imaging imOut;\ | ||||||
|     imOut = create(imIn1, imIn2, mode);\ |     imOut = create(imIn1, imIn2, mode);\ | ||||||
|     if (!imOut)\ |     if (!imOut) {\ | ||||||
|         return NULL;\ |         return NULL;\ | ||||||
|  |     }\ | ||||||
|     for (y = 0; y < imOut->ysize; y++) {\ |     for (y = 0; y < imOut->ysize; y++) {\ | ||||||
|         UINT8* out = (UINT8*) imOut->image[y];\ |         UINT8* out = (UINT8*) imOut->image[y];\ | ||||||
|         UINT8* in1 = (UINT8*) imIn1->image[y];\ |         UINT8* in1 = (UINT8*) imIn1->image[y];\ | ||||||
|  | @ -63,11 +66,13 @@ create(Imaging im1, Imaging im2, char* mode) | ||||||
|     int xsize, ysize; |     int xsize, ysize; | ||||||
| 
 | 
 | ||||||
|     if (!im1 || !im2 || im1->type != IMAGING_TYPE_UINT8 || |     if (!im1 || !im2 || im1->type != IMAGING_TYPE_UINT8 || | ||||||
|         (mode != NULL && (strcmp(im1->mode, "1") || strcmp(im2->mode, "1")))) |         (mode != NULL && (strcmp(im1->mode, "1") || strcmp(im2->mode, "1")))) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
|     if (im1->type  != im2->type  || |     if (im1->type  != im2->type  || | ||||||
|         im1->bands != im2->bands) |         im1->bands != im2->bands) { | ||||||
|         return (Imaging) ImagingError_Mismatch(); |         return (Imaging) ImagingError_Mismatch(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     xsize = (im1->xsize < im2->xsize) ? im1->xsize : im2->xsize; |     xsize = (im1->xsize < im2->xsize) ? im1->xsize : im2->xsize; | ||||||
|     ysize = (im1->ysize < im2->ysize) ? im1->ysize : im2->ysize; |     ysize = (im1->ysize < im2->ysize) ? im1->ysize : im2->ysize; | ||||||
|  |  | ||||||
|  | @ -123,8 +123,9 @@ static void | ||||||
| l2bit(UINT8* out, const UINT8* in, int xsize) | l2bit(UINT8* out, const UINT8* in, int xsize) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     for (x = 0; x < xsize; x++) |     for (x = 0; x < xsize; x++) { | ||||||
|         *out++ = (*in++ >= 128) ? 255 : 0; |         *out++ = (*in++ >= 128) ? 255 : 0; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -206,8 +207,9 @@ static void | ||||||
| la2l(UINT8* out, const UINT8* in, int xsize) | la2l(UINT8* out, const UINT8* in, int xsize) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     for (x = 0; x < xsize; x++, in += 4) |     for (x = 0; x < xsize; x++, in += 4) { | ||||||
|         *out++ = in[0]; |         *out++ = in[0]; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -240,18 +242,20 @@ static void | ||||||
| rgb2bit(UINT8* out, const UINT8* in, int xsize) | rgb2bit(UINT8* out, const UINT8* in, int xsize) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     for (x = 0; x < xsize; x++, in += 4) |     for (x = 0; x < xsize; x++, in += 4) { | ||||||
|         /* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */ |         /* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */ | ||||||
|         *out++ = (L(in) >= 128000) ? 255 : 0; |         *out++ = (L(in) >= 128000) ? 255 : 0; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| rgb2l(UINT8* out, const UINT8* in, int xsize) | rgb2l(UINT8* out, const UINT8* in, int xsize) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     for (x = 0; x < xsize; x++, in += 4) |     for (x = 0; x < xsize; x++, in += 4) { | ||||||
|         /* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */ |         /* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */ | ||||||
|         *out++ = L24(in) >> 16; |         *out++ = L24(in) >> 16; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -653,12 +657,13 @@ i2l(UINT8* out, const UINT8* in_, int xsize) | ||||||
|     for (x = 0; x < xsize; x++, out++, in_ += 4) { |     for (x = 0; x < xsize; x++, out++, in_ += 4) { | ||||||
|         INT32 v; |         INT32 v; | ||||||
|         memcpy(&v, in_, sizeof(v)); |         memcpy(&v, in_, sizeof(v)); | ||||||
|         if (v <= 0) |         if (v <= 0) { | ||||||
|             *out = 0; |             *out = 0; | ||||||
|         else if (v >= 255) |         } else if (v >= 255) { | ||||||
|             *out = 255; |             *out = 255; | ||||||
|         else |         } else { | ||||||
|             *out = (UINT8) v; |             *out = (UINT8) v; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -681,12 +686,13 @@ i2rgb(UINT8* out, const UINT8* in_, int xsize) | ||||||
|     int x; |     int x; | ||||||
|     INT32* in = (INT32*) in_; |     INT32* in = (INT32*) in_; | ||||||
|     for (x = 0; x < xsize; x++, in++, out+=4) { |     for (x = 0; x < xsize; x++, in++, out+=4) { | ||||||
|         if (*in <= 0) |         if (*in <= 0) { | ||||||
|             out[0] = out[1] = out[2] = 0; |             out[0] = out[1] = out[2] = 0; | ||||||
|         else if (*in >= 255) |         } else if (*in >= 255) { | ||||||
|             out[0] = out[1] = out[2] = 255; |             out[0] = out[1] = out[2] = 255; | ||||||
|         else |         } else { | ||||||
|             out[0] = out[1] = out[2] = (UINT8) *in; |             out[0] = out[1] = out[2] = (UINT8) *in; | ||||||
|  |         } | ||||||
|         out[3] = 255; |         out[3] = 255; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -741,12 +747,13 @@ f2l(UINT8* out, const UINT8* in_, int xsize) | ||||||
|     for (x = 0; x < xsize; x++, out++, in_ += 4) { |     for (x = 0; x < xsize; x++, out++, in_ += 4) { | ||||||
|         FLOAT32 v; |         FLOAT32 v; | ||||||
|         memcpy(&v, in_, sizeof(v)); |         memcpy(&v, in_, sizeof(v)); | ||||||
|         if (v <= 0.0) |         if (v <= 0.0) { | ||||||
|             *out = 0; |             *out = 0; | ||||||
|         else if (v >= 255.0) |         } else if (v >= 255.0) { | ||||||
|             *out = 255; |             *out = 255; | ||||||
|         else |         } else { | ||||||
|             *out = (UINT8) v; |             *out = (UINT8) v; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -797,8 +804,9 @@ static void | ||||||
| ycbcr2l(UINT8* out, const UINT8* in, int xsize) | ycbcr2l(UINT8* out, const UINT8* in, int xsize) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     for (x = 0; x < xsize; x++, in += 4) |     for (x = 0; x < xsize; x++, in += 4) { | ||||||
|         *out++ = in[0]; |         *out++ = in[0]; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -908,22 +916,26 @@ static void | ||||||
| I16L_L(UINT8* out, const UINT8* in, int xsize) | I16L_L(UINT8* out, const UINT8* in, int xsize) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     for (x = 0; x < xsize; x++, in += 2) |     for (x = 0; x < xsize; x++, in += 2) { | ||||||
|         if (in[1] != 0) |         if (in[1] != 0) { | ||||||
|             *out++ = 255; |             *out++ = 255; | ||||||
|         else |         } else { | ||||||
|             *out++ = in[0]; |             *out++ = in[0]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| I16B_L(UINT8* out, const UINT8* in, int xsize) | I16B_L(UINT8* out, const UINT8* in, int xsize) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     for (x = 0; x < xsize; x++, in += 2) |     for (x = 0; x < xsize; x++, in += 2) { | ||||||
|         if (in[0] != 0) |         if (in[0] != 0) { | ||||||
|             *out++ = 255; |             *out++ = 255; | ||||||
|         else |         } else { | ||||||
|             *out++ = in[1]; |             *out++ = in[1]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct { | static struct { | ||||||
|  | @ -1056,8 +1068,9 @@ p2bit(UINT8* out, const UINT8* in, int xsize, const UINT8* palette) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     /* FIXME: precalculate greyscale palette? */ |     /* FIXME: precalculate greyscale palette? */ | ||||||
|     for (x = 0; x < xsize; x++) |     for (x = 0; x < xsize; x++) { | ||||||
|         *out++ = (L(&palette[in[x]*4]) >= 128000) ? 255 : 0; |         *out++ = (L(&palette[in[x]*4]) >= 128000) ? 255 : 0; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -1065,8 +1078,9 @@ pa2bit(UINT8* out, const UINT8* in, int xsize, const UINT8* palette) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     /* FIXME: precalculate greyscale palette? */ |     /* FIXME: precalculate greyscale palette? */ | ||||||
|     for (x = 0; x < xsize; x++, in += 4) |     for (x = 0; x < xsize; x++, in += 4) { | ||||||
|         *out++ = (L(&palette[in[0]*4]) >= 128000) ? 255 : 0; |         *out++ = (L(&palette[in[0]*4]) >= 128000) ? 255 : 0; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -1074,8 +1088,9 @@ p2l(UINT8* out, const UINT8* in, int xsize, const UINT8* palette) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     /* FIXME: precalculate greyscale palette? */ |     /* FIXME: precalculate greyscale palette? */ | ||||||
|     for (x = 0; x < xsize; x++) |     for (x = 0; x < xsize; x++) { | ||||||
|         *out++ = L(&palette[in[x]*4]) / 1000; |         *out++ = L(&palette[in[x]*4]) / 1000; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -1083,8 +1098,9 @@ pa2l(UINT8* out, const UINT8* in, int xsize, const UINT8* palette) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     /* FIXME: precalculate greyscale palette? */ |     /* FIXME: precalculate greyscale palette? */ | ||||||
|     for (x = 0; x < xsize; x++, in += 4) |     for (x = 0; x < xsize; x++, in += 4) { | ||||||
|         *out++ = L(&palette[in[0]*4]) / 1000; |         *out++ = L(&palette[in[0]*4]) / 1000; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -1138,8 +1154,9 @@ pa2i(UINT8* out_, const UINT8* in, int xsize, const UINT8* palette) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     INT32* out = (INT32*) out_; |     INT32* out = (INT32*) out_; | ||||||
|     for (x = 0; x < xsize; x++, in += 4) |     for (x = 0; x < xsize; x++, in += 4) { | ||||||
|         *out++ = L(&palette[in[0]*4]) / 1000; |         *out++ = L(&palette[in[0]*4]) / 1000; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -1157,8 +1174,9 @@ pa2f(UINT8* out_, const UINT8* in, int xsize, const UINT8* palette) | ||||||
| { | { | ||||||
|     int x; |     int x; | ||||||
|     FLOAT32* out = (FLOAT32*) out_; |     FLOAT32* out = (FLOAT32*) out_; | ||||||
|     for (x = 0; x < xsize; x++, in += 4) |     for (x = 0; x < xsize; x++, in += 4) { | ||||||
|         *out++ = (float) L(&palette[in[0]*4]) / 1000.0F; |         *out++ = (float) L(&palette[in[0]*4]) / 1000.0F; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -1273,46 +1291,50 @@ frompalette(Imaging imOut, Imaging imIn, const char *mode) | ||||||
| 
 | 
 | ||||||
|     /* Map palette image to L, RGB, RGBA, or CMYK */ |     /* Map palette image to L, RGB, RGBA, or CMYK */ | ||||||
| 
 | 
 | ||||||
|     if (!imIn->palette) |     if (!imIn->palette) { | ||||||
|         return (Imaging) ImagingError_ValueError("no palette"); |         return (Imaging) ImagingError_ValueError("no palette"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     alpha = !strcmp(imIn->mode, "PA"); |     alpha = !strcmp(imIn->mode, "PA"); | ||||||
| 
 | 
 | ||||||
|     if (strcmp(mode, "1") == 0) |     if (strcmp(mode, "1") == 0) { | ||||||
|         convert = alpha ? pa2bit : p2bit; |         convert = alpha ? pa2bit : p2bit; | ||||||
|     else if (strcmp(mode, "L") == 0) |     } else if (strcmp(mode, "L") == 0) { | ||||||
|         convert = alpha ? pa2l : p2l; |         convert = alpha ? pa2l : p2l; | ||||||
|     else if (strcmp(mode, "LA") == 0) |     } else if (strcmp(mode, "LA") == 0) { | ||||||
|         convert = alpha ? pa2la : p2la; |         convert = alpha ? pa2la : p2la; | ||||||
|     else if (strcmp(mode, "PA") == 0) |     } else if (strcmp(mode, "PA") == 0) { | ||||||
|         convert = p2pa; |         convert = p2pa; | ||||||
|     else if (strcmp(mode, "I") == 0) |     } else if (strcmp(mode, "I") == 0) { | ||||||
|         convert = alpha ? pa2i : p2i; |         convert = alpha ? pa2i : p2i; | ||||||
|     else if (strcmp(mode, "F") == 0) |     } else if (strcmp(mode, "F") == 0) { | ||||||
|         convert = alpha ? pa2f : p2f; |         convert = alpha ? pa2f : p2f; | ||||||
|     else if (strcmp(mode, "RGB") == 0) |     } else if (strcmp(mode, "RGB") == 0) { | ||||||
|         convert = alpha ? pa2rgb : p2rgb; |         convert = alpha ? pa2rgb : p2rgb; | ||||||
|     else if (strcmp(mode, "RGBA") == 0) |     } else if (strcmp(mode, "RGBA") == 0) { | ||||||
|         convert = alpha ? pa2rgba : p2rgba; |         convert = alpha ? pa2rgba : p2rgba; | ||||||
|     else if (strcmp(mode, "RGBX") == 0) |     } else if (strcmp(mode, "RGBX") == 0) { | ||||||
|         convert = alpha ? pa2rgba : p2rgba; |         convert = alpha ? pa2rgba : p2rgba; | ||||||
|     else if (strcmp(mode, "CMYK") == 0) |     } else if (strcmp(mode, "CMYK") == 0) { | ||||||
|         convert = alpha ? pa2cmyk : p2cmyk; |         convert = alpha ? pa2cmyk : p2cmyk; | ||||||
|     else if (strcmp(mode, "YCbCr") == 0) |     } else if (strcmp(mode, "YCbCr") == 0) { | ||||||
|         convert = alpha ? pa2ycbcr : p2ycbcr; |         convert = alpha ? pa2ycbcr : p2ycbcr; | ||||||
|     else if (strcmp(mode, "HSV") == 0) |     } else if (strcmp(mode, "HSV") == 0) { | ||||||
|         convert = alpha ? pa2hsv : p2hsv; |         convert = alpha ? pa2hsv : p2hsv; | ||||||
|     else |     } else { | ||||||
|         return (Imaging) ImagingError_ValueError("conversion not supported"); |         return (Imaging) ImagingError_ValueError("conversion not supported"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNew2Dirty(mode, imOut, imIn); |     imOut = ImagingNew2Dirty(mode, imOut, imIn); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
|     for (y = 0; y < imIn->ysize; y++) |     for (y = 0; y < imIn->ysize; y++) { | ||||||
|         (*convert)((UINT8*) imOut->image[y], (UINT8*) imIn->image[y], |         (*convert)((UINT8*) imOut->image[y], (UINT8*) imIn->image[y], | ||||||
|                    imIn->xsize, imIn->palette->palette); |                    imIn->xsize, imIn->palette->palette); | ||||||
|  |     } | ||||||
|     ImagingSectionLeave(&cookie); |     ImagingSectionLeave(&cookie); | ||||||
| 
 | 
 | ||||||
|     return imOut; |     return imOut; | ||||||
|  | @ -1330,26 +1352,30 @@ topalette(Imaging imOut, Imaging imIn, const char *mode, ImagingPalette inpalett | ||||||
|     ImagingPalette palette = inpalette;; |     ImagingPalette palette = inpalette;; | ||||||
| 
 | 
 | ||||||
|     /* Map L or RGB/RGBX/RGBA to palette image */ |     /* Map L or RGB/RGBX/RGBA to palette image */ | ||||||
|     if (strcmp(imIn->mode, "L") != 0 && strncmp(imIn->mode, "RGB", 3) != 0) |     if (strcmp(imIn->mode, "L") != 0 && strncmp(imIn->mode, "RGB", 3) != 0) { | ||||||
|         return (Imaging) ImagingError_ValueError("conversion not supported"); |         return (Imaging) ImagingError_ValueError("conversion not supported"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     alpha = !strcmp(mode, "PA"); |     alpha = !strcmp(mode, "PA"); | ||||||
| 
 | 
 | ||||||
|     if (palette == NULL) { |     if (palette == NULL) { | ||||||
|       /* FIXME: make user configurable */ |       /* FIXME: make user configurable */ | ||||||
|       if (imIn->bands == 1) |       if (imIn->bands == 1) { | ||||||
|         palette = ImagingPaletteNew("RGB"); /* Initialised to grey ramp */ |         palette = ImagingPaletteNew("RGB"); /* Initialised to grey ramp */ | ||||||
|       else |       } else { | ||||||
|         palette = ImagingPaletteNewBrowser(); /* Standard colour cube */ |         palette = ImagingPaletteNewBrowser(); /* Standard colour cube */ | ||||||
|  |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!palette) |     if (!palette) { | ||||||
|         return (Imaging) ImagingError_ValueError("no palette"); |         return (Imaging) ImagingError_ValueError("no palette"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNew2Dirty(mode, imOut, imIn); |     imOut = ImagingNew2Dirty(mode, imOut, imIn); | ||||||
|     if (!imOut) { |     if (!imOut) { | ||||||
|       if (palette != inpalette) |       if (palette != inpalette) { | ||||||
|         ImagingPaletteDelete(palette); |         ImagingPaletteDelete(palette); | ||||||
|  |       } | ||||||
|       return NULL; |       return NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1376,8 +1402,9 @@ topalette(Imaging imOut, Imaging imIn, const char *mode, ImagingPalette inpalett | ||||||
|         /* Create mapping cache */ |         /* Create mapping cache */ | ||||||
|         if (ImagingPaletteCachePrepare(palette) < 0) { |         if (ImagingPaletteCachePrepare(palette) < 0) { | ||||||
|             ImagingDelete(imOut); |             ImagingDelete(imOut); | ||||||
|             if (palette != inpalette) |             if (palette != inpalette) { | ||||||
|               ImagingPaletteDelete(palette); |               ImagingPaletteDelete(palette); | ||||||
|  |             } | ||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -1415,8 +1442,9 @@ topalette(Imaging imOut, Imaging imIn, const char *mode, ImagingPalette inpalett | ||||||
| 
 | 
 | ||||||
|                     /* get closest colour */ |                     /* get closest colour */ | ||||||
|                     cache = &ImagingPaletteCache(palette, r, g, b); |                     cache = &ImagingPaletteCache(palette, r, g, b); | ||||||
|                     if (cache[0] == 0x100) |                     if (cache[0] == 0x100) { | ||||||
|                         ImagingPaletteCacheUpdate(palette, r, g, b); |                         ImagingPaletteCacheUpdate(palette, r, g, b); | ||||||
|  |                     } | ||||||
|                     if (alpha) { |                     if (alpha) { | ||||||
|                         out[x*4] = out[x*4+1] = out[x*4+2] = (UINT8) cache[0]; |                         out[x*4] = out[x*4+1] = out[x*4+2] = (UINT8) cache[0]; | ||||||
|                         out[x*4+3] = 255; |                         out[x*4+3] = 255; | ||||||
|  | @ -1464,8 +1492,9 @@ topalette(Imaging imOut, Imaging imIn, const char *mode, ImagingPalette inpalett | ||||||
| 
 | 
 | ||||||
|                     /* get closest colour */ |                     /* get closest colour */ | ||||||
|                     cache = &ImagingPaletteCache(palette, r, g, b); |                     cache = &ImagingPaletteCache(palette, r, g, b); | ||||||
|                     if (cache[0] == 0x100) |                     if (cache[0] == 0x100) { | ||||||
|                         ImagingPaletteCacheUpdate(palette, r, g, b); |                         ImagingPaletteCacheUpdate(palette, r, g, b); | ||||||
|  |                     } | ||||||
|                     if (alpha) { |                     if (alpha) { | ||||||
|                         out[x*4] = out[x*4+1] = out[x*4+2] = (UINT8) cache[0]; |                         out[x*4] = out[x*4+1] = out[x*4+2] = (UINT8) cache[0]; | ||||||
|                         out[x*4+3] = 255; |                         out[x*4+3] = 255; | ||||||
|  | @ -1477,12 +1506,14 @@ topalette(Imaging imOut, Imaging imIn, const char *mode, ImagingPalette inpalett | ||||||
|             ImagingSectionLeave(&cookie); |             ImagingSectionLeave(&cookie); | ||||||
| 
 | 
 | ||||||
|         } |         } | ||||||
|         if (inpalette != palette) |         if (inpalette != palette) { | ||||||
|           ImagingPaletteCacheDelete(palette); |           ImagingPaletteCacheDelete(palette); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (inpalette != palette) |     if (inpalette != palette) { | ||||||
|       ImagingPaletteDelete(palette); |       ImagingPaletteDelete(palette); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return imOut; |     return imOut; | ||||||
| } | } | ||||||
|  | @ -1495,12 +1526,14 @@ tobilevel(Imaging imOut, Imaging imIn, int dither) | ||||||
|     int* errors; |     int* errors; | ||||||
| 
 | 
 | ||||||
|     /* Map L or RGB to dithered 1 image */ |     /* Map L or RGB to dithered 1 image */ | ||||||
|     if (strcmp(imIn->mode, "L") != 0 && strcmp(imIn->mode, "RGB") != 0) |     if (strcmp(imIn->mode, "L") != 0 && strcmp(imIn->mode, "RGB") != 0) { | ||||||
|         return (Imaging) ImagingError_ValueError("conversion not supported"); |         return (Imaging) ImagingError_ValueError("conversion not supported"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNew2Dirty("1", imOut, imIn); |     imOut = ImagingNew2Dirty("1", imOut, imIn); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     errors = calloc(imIn->xsize + 1, sizeof(int)); |     errors = calloc(imIn->xsize + 1, sizeof(int)); | ||||||
|     if (!errors) { |     if (!errors) { | ||||||
|  | @ -1582,63 +1615,72 @@ convert(Imaging imOut, Imaging imIn, const char *mode, | ||||||
|     ImagingShuffler convert; |     ImagingShuffler convert; | ||||||
|     int y; |     int y; | ||||||
| 
 | 
 | ||||||
|     if (!imIn) |     if (!imIn) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!mode) { |     if (!mode) { | ||||||
|         /* Map palette image to full depth */ |         /* Map palette image to full depth */ | ||||||
|         if (!imIn->palette) |         if (!imIn->palette) { | ||||||
|             return (Imaging) ImagingError_ModeError(); |             return (Imaging) ImagingError_ModeError(); | ||||||
|  |         } | ||||||
|         mode = imIn->palette->mode; |         mode = imIn->palette->mode; | ||||||
|     } else |     } else { | ||||||
|         /* Same mode? */ |         /* Same mode? */ | ||||||
|         if (!strcmp(imIn->mode, mode)) |         if (!strcmp(imIn->mode, mode)) { | ||||||
|             return ImagingCopy2(imOut, imIn); |             return ImagingCopy2(imOut, imIn); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     /* test for special conversions */ |     /* test for special conversions */ | ||||||
| 
 | 
 | ||||||
|     if (strcmp(imIn->mode, "P") == 0 || strcmp(imIn->mode, "PA") == 0) |     if (strcmp(imIn->mode, "P") == 0 || strcmp(imIn->mode, "PA") == 0) { | ||||||
|         return frompalette(imOut, imIn, mode); |         return frompalette(imOut, imIn, mode); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (strcmp(mode, "P") == 0 || strcmp(mode, "PA") == 0) |     if (strcmp(mode, "P") == 0 || strcmp(mode, "PA") == 0) { | ||||||
|         return topalette(imOut, imIn, mode, palette, dither); |         return topalette(imOut, imIn, mode, palette, dither); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (dither && strcmp(mode, "1") == 0) |     if (dither && strcmp(mode, "1") == 0) { | ||||||
|         return tobilevel(imOut, imIn, dither); |         return tobilevel(imOut, imIn, dither); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     /* standard conversion machinery */ |     /* standard conversion machinery */ | ||||||
| 
 | 
 | ||||||
|     convert = NULL; |     convert = NULL; | ||||||
| 
 | 
 | ||||||
|     for (y = 0; converters[y].from; y++) |     for (y = 0; converters[y].from; y++) { | ||||||
|         if (!strcmp(imIn->mode, converters[y].from) && |         if (!strcmp(imIn->mode, converters[y].from) && | ||||||
|             !strcmp(mode, converters[y].to)) { |             !strcmp(mode, converters[y].to)) { | ||||||
|             convert = converters[y].convert; |             convert = converters[y].convert; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!convert) |     if (!convert) { | ||||||
| #ifdef notdef | #ifdef notdef | ||||||
|         return (Imaging) ImagingError_ValueError("conversion not supported"); |         return (Imaging) ImagingError_ValueError("conversion not supported"); | ||||||
| #else | #else | ||||||
|     { |         static char buf[256]; | ||||||
|       static char buf[256]; |         /* FIXME: may overflow if mode is too large */ | ||||||
|       /* FIXME: may overflow if mode is too large */ |         sprintf(buf, "conversion from %s to %s not supported", imIn->mode, mode); | ||||||
|       sprintf(buf, "conversion from %s to %s not supported", imIn->mode, mode); |         return (Imaging) ImagingError_ValueError(buf); | ||||||
|       return (Imaging) ImagingError_ValueError(buf); |  | ||||||
|     } |  | ||||||
| #endif | #endif | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNew2Dirty(mode, imOut, imIn); |     imOut = ImagingNew2Dirty(mode, imOut, imIn); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
|     for (y = 0; y < imIn->ysize; y++) |     for (y = 0; y < imIn->ysize; y++) { | ||||||
|         (*convert)((UINT8*) imOut->image[y], (UINT8*) imIn->image[y], |         (*convert)((UINT8*) imOut->image[y], (UINT8*) imIn->image[y], | ||||||
|                    imIn->xsize); |                    imIn->xsize); | ||||||
|  |     } | ||||||
|     ImagingSectionLeave(&cookie); |     ImagingSectionLeave(&cookie); | ||||||
| 
 | 
 | ||||||
|     return imOut; |     return imOut; | ||||||
|  | @ -1727,17 +1769,19 @@ ImagingConvertInPlace(Imaging imIn, const char* mode) | ||||||
|     int y; |     int y; | ||||||
| 
 | 
 | ||||||
|     /* limited support for inplace conversion */ |     /* limited support for inplace conversion */ | ||||||
|     if (strcmp(imIn->mode, "L") == 0 && strcmp(mode, "1") == 0) |     if (strcmp(imIn->mode, "L") == 0 && strcmp(mode, "1") == 0) { | ||||||
|         convert = l2bit; |         convert = l2bit; | ||||||
|     else if (strcmp(imIn->mode, "1") == 0 && strcmp(mode, "L") == 0) |     } else if (strcmp(imIn->mode, "1") == 0 && strcmp(mode, "L") == 0) { | ||||||
|         convert = bit2l; |         convert = bit2l; | ||||||
|     else |     } else { | ||||||
|         return ImagingError_ModeError(); |         return ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
|     for (y = 0; y < imIn->ysize; y++) |     for (y = 0; y < imIn->ysize; y++) { | ||||||
|         (*convert)((UINT8*) imIn->image[y], (UINT8*) imIn->image[y], |         (*convert)((UINT8*) imIn->image[y], (UINT8*) imIn->image[y], | ||||||
|                    imIn->xsize); |                    imIn->xsize); | ||||||
|  |     } | ||||||
|     ImagingSectionLeave(&cookie); |     ImagingSectionLeave(&cookie); | ||||||
| 
 | 
 | ||||||
|     return imIn; |     return imIn; | ||||||
|  |  | ||||||
|  | @ -25,21 +25,25 @@ _copy(Imaging imOut, Imaging imIn) | ||||||
|     ImagingSectionCookie cookie; |     ImagingSectionCookie cookie; | ||||||
|     int y; |     int y; | ||||||
| 
 | 
 | ||||||
|     if (!imIn) |     if (!imIn) { | ||||||
|         return (Imaging) ImagingError_ValueError(NULL); |         return (Imaging) ImagingError_ValueError(NULL); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNew2Dirty(imIn->mode, imOut, imIn); |     imOut = ImagingNew2Dirty(imIn->mode, imOut, imIn); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, imIn); |     ImagingCopyPalette(imOut, imIn); | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
|     if (imIn->block != NULL && imOut->block != NULL) |     if (imIn->block != NULL && imOut->block != NULL) { | ||||||
|         memcpy(imOut->block, imIn->block, imIn->ysize * imIn->linesize); |         memcpy(imOut->block, imIn->block, imIn->ysize * imIn->linesize); | ||||||
|     else |     } else { | ||||||
|         for (y = 0; y < imIn->ysize; y++) |         for (y = 0; y < imIn->ysize; y++) { | ||||||
|             memcpy(imOut->image[y], imIn->image[y], imIn->linesize); |             memcpy(imOut->image[y], imIn->image[y], imIn->linesize); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|     ImagingSectionLeave(&cookie); |     ImagingSectionLeave(&cookie); | ||||||
| 
 | 
 | ||||||
|     return imOut; |     return imOut; | ||||||
|  |  | ||||||
|  | @ -27,24 +27,29 @@ ImagingCrop(Imaging imIn, int sx0, int sy0, int sx1, int sy1) | ||||||
|     int dx0, dy0, dx1, dy1; |     int dx0, dy0, dx1, dy1; | ||||||
|     INT32 zero = 0; |     INT32 zero = 0; | ||||||
| 
 | 
 | ||||||
|     if (!imIn) |     if (!imIn) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     xsize = sx1 - sx0; |     xsize = sx1 - sx0; | ||||||
|     if (xsize < 0) |     if (xsize < 0) { | ||||||
|         xsize = 0; |         xsize = 0; | ||||||
|  |     } | ||||||
|     ysize = sy1 - sy0; |     ysize = sy1 - sy0; | ||||||
|     if (ysize < 0) |     if (ysize < 0) { | ||||||
|         ysize = 0; |         ysize = 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty(imIn->mode, xsize, ysize); |     imOut = ImagingNewDirty(imIn->mode, xsize, ysize); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, imIn); |     ImagingCopyPalette(imOut, imIn); | ||||||
| 
 | 
 | ||||||
|     if (sx0 < 0 || sy0 < 0 || sx1 > imIn->xsize || sy1 > imIn->ysize) |     if (sx0 < 0 || sy0 < 0 || sx1 > imIn->xsize || sy1 > imIn->ysize) { | ||||||
|         (void) ImagingFill(imOut, &zero); |         (void) ImagingFill(imOut, &zero); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     dx0 = -sx0; |     dx0 = -sx0; | ||||||
|     dy0 = -sy0; |     dy0 = -sy0; | ||||||
|  |  | ||||||
|  | @ -40,8 +40,9 @@ ImagingGetModeDIB(int size_out[2]) | ||||||
|     mode = "P"; |     mode = "P"; | ||||||
|     if (!(GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE)) { |     if (!(GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE)) { | ||||||
|         mode = "RGB"; |         mode = "RGB"; | ||||||
|         if (GetDeviceCaps(dc, BITSPIXEL) == 1) |         if (GetDeviceCaps(dc, BITSPIXEL) == 1) { | ||||||
|             mode = "1"; |             mode = "1"; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (size_out) { |     if (size_out) { | ||||||
|  | @ -66,14 +67,16 @@ ImagingNewDIB(const char *mode, int xsize, int ysize) | ||||||
| 
 | 
 | ||||||
|     /* Check mode */ |     /* Check mode */ | ||||||
|     if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 && |     if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 && | ||||||
|         strcmp(mode, "RGB") != 0) |         strcmp(mode, "RGB") != 0) { | ||||||
|         return (ImagingDIB) ImagingError_ModeError(); |         return (ImagingDIB) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Create DIB context and info header */ |     /* Create DIB context and info header */ | ||||||
|     /* malloc check ok, small constant allocation */ |     /* malloc check ok, small constant allocation */ | ||||||
|     dib = (ImagingDIB) malloc(sizeof(*dib)); |     dib = (ImagingDIB) malloc(sizeof(*dib)); | ||||||
|     if (!dib) |     if (!dib) { | ||||||
|         return (ImagingDIB) ImagingError_MemoryError(); |         return (ImagingDIB) ImagingError_MemoryError(); | ||||||
|  |     } | ||||||
|     /* malloc check ok, small constant allocation */ |     /* malloc check ok, small constant allocation */ | ||||||
|     dib->info = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) + |     dib->info = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) + | ||||||
|                                      256 * sizeof(RGBQUAD)); |                                      256 * sizeof(RGBQUAD)); | ||||||
|  | @ -113,9 +116,9 @@ ImagingNewDIB(const char *mode, int xsize, int ysize) | ||||||
|     dib->pixelsize = strlen(mode); |     dib->pixelsize = strlen(mode); | ||||||
|     dib->linesize = (xsize * dib->pixelsize + 3) & -4; |     dib->linesize = (xsize * dib->pixelsize + 3) & -4; | ||||||
| 
 | 
 | ||||||
|     if (dib->pixelsize == 1) |     if (dib->pixelsize == 1) { | ||||||
|         dib->pack = dib->unpack = (ImagingShuffler) memcpy; |         dib->pack = dib->unpack = (ImagingShuffler) memcpy; | ||||||
|     else { |     } else { | ||||||
|         dib->pack = ImagingPackBGR; |         dib->pack = ImagingPackBGR; | ||||||
|         dib->unpack = ImagingPackBGR; |         dib->unpack = ImagingPackBGR; | ||||||
|     } |     } | ||||||
|  | @ -174,14 +177,16 @@ ImagingNewDIB(const char *mode, int xsize, int ysize) | ||||||
|              * images. */ |              * images. */ | ||||||
| 
 | 
 | ||||||
|             i = 10; |             i = 10; | ||||||
|             for (r = 0; r < 256; r += 51) |             for (r = 0; r < 256; r += 51) { | ||||||
|                 for (g = 0; g < 256; g += 51) |                 for (g = 0; g < 256; g += 51) { | ||||||
|                     for (b = 0; b < 256; b += 51) { |                     for (b = 0; b < 256; b += 51) { | ||||||
|                         pal->palPalEntry[i].peRed = r; |                         pal->palPalEntry[i].peRed = r; | ||||||
|                         pal->palPalEntry[i].peGreen = g; |                         pal->palPalEntry[i].peGreen = g; | ||||||
|                         pal->palPalEntry[i].peBlue = b; |                         pal->palPalEntry[i].peBlue = b; | ||||||
|                         i++; |                         i++; | ||||||
|                     } |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|             for (r = 1; r < 22-1; r++) { |             for (r = 1; r < 22-1; r++) { | ||||||
|                 /* Black and white are already provided by the cube. */ |                 /* Black and white are already provided by the cube. */ | ||||||
|                 pal->palPalEntry[i].peRed = |                 pal->palPalEntry[i].peRed = | ||||||
|  | @ -195,14 +200,16 @@ ImagingNewDIB(const char *mode, int xsize, int ysize) | ||||||
|             /* Colour DIB.  Alternate palette. */ |             /* Colour DIB.  Alternate palette. */ | ||||||
| 
 | 
 | ||||||
|             i = 10; |             i = 10; | ||||||
|             for (r = 0; r < 256; r += 37) |             for (r = 0; r < 256; r += 37) { | ||||||
|                 for (g = 0; g < 256; g += 32) |                 for (g = 0; g < 256; g += 32) { | ||||||
|                     for (b = 0; b < 256; b += 64) { |                     for (b = 0; b < 256; b += 64) { | ||||||
|                         pal->palPalEntry[i].peRed = r; |                         pal->palPalEntry[i].peRed = r; | ||||||
|                         pal->palPalEntry[i].peGreen = g; |                         pal->palPalEntry[i].peGreen = g; | ||||||
|                         pal->palPalEntry[i].peBlue = b; |                         pal->palPalEntry[i].peBlue = b; | ||||||
|                         i++; |                         i++; | ||||||
|                     } |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | @ -223,9 +230,10 @@ ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4]) | ||||||
|     /* FIXME: check size! */ |     /* FIXME: check size! */ | ||||||
| 
 | 
 | ||||||
|     int y; |     int y; | ||||||
|     for (y = 0; y < im->ysize; y++) |     for (y = 0; y < im->ysize; y++) { | ||||||
|         dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) + |         dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) + | ||||||
|                   xy[0]*dib->pixelsize, im->image[y], im->xsize); |                   xy[0]*dib->pixelsize, im->image[y], im->xsize); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -234,8 +242,9 @@ ImagingExposeDIB(ImagingDIB dib, void *dc) | ||||||
| { | { | ||||||
|     /* Copy bitmap to display */ |     /* Copy bitmap to display */ | ||||||
| 
 | 
 | ||||||
|     if (dib->palette != 0) |     if (dib->palette != 0) { | ||||||
|         SelectPalette((HDC) dc, dib->palette, FALSE); |         SelectPalette((HDC) dc, dib->palette, FALSE); | ||||||
|  |     } | ||||||
|     BitBlt((HDC) dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY); |     BitBlt((HDC) dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -251,8 +260,9 @@ ImagingDrawDIB(ImagingDIB dib, void *dc, int dst[4], int src[4]) | ||||||
|                       dib->info, DIB_RGB_COLORS, SRCCOPY); |                       dib->info, DIB_RGB_COLORS, SRCCOPY); | ||||||
|     } else { |     } else { | ||||||
|         /* stretchblt (displays) */ |         /* stretchblt (displays) */ | ||||||
|         if (dib->palette != 0) |         if (dib->palette != 0) { | ||||||
|             SelectPalette((HDC) dc, dib->palette, FALSE); |             SelectPalette((HDC) dc, dib->palette, FALSE); | ||||||
|  |         } | ||||||
|         StretchBlt((HDC) dc, dst[0], dst[1], dst[2]-dst[0], dst[3]-dst[1], |         StretchBlt((HDC) dc, dst[0], dst[1], dst[2]-dst[0], dst[3]-dst[1], | ||||||
|                    dib->dc, src[0], src[1], src[2]-src[0], src[3]-src[1], |                    dib->dc, src[0], src[1], src[2]-src[0], src[3]-src[1], | ||||||
|                    SRCCOPY); |                    SRCCOPY); | ||||||
|  | @ -275,8 +285,9 @@ ImagingQueryPaletteDIB(ImagingDIB dib, void *dc) | ||||||
|         /* Restore palette */ |         /* Restore palette */ | ||||||
|         SelectPalette((HDC) dc, now, FALSE); |         SelectPalette((HDC) dc, now, FALSE); | ||||||
| 
 | 
 | ||||||
|     } else |     } else { | ||||||
|         n = 0; |         n = 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return n; /* number of colours that was changed */ |     return n; /* number of colours that was changed */ | ||||||
| } | } | ||||||
|  | @ -286,14 +297,16 @@ ImagingDeleteDIB(ImagingDIB dib) | ||||||
| { | { | ||||||
|     /* Clean up */ |     /* Clean up */ | ||||||
| 
 | 
 | ||||||
|     if (dib->palette) |     if (dib->palette) { | ||||||
|         DeleteObject(dib->palette); |         DeleteObject(dib->palette); | ||||||
|  |     } | ||||||
|     if (dib->bitmap) { |     if (dib->bitmap) { | ||||||
|         SelectObject(dib->dc, dib->old_bitmap); |         SelectObject(dib->dc, dib->old_bitmap); | ||||||
|         DeleteObject(dib->bitmap); |         DeleteObject(dib->bitmap); | ||||||
|     } |     } | ||||||
|     if (dib->dc) |     if (dib->dc) { | ||||||
|         DeleteDC(dib->dc); |         DeleteDC(dib->dc); | ||||||
|  |     } | ||||||
|     free(dib->info); |     free(dib->info); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -79,8 +79,9 @@ point8(Imaging im, int x, int y, int ink) | ||||||
| static inline void | static inline void | ||||||
| point32(Imaging im, int x, int y, int ink) | point32(Imaging im, int x, int y, int ink) | ||||||
| { | { | ||||||
|     if (x >= 0 && x < im->xsize && y >= 0 && y < im->ysize) |     if (x >= 0 && x < im->xsize && y >= 0 && y < im->ysize) { | ||||||
|         im->image32[y][x] = ink; |         im->image32[y][x] = ink; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void | static inline void | ||||||
|  | @ -103,16 +104,19 @@ hline8(Imaging im, int x0, int y0, int x1, int ink) | ||||||
|     int tmp, pixelwidth; |     int tmp, pixelwidth; | ||||||
| 
 | 
 | ||||||
|     if (y0 >= 0 && y0 < im->ysize) { |     if (y0 >= 0 && y0 < im->ysize) { | ||||||
|         if (x0 > x1) |         if (x0 > x1) { | ||||||
|             tmp = x0, x0 = x1, x1 = tmp; |             tmp = x0, x0 = x1, x1 = tmp; | ||||||
|         if (x0 < 0) |         } | ||||||
|  |         if (x0 < 0) { | ||||||
|             x0 = 0; |             x0 = 0; | ||||||
|         else if (x0 >= im->xsize) |         } else if (x0 >= im->xsize) { | ||||||
|             return; |             return; | ||||||
|         if (x1 < 0) |         } | ||||||
|  |         if (x1 < 0) { | ||||||
|             return; |             return; | ||||||
|         else if (x1 >= im->xsize) |         } else if (x1 >= im->xsize) { | ||||||
|             x1 = im->xsize-1; |             x1 = im->xsize-1; | ||||||
|  |         } | ||||||
|         if (x0 <= x1) { |         if (x0 <= x1) { | ||||||
|             pixelwidth = strncmp(im->mode, "I;16", 4) == 0 ? 2 : 1; |             pixelwidth = strncmp(im->mode, "I;16", 4) == 0 ? 2 : 1; | ||||||
|             memset(im->image8[y0] + x0 * pixelwidth, (UINT8) ink, |             memset(im->image8[y0] + x0 * pixelwidth, (UINT8) ink, | ||||||
|  | @ -128,19 +132,23 @@ hline32(Imaging im, int x0, int y0, int x1, int ink) | ||||||
|     INT32* p; |     INT32* p; | ||||||
| 
 | 
 | ||||||
|     if (y0 >= 0 && y0 < im->ysize) { |     if (y0 >= 0 && y0 < im->ysize) { | ||||||
|         if (x0 > x1) |         if (x0 > x1) { | ||||||
|             tmp = x0, x0 = x1, x1 = tmp; |             tmp = x0, x0 = x1, x1 = tmp; | ||||||
|         if (x0 < 0) |         } | ||||||
|  |         if (x0 < 0) { | ||||||
|             x0 = 0; |             x0 = 0; | ||||||
|         else if (x0 >= im->xsize) |         } else if (x0 >= im->xsize) { | ||||||
|             return; |             return; | ||||||
|         if (x1 < 0) |         } | ||||||
|  |         if (x1 < 0) { | ||||||
|             return; |             return; | ||||||
|         else if (x1 >= im->xsize) |         } else if (x1 >= im->xsize) { | ||||||
|             x1 = im->xsize-1; |             x1 = im->xsize-1; | ||||||
|  |         } | ||||||
|         p = im->image32[y0]; |         p = im->image32[y0]; | ||||||
|         while (x0 <= x1) |         while (x0 <= x1) { | ||||||
|             p[x0++] = ink; |             p[x0++] = ink; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -151,16 +159,19 @@ hline32rgba(Imaging im, int x0, int y0, int x1, int ink) | ||||||
|     unsigned int tmp1; |     unsigned int tmp1; | ||||||
| 
 | 
 | ||||||
|     if (y0 >= 0 && y0 < im->ysize) { |     if (y0 >= 0 && y0 < im->ysize) { | ||||||
|         if (x0 > x1) |         if (x0 > x1) { | ||||||
|             tmp = x0, x0 = x1, x1 = tmp; |             tmp = x0, x0 = x1, x1 = tmp; | ||||||
|         if (x0 < 0) |         } | ||||||
|  |         if (x0 < 0) { | ||||||
|             x0 = 0; |             x0 = 0; | ||||||
|         else if (x0 >= im->xsize) |         } else if (x0 >= im->xsize) { | ||||||
|             return; |             return; | ||||||
|         if (x1 < 0) |         } | ||||||
|  |         if (x1 < 0) { | ||||||
|             return; |             return; | ||||||
|         else if (x1 >= im->xsize) |         } else if (x1 >= im->xsize) { | ||||||
|             x1 = im->xsize-1; |             x1 = im->xsize-1; | ||||||
|  |         } | ||||||
|         if (x0 <= x1) { |         if (x0 <= x1) { | ||||||
|             UINT8* out = (UINT8*) im->image[y0]+x0*4; |             UINT8* out = (UINT8*) im->image[y0]+x0*4; | ||||||
|             UINT8* in = (UINT8*) &ink; |             UINT8* in = (UINT8*) &ink; | ||||||
|  | @ -183,19 +194,21 @@ line8(Imaging im, int x0, int y0, int x1, int y1, int ink) | ||||||
| 
 | 
 | ||||||
|     /* normalize coordinates */ |     /* normalize coordinates */ | ||||||
|     dx = x1-x0; |     dx = x1-x0; | ||||||
|     if (dx < 0) |     if (dx < 0) { | ||||||
|         dx = -dx, xs = -1; |         dx = -dx, xs = -1; | ||||||
|     else |     } else { | ||||||
|         xs = 1; |         xs = 1; | ||||||
|  |     } | ||||||
|     dy = y1-y0; |     dy = y1-y0; | ||||||
|     if (dy < 0) |     if (dy < 0) { | ||||||
|         dy = -dy, ys = -1; |         dy = -dy, ys = -1; | ||||||
|     else |     } else { | ||||||
|         ys = 1; |         ys = 1; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     n = (dx > dy) ? dx : dy; |     n = (dx > dy) ? dx : dy; | ||||||
| 
 | 
 | ||||||
|     if (dx == 0) |     if (dx == 0) { | ||||||
| 
 | 
 | ||||||
|         /* vertical */ |         /* vertical */ | ||||||
|         for (i = 0; i < dy; i++) { |         for (i = 0; i < dy; i++) { | ||||||
|  | @ -203,7 +216,7 @@ line8(Imaging im, int x0, int y0, int x1, int y1, int ink) | ||||||
|             y0 += ys; |             y0 += ys; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     else if (dy == 0) |     } else if (dy == 0) { | ||||||
| 
 | 
 | ||||||
|         /* horizontal */ |         /* horizontal */ | ||||||
|         for (i = 0; i < dx; i++) { |         for (i = 0; i < dx; i++) { | ||||||
|  | @ -211,7 +224,7 @@ line8(Imaging im, int x0, int y0, int x1, int y1, int ink) | ||||||
|             x0 += xs; |             x0 += xs; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     else if (dx > dy) { |     } else if (dx > dy) { | ||||||
| 
 | 
 | ||||||
|         /* bresenham, horizontal slope */ |         /* bresenham, horizontal slope */ | ||||||
|         n = dx; |         n = dx; | ||||||
|  | @ -259,19 +272,21 @@ line32(Imaging im, int x0, int y0, int x1, int y1, int ink) | ||||||
| 
 | 
 | ||||||
|     /* normalize coordinates */ |     /* normalize coordinates */ | ||||||
|     dx = x1-x0; |     dx = x1-x0; | ||||||
|     if (dx < 0) |     if (dx < 0) { | ||||||
|         dx = -dx, xs = -1; |         dx = -dx, xs = -1; | ||||||
|     else |     } else { | ||||||
|         xs = 1; |         xs = 1; | ||||||
|  |     } | ||||||
|     dy = y1-y0; |     dy = y1-y0; | ||||||
|     if (dy < 0) |     if (dy < 0) { | ||||||
|         dy = -dy, ys = -1; |         dy = -dy, ys = -1; | ||||||
|     else |     } else { | ||||||
|         ys = 1; |         ys = 1; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     n = (dx > dy) ? dx : dy; |     n = (dx > dy) ? dx : dy; | ||||||
| 
 | 
 | ||||||
|     if (dx == 0) |     if (dx == 0) { | ||||||
| 
 | 
 | ||||||
|         /* vertical */ |         /* vertical */ | ||||||
|         for (i = 0; i < dy; i++) { |         for (i = 0; i < dy; i++) { | ||||||
|  | @ -279,7 +294,7 @@ line32(Imaging im, int x0, int y0, int x1, int y1, int ink) | ||||||
|             y0 += ys; |             y0 += ys; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     else if (dy == 0) |     } else if (dy == 0) { | ||||||
| 
 | 
 | ||||||
|         /* horizontal */ |         /* horizontal */ | ||||||
|         for (i = 0; i < dx; i++) { |         for (i = 0; i < dx; i++) { | ||||||
|  | @ -287,7 +302,7 @@ line32(Imaging im, int x0, int y0, int x1, int y1, int ink) | ||||||
|             x0 += xs; |             x0 += xs; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     else if (dx > dy) { |     } else if (dx > dy) { | ||||||
| 
 | 
 | ||||||
|         /* bresenham, horizontal slope */ |         /* bresenham, horizontal slope */ | ||||||
|         n = dx; |         n = dx; | ||||||
|  | @ -335,19 +350,21 @@ line32rgba(Imaging im, int x0, int y0, int x1, int y1, int ink) | ||||||
| 
 | 
 | ||||||
|     /* normalize coordinates */ |     /* normalize coordinates */ | ||||||
|     dx = x1-x0; |     dx = x1-x0; | ||||||
|     if (dx < 0) |     if (dx < 0) { | ||||||
|         dx = -dx, xs = -1; |         dx = -dx, xs = -1; | ||||||
|     else |     } else { | ||||||
|         xs = 1; |         xs = 1; | ||||||
|  |     } | ||||||
|     dy = y1-y0; |     dy = y1-y0; | ||||||
|     if (dy < 0) |     if (dy < 0) { | ||||||
|         dy = -dy, ys = -1; |         dy = -dy, ys = -1; | ||||||
|     else |     } else { | ||||||
|         ys = 1; |         ys = 1; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     n = (dx > dy) ? dx : dy; |     n = (dx > dy) ? dx : dy; | ||||||
| 
 | 
 | ||||||
|     if (dx == 0) |     if (dx == 0) { | ||||||
| 
 | 
 | ||||||
|         /* vertical */ |         /* vertical */ | ||||||
|         for (i = 0; i < dy; i++) { |         for (i = 0; i < dy; i++) { | ||||||
|  | @ -355,7 +372,7 @@ line32rgba(Imaging im, int x0, int y0, int x1, int y1, int ink) | ||||||
|             y0 += ys; |             y0 += ys; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     else if (dy == 0) |     } else if (dy == 0) { | ||||||
| 
 | 
 | ||||||
|         /* horizontal */ |         /* horizontal */ | ||||||
|         for (i = 0; i < dx; i++) { |         for (i = 0; i < dx; i++) { | ||||||
|  | @ -363,7 +380,7 @@ line32rgba(Imaging im, int x0, int y0, int x1, int y1, int ink) | ||||||
|             x0 += xs; |             x0 += xs; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     else if (dx > dy) { |     } else if (dx > dy) { | ||||||
| 
 | 
 | ||||||
|         /* bresenham, horizontal slope */ |         /* bresenham, horizontal slope */ | ||||||
|         n = dx; |         n = dx; | ||||||
|  | @ -406,12 +423,13 @@ static int | ||||||
| x_cmp(const void *x0, const void *x1) | x_cmp(const void *x0, const void *x1) | ||||||
| { | { | ||||||
|     float diff = *((float*)x0) - *((float*)x1); |     float diff = *((float*)x0) - *((float*)x1); | ||||||
|     if (diff < 0) |     if (diff < 0) { | ||||||
|         return -1; |         return -1; | ||||||
|     else if (diff > 0) |     } else if (diff > 0) { | ||||||
|         return 1; |         return 1; | ||||||
|     else |     } else { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -566,25 +584,28 @@ add_edge(Edge *e, int x0, int y0, int x1, int y1) | ||||||
| { | { | ||||||
|     /* printf("edge %d %d %d %d\n", x0, y0, x1, y1); */ |     /* printf("edge %d %d %d %d\n", x0, y0, x1, y1); */ | ||||||
| 
 | 
 | ||||||
|     if (x0 <= x1) |     if (x0 <= x1) { | ||||||
|         e->xmin = x0, e->xmax = x1; |         e->xmin = x0, e->xmax = x1; | ||||||
|     else |     } else { | ||||||
|         e->xmin = x1, e->xmax = x0; |         e->xmin = x1, e->xmax = x0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (y0 <= y1) |     if (y0 <= y1) { | ||||||
|         e->ymin = y0, e->ymax = y1; |         e->ymin = y0, e->ymax = y1; | ||||||
|     else |     } else { | ||||||
|         e->ymin = y1, e->ymax = y0; |         e->ymin = y1, e->ymax = y0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (y0 == y1) { |     if (y0 == y1) { | ||||||
|         e->d = 0; |         e->d = 0; | ||||||
|         e->dx = 0.0; |         e->dx = 0.0; | ||||||
|     } else { |     } else { | ||||||
|         e->dx = ((float)(x1-x0)) / (y1-y0); |         e->dx = ((float)(x1-x0)) / (y1-y0); | ||||||
|         if (y0 == e->ymin) |         if (y0 == e->ymin) { | ||||||
|             e->d = 1; |             e->d = 1; | ||||||
|         else |         } else { | ||||||
|             e->d = -1; |             e->d = -1; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     e->x0 = x0; |     e->x0 = x0; | ||||||
|  | @ -701,23 +722,27 @@ ImagingDrawRectangle(Imaging im, int x0, int y0, int x1, int y1, | ||||||
| 
 | 
 | ||||||
|     DRAWINIT(); |     DRAWINIT(); | ||||||
| 
 | 
 | ||||||
|     if (y0 > y1) |     if (y0 > y1) { | ||||||
|         tmp = y0, y0 = y1, y1 = tmp; |         tmp = y0, y0 = y1, y1 = tmp; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (fill) { |     if (fill) { | ||||||
| 
 | 
 | ||||||
|         if (y0 < 0) |         if (y0 < 0) { | ||||||
|             y0 = 0; |             y0 = 0; | ||||||
|         else if (y0 >= im->ysize) |         } else if (y0 >= im->ysize) { | ||||||
|             return 0; |             return 0; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (y1 < 0) |         if (y1 < 0) { | ||||||
|             return 0; |             return 0; | ||||||
|         else if (y1 > im->ysize) |         } else if (y1 > im->ysize) { | ||||||
|             y1 = im->ysize; |             y1 = im->ysize; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         for (y = y0; y <= y1; y++) |         for (y = y0; y <= y1; y++) { | ||||||
|             draw->hline(im, x0, y, x1, ink); |             draw->hline(im, x0, y, x1, ink); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } else { |     } else { | ||||||
|         /* outline */ |         /* outline */ | ||||||
|  | @ -743,8 +768,9 @@ ImagingDrawPolygon(Imaging im, int count, int* xy, const void* ink_, | ||||||
|     DRAW* draw; |     DRAW* draw; | ||||||
|     INT32 ink; |     INT32 ink; | ||||||
| 
 | 
 | ||||||
|     if (count <= 0) |     if (count <= 0) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     DRAWINIT(); |     DRAWINIT(); | ||||||
| 
 | 
 | ||||||
|  | @ -757,18 +783,21 @@ ImagingDrawPolygon(Imaging im, int count, int* xy, const void* ink_, | ||||||
|             (void) ImagingError_MemoryError(); |             (void) ImagingError_MemoryError(); | ||||||
|             return -1; |             return -1; | ||||||
|         } |         } | ||||||
|         for (i = n = 0; i < count-1; i++) |         for (i = n = 0; i < count-1; i++) { | ||||||
|             add_edge(&e[n++], xy[i+i], xy[i+i+1], xy[i+i+2], xy[i+i+3]); |             add_edge(&e[n++], xy[i+i], xy[i+i+1], xy[i+i+2], xy[i+i+3]); | ||||||
|         if (xy[i+i] != xy[0] || xy[i+i+1] != xy[1]) |         } | ||||||
|  |         if (xy[i+i] != xy[0] || xy[i+i+1] != xy[1]) { | ||||||
|             add_edge(&e[n++], xy[i+i], xy[i+i+1], xy[0], xy[1]); |             add_edge(&e[n++], xy[i+i], xy[i+i+1], xy[0], xy[1]); | ||||||
|  |         } | ||||||
|         draw->polygon(im, n, e, ink, 0); |         draw->polygon(im, n, e, ink, 0); | ||||||
|         free(e); |         free(e); | ||||||
| 
 | 
 | ||||||
|     } else { |     } else { | ||||||
| 
 | 
 | ||||||
|         /* Outline */ |         /* Outline */ | ||||||
|         for (i = 0; i < count-1; i++) |         for (i = 0; i < count-1; i++) { | ||||||
|             draw->line(im, xy[i+i], xy[i+i+1], xy[i+i+2], xy[i+i+3], ink); |             draw->line(im, xy[i+i], xy[i+i+1], xy[i+i+2], xy[i+i+3], ink); | ||||||
|  |         } | ||||||
|         draw->line(im, xy[i+i], xy[i+i+1], xy[0], xy[1], ink); |         draw->line(im, xy[i+i], xy[i+i+1], xy[0], xy[1], ink); | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
|  | @ -838,8 +867,9 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1, | ||||||
| 
 | 
 | ||||||
|     DRAWINIT(); |     DRAWINIT(); | ||||||
| 
 | 
 | ||||||
|     while (end < start) |     while (end < start) { | ||||||
|         end += 360; |         end += 360; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (end - start > 360) { |     if (end - start > 360) { | ||||||
|         // no need to go in loops
 |         // no need to go in loops
 | ||||||
|  | @ -848,8 +878,9 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1, | ||||||
| 
 | 
 | ||||||
|     w = x1 - x0; |     w = x1 - x0; | ||||||
|     h = y1 - y0; |     h = y1 - y0; | ||||||
|     if (w <= 0 || h <= 0) |     if (w <= 0 || h <= 0) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     cx = (x0 + x1) / 2; |     cx = (x0 + x1) / 2; | ||||||
|     cy = (y0 + y1) / 2; |     cy = (y0 + y1) / 2; | ||||||
|  | @ -860,10 +891,11 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1, | ||||||
|                 i = end; |                 i = end; | ||||||
|             } |             } | ||||||
|             ellipsePoint(cx, cy, w, h, i, &x, &y); |             ellipsePoint(cx, cy, w, h, i, &x, &y); | ||||||
|             if (i != start) |             if (i != start) { | ||||||
|                 draw->line(im, lx, ly, x, y, ink); |                 draw->line(im, lx, ly, x, y, ink); | ||||||
|             else |             } else { | ||||||
|                 sx = x, sy = y; |                 sx = x, sy = y; | ||||||
|  |             } | ||||||
|             lx = x, ly = y; |             lx = x, ly = y; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -874,8 +906,9 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1, | ||||||
|                     draw->line(im, cx, cy, sx, sy, ink); |                     draw->line(im, cx, cy, sx, sy, ink); | ||||||
|                 } |                 } | ||||||
|             } else if (mode == CHORD) { |             } else if (mode == CHORD) { | ||||||
|                 if (x != sx || y != sy) |                 if (x != sx || y != sy) { | ||||||
|                     draw->line(im, x, y, sx, sy, ink); |                     draw->line(im, x, y, sx, sy, ink); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|  | @ -908,8 +941,9 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1, | ||||||
|             } |             } | ||||||
|             lx = x, ly = y; |             lx = x, ly = y; | ||||||
|         } |         } | ||||||
|         if (n == 0) |         if (n == 0) { | ||||||
|             return 0; |             return 0; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (inner) { |         if (inner) { | ||||||
|             // Inner circle
 |             // Inner circle
 | ||||||
|  | @ -930,10 +964,11 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1, | ||||||
|                         i = end; |                         i = end; | ||||||
|                     } |                     } | ||||||
|                     ellipsePoint(cx, cy, w, h, i, &x, &y); |                     ellipsePoint(cx, cy, w, h, i, &x, &y); | ||||||
|                     if (i == start) |                     if (i == start) { | ||||||
|                         sx_inner = x, sy_inner = y; |                         sx_inner = x, sy_inner = y; | ||||||
|                     else |                     } else { | ||||||
|                         add_edge(&e[n++], lx_inner, ly_inner, x, y); |                         add_edge(&e[n++], lx_inner, ly_inner, x, y); | ||||||
|  |                     } | ||||||
|                     lx_inner = x, ly_inner = y; |                     lx_inner = x, ly_inner = y; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -1026,8 +1061,9 @@ ImagingOutlineNew(void) | ||||||
|     ImagingOutline outline; |     ImagingOutline outline; | ||||||
| 
 | 
 | ||||||
|     outline = calloc(1, sizeof(struct ImagingOutlineInstance)); |     outline = calloc(1, sizeof(struct ImagingOutlineInstance)); | ||||||
|     if (!outline) |     if (!outline) { | ||||||
|         return (ImagingOutline) ImagingError_MemoryError(); |         return (ImagingOutline) ImagingError_MemoryError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     outline->edges = NULL; |     outline->edges = NULL; | ||||||
|     outline->count = outline->size = 0; |     outline->count = outline->size = 0; | ||||||
|  | @ -1040,11 +1076,13 @@ ImagingOutlineNew(void) | ||||||
| void | void | ||||||
| ImagingOutlineDelete(ImagingOutline outline) | ImagingOutlineDelete(ImagingOutline outline) | ||||||
| { | { | ||||||
|     if (!outline) |     if (!outline) { | ||||||
|         return; |         return; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (outline->edges) |     if (outline->edges) { | ||||||
|         free(outline->edges); |         free(outline->edges); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     free(outline); |     free(outline); | ||||||
| } | } | ||||||
|  | @ -1068,8 +1106,9 @@ allocate(ImagingOutline outline, int extra) | ||||||
|             /* malloc check ok, overflow checked above */ |             /* malloc check ok, overflow checked above */ | ||||||
|             e = realloc(outline->edges, outline->size * sizeof(Edge)); |             e = realloc(outline->edges, outline->size * sizeof(Edge)); | ||||||
|         } |         } | ||||||
|         if (!e) |         if (!e) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  |         } | ||||||
|         outline->edges = e; |         outline->edges = e; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1095,8 +1134,9 @@ ImagingOutlineLine(ImagingOutline outline, float x1, float y1) | ||||||
|     Edge* e; |     Edge* e; | ||||||
| 
 | 
 | ||||||
|     e = allocate(outline, 1); |     e = allocate(outline, 1); | ||||||
|     if (!e) |     if (!e) { | ||||||
|         return -1; /* out of memory */ |         return -1; /* out of memory */ | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     add_edge(e, (int) outline->x, (int) outline->y, (int) x1, (int) y1); |     add_edge(e, (int) outline->x, (int) outline->y, (int) x1, (int) y1); | ||||||
| 
 | 
 | ||||||
|  | @ -1117,8 +1157,9 @@ ImagingOutlineCurve(ImagingOutline outline, float x1, float y1, | ||||||
| #define STEPS 32 | #define STEPS 32 | ||||||
| 
 | 
 | ||||||
|     e = allocate(outline, STEPS); |     e = allocate(outline, STEPS); | ||||||
|     if (!e) |     if (!e) { | ||||||
|         return -1; /* out of memory */ |         return -1; /* out of memory */ | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     xo = outline->x; |     xo = outline->x; | ||||||
|     yo = outline->y; |     yo = outline->y; | ||||||
|  | @ -1153,8 +1194,9 @@ ImagingOutlineCurve(ImagingOutline outline, float x1, float y1, | ||||||
| int | int | ||||||
| ImagingOutlineClose(ImagingOutline outline) | ImagingOutlineClose(ImagingOutline outline) | ||||||
| { | { | ||||||
|     if (outline->x == outline->x0 && outline->y == outline->y0) |     if (outline->x == outline->x0 && outline->y == outline->y0) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
|     return ImagingOutlineLine(outline, outline->x0, outline->y0); |     return ImagingOutlineLine(outline, outline->x0, outline->y0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1191,14 +1233,16 @@ ImagingOutlineTransform(ImagingOutline outline, double a[6]) | ||||||
|         y0 = eIn->y0; |         y0 = eIn->y0; | ||||||
| 
 | 
 | ||||||
|         /* FIXME: ouch! */ |         /* FIXME: ouch! */ | ||||||
|         if (eIn->x0 == eIn->xmin) |         if (eIn->x0 == eIn->xmin) { | ||||||
|             x1 = eIn->xmax; |             x1 = eIn->xmax; | ||||||
|         else |         } else { | ||||||
|             x1 = eIn->xmin; |             x1 = eIn->xmin; | ||||||
|         if (eIn->y0 == eIn->ymin) |         } | ||||||
|  |         if (eIn->y0 == eIn->ymin) { | ||||||
|             y1 = eIn->ymax; |             y1 = eIn->ymax; | ||||||
|         else |         } else { | ||||||
|             y1 = eIn->ymin; |             y1 = eIn->ymin; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         /* full moon tonight!  if this doesn't work, you may need to
 |         /* full moon tonight!  if this doesn't work, you may need to
 | ||||||
|            upgrade your compiler (make sure you have the right service |            upgrade your compiler (make sure you have the right service | ||||||
|  |  | ||||||
|  | @ -34,12 +34,14 @@ ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality) | ||||||
|     /* Check arguments */ |     /* Check arguments */ | ||||||
|     width  = extent[2] - extent[0]; |     width  = extent[2] - extent[0]; | ||||||
|     height = extent[3] - extent[1]; |     height = extent[3] - extent[1]; | ||||||
|     if (width < 0.0 || height < 0.0 || quality < 2) |     if (width < 0.0 || height < 0.0 || quality < 2) { | ||||||
|         return (Imaging) ImagingError_ValueError(NULL); |         return (Imaging) ImagingError_ValueError(NULL); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     im = ImagingNewDirty("L", xsize, ysize); |     im = ImagingNewDirty("L", xsize, ysize); | ||||||
|     if (!im) |     if (!im) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     dr = width/(xsize-1); |     dr = width/(xsize-1); | ||||||
|     di = height/(ysize-1); |     di = height/(ysize-1); | ||||||
|  | @ -82,8 +84,9 @@ ImagingEffectNoise(int xsize, int ysize, float sigma) | ||||||
|     double this, next; |     double this, next; | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty("L", xsize, ysize); |     imOut = ImagingNewDirty("L", xsize, ysize); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     next = 0.0; |     next = 0.0; | ||||||
|     nextok = 0; |     nextok = 0; | ||||||
|  | @ -123,20 +126,23 @@ ImagingEffectSpread(Imaging imIn, int distance) | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty(imIn->mode, imIn->xsize, imIn->ysize); |     imOut = ImagingNewDirty(imIn->mode, imIn->xsize, imIn->ysize); | ||||||
| 
 | 
 | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
| #define SPREAD(type, image)\ | #define SPREAD(type, image)\ | ||||||
|     for (y = 0; y < imOut->ysize; y++)\ |     for (y = 0; y < imOut->ysize; y++) {\ | ||||||
|         for (x = 0; x < imOut->xsize; x++) {\ |         for (x = 0; x < imOut->xsize; x++) {\ | ||||||
|             int xx = x + (rand() % distance) - distance/2;\ |             int xx = x + (rand() % distance) - distance/2;\ | ||||||
|             int yy = y + (rand() % distance) - distance/2;\ |             int yy = y + (rand() % distance) - distance/2;\ | ||||||
|             if (xx >= 0 && xx < imIn->xsize && yy >= 0 && yy < imIn->ysize) {\ |             if (xx >= 0 && xx < imIn->xsize && yy >= 0 && yy < imIn->ysize) {\ | ||||||
|                 imOut->image[yy][xx] = imIn->image[y][x];\ |                 imOut->image[yy][xx] = imIn->image[y][x];\ | ||||||
|                 imOut->image[y][x]   = imIn->image[yy][xx];\ |                 imOut->image[y][x]   = imIn->image[yy][xx];\ | ||||||
|             } else\ |             } else {\ | ||||||
|                 imOut->image[y][x]   = imIn->image[y][x];\ |                 imOut->image[y][x]   = imIn->image[y][x];\ | ||||||
|         } |             }\ | ||||||
|  |         }\ | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (imIn->image8) { |     if (imIn->image8) { | ||||||
|         SPREAD(UINT8, image8); |         SPREAD(UINT8, image8); | ||||||
|  |  | ||||||
|  | @ -40,15 +40,17 @@ ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|     for (;;) { |     for (;;) { | ||||||
| 
 | 
 | ||||||
|         if (state->state == NEWLINE) { |         if (state->state == NEWLINE) { | ||||||
|             if (bytes < 1) |             if (bytes < 1) { | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
|             *ptr++ = '\n'; |             *ptr++ = '\n'; | ||||||
|             bytes--; |             bytes--; | ||||||
|             state->state = HEXBYTE; |             state->state = HEXBYTE; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (bytes < 2) |         if (bytes < 2) { | ||||||
|             break; |             break; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         i = in[state->x++]; |         i = in[state->x++]; | ||||||
|         *ptr++ = hex[(i>>4)&15]; |         *ptr++ = hex[(i>>4)&15]; | ||||||
|  | @ -56,8 +58,9 @@ ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|         bytes -= 2; |         bytes -= 2; | ||||||
| 
 | 
 | ||||||
|         /* Skip junk bytes */ |         /* Skip junk bytes */ | ||||||
|         if (im->bands == 3 && (state->x & 3) == 3) |         if (im->bands == 3 && (state->x & 3) == 3) { | ||||||
|             state->x++; |             state->x++; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (++state->count >= 79/2) { |         if (++state->count >= 79/2) { | ||||||
|             state->state = NEWLINE; |             state->state = NEWLINE; | ||||||
|  |  | ||||||
|  | @ -56,8 +56,9 @@ ImagingError_Mismatch(void) | ||||||
| void * | void * | ||||||
| ImagingError_ValueError(const char *message) | ImagingError_ValueError(const char *message) | ||||||
| { | { | ||||||
|     if (!message) |     if (!message) { | ||||||
|         message = "exception: bad argument to function"; |         message = "exception: bad argument to function"; | ||||||
|  |     } | ||||||
|     fprintf(stderr, "*** %s\n", message); |     fprintf(stderr, "*** %s\n", message); | ||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -31,15 +31,18 @@ ImagingSaveRaw(Imaging im, FILE* fp) | ||||||
|         /* @PIL227: FIXME: for mode "1", map != 0 to 255 */ |         /* @PIL227: FIXME: for mode "1", map != 0 to 255 */ | ||||||
| 
 | 
 | ||||||
|         /* PGM "L" */ |         /* PGM "L" */ | ||||||
|         for (y = 0; y < im->ysize; y++) |         for (y = 0; y < im->ysize; y++) { | ||||||
|             fwrite(im->image[y], 1, im->xsize, fp); |             fwrite(im->image[y], 1, im->xsize, fp); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } else { |     } else { | ||||||
| 
 | 
 | ||||||
|         /* PPM "RGB" or other internal format */ |         /* PPM "RGB" or other internal format */ | ||||||
|         for (y = 0; y < im->ysize; y++) |         for (y = 0; y < im->ysize; y++) { | ||||||
|             for (x = i = 0; x < im->xsize; x++, i += im->pixelsize) |             for (x = i = 0; x < im->xsize; x++, i += im->pixelsize) { | ||||||
|                 fwrite(im->image[y]+i, 1, im->bands, fp); |                 fwrite(im->image[y]+i, 1, im->bands, fp); | ||||||
|  |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -30,27 +30,33 @@ ImagingFill(Imaging im, const void* colour) | ||||||
|         /* use generic API */ |         /* use generic API */ | ||||||
|         ImagingAccess access = ImagingAccessNew(im); |         ImagingAccess access = ImagingAccessNew(im); | ||||||
|         if (access) { |         if (access) { | ||||||
|             for (y = 0; y < im->ysize; y++) |             for (y = 0; y < im->ysize; y++) { | ||||||
|                 for (x = 0; x < im->xsize; x++) |                 for (x = 0; x < im->xsize; x++) { | ||||||
|                     access->put_pixel(im, x, y, colour); |                     access->put_pixel(im, x, y, colour); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|             ImagingAccessDelete(im, access); |             ImagingAccessDelete(im, access); | ||||||
|         } else { |         } else { | ||||||
|             /* wipe the image */ |             /* wipe the image */ | ||||||
|             for (y = 0; y < im->ysize; y++) |             for (y = 0; y < im->ysize; y++) { | ||||||
|                 memset(im->image[y], 0, im->linesize); |                 memset(im->image[y], 0, im->linesize); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         INT32 c = 0L; |         INT32 c = 0L; | ||||||
|         ImagingSectionEnter(&cookie); |         ImagingSectionEnter(&cookie); | ||||||
|         memcpy(&c, colour, im->pixelsize); |         memcpy(&c, colour, im->pixelsize); | ||||||
|         if (im->image32 && c != 0L) { |         if (im->image32 && c != 0L) { | ||||||
|             for (y = 0; y < im->ysize; y++) |             for (y = 0; y < im->ysize; y++) { | ||||||
|                 for (x = 0; x < im->xsize; x++) |                 for (x = 0; x < im->xsize; x++) { | ||||||
|                     im->image32[y][x] = c; |                     im->image32[y][x] = c; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         } else { |         } else { | ||||||
|             unsigned char cc = (unsigned char) *(UINT8*) colour; |             unsigned char cc = (unsigned char) *(UINT8*) colour; | ||||||
|             for (y = 0; y < im->ysize; y++) |             for (y = 0; y < im->ysize; y++) { | ||||||
|                 memset(im->image[y], cc, im->linesize); |                 memset(im->image[y], cc, im->linesize); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         ImagingSectionLeave(&cookie); |         ImagingSectionLeave(&cookie); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -29,10 +29,12 @@ | ||||||
| 
 | 
 | ||||||
| static inline UINT8 clip8(float in) | static inline UINT8 clip8(float in) | ||||||
| { | { | ||||||
|     if (in <= 0.0) |     if (in <= 0.0) { | ||||||
|         return 0; |         return 0; | ||||||
|     if (in >= 255.0) |     } | ||||||
|  |     if (in >= 255.0) { | ||||||
|         return 255; |         return 255; | ||||||
|  |     } | ||||||
|     return (UINT8) in; |     return (UINT8) in; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -43,32 +45,40 @@ ImagingExpand(Imaging imIn, int xmargin, int ymargin, int mode) | ||||||
|     int x, y; |     int x, y; | ||||||
|     ImagingSectionCookie cookie; |     ImagingSectionCookie cookie; | ||||||
| 
 | 
 | ||||||
|     if (xmargin < 0 && ymargin < 0) |     if (xmargin < 0 && ymargin < 0) { | ||||||
|         return (Imaging) ImagingError_ValueError("bad kernel size"); |         return (Imaging) ImagingError_ValueError("bad kernel size"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty( |     imOut = ImagingNewDirty( | ||||||
|         imIn->mode, imIn->xsize+2*xmargin, imIn->ysize+2*ymargin); |         imIn->mode, imIn->xsize+2*xmargin, imIn->ysize+2*ymargin); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
| #define EXPAND_LINE(type, image, yin, yout) {\ | #define EXPAND_LINE(type, image, yin, yout) {\ | ||||||
|     for (x = 0; x < xmargin; x++)\ |     for (x = 0; x < xmargin; x++) {\ | ||||||
|         imOut->image[yout][x] = imIn->image[yin][0];\ |         imOut->image[yout][x] = imIn->image[yin][0];\ | ||||||
|     for (x = 0; x < imIn->xsize; x++)\ |     }\ | ||||||
|  |     for (x = 0; x < imIn->xsize; x++) {\ | ||||||
|         imOut->image[yout][x+xmargin] = imIn->image[yin][x];\ |         imOut->image[yout][x+xmargin] = imIn->image[yin][x];\ | ||||||
|     for (x = 0; x < xmargin; x++)\ |     }\ | ||||||
|  |     for (x = 0; x < xmargin; x++) {\ | ||||||
|         imOut->image[yout][xmargin+imIn->xsize+x] =\ |         imOut->image[yout][xmargin+imIn->xsize+x] =\ | ||||||
|             imIn->image[yin][imIn->xsize-1];\ |             imIn->image[yin][imIn->xsize-1];\ | ||||||
|     } |     }\ | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| #define EXPAND(type, image) {\ | #define EXPAND(type, image) {\ | ||||||
|     for (y = 0; y < ymargin; y++)\ |     for (y = 0; y < ymargin; y++) {\ | ||||||
|         EXPAND_LINE(type, image, 0, y);\ |         EXPAND_LINE(type, image, 0, y);\ | ||||||
|     for (y = 0; y < imIn->ysize; y++)\ |     }\ | ||||||
|  |     for (y = 0; y < imIn->ysize; y++) {\ | ||||||
|         EXPAND_LINE(type, image, y, y+ymargin);\ |         EXPAND_LINE(type, image, y, y+ymargin);\ | ||||||
|     for (y = 0; y < ymargin; y++)\ |     }\ | ||||||
|  |     for (y = 0; y < ymargin; y++) {\ | ||||||
|         EXPAND_LINE(type, image, imIn->ysize-1, ymargin+imIn->ysize+y);\ |         EXPAND_LINE(type, image, imIn->ysize-1, ymargin+imIn->ysize+y);\ | ||||||
|     } |     }\ | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
|     if (imIn->image8) { |     if (imIn->image8) { | ||||||
|  | @ -330,18 +340,22 @@ ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel, | ||||||
|     Imaging imOut; |     Imaging imOut; | ||||||
|     ImagingSectionCookie cookie; |     ImagingSectionCookie cookie; | ||||||
| 
 | 
 | ||||||
|     if ( ! im || im->type != IMAGING_TYPE_UINT8) |     if ( ! im || im->type != IMAGING_TYPE_UINT8) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (im->xsize < xsize || im->ysize < ysize) |     if (im->xsize < xsize || im->ysize < ysize) { | ||||||
|         return ImagingCopy(im); |         return ImagingCopy(im); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if ((xsize != 3 && xsize != 5) || xsize != ysize) |     if ((xsize != 3 && xsize != 5) || xsize != ysize) { | ||||||
|         return (Imaging) ImagingError_ValueError("bad kernel size"); |         return (Imaging) ImagingError_ValueError("bad kernel size"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); |     imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
|     if (xsize == 3) { |     if (xsize == 3) { | ||||||
|  |  | ||||||
|  | @ -41,8 +41,9 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
| 
 | 
 | ||||||
|     /* If not even the chunk size is present, we'd better leave */ |     /* If not even the chunk size is present, we'd better leave */ | ||||||
| 
 | 
 | ||||||
|     if (bytes < 4) |     if (bytes < 4) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* We don't decode anything unless we have a full chunk in the
 |     /* We don't decode anything unless we have a full chunk in the
 | ||||||
|        input buffer */ |        input buffer */ | ||||||
|  | @ -50,8 +51,9 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|     ptr = buf; |     ptr = buf; | ||||||
| 
 | 
 | ||||||
|     framesize = I32(ptr); |     framesize = I32(ptr); | ||||||
|     if (framesize < I32(ptr)) |     if (framesize < I32(ptr)) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Make sure this is a frame chunk.  The Python driver takes
 |     /* Make sure this is a frame chunk.  The Python driver takes
 | ||||||
|        case of other chunk types. */ |        case of other chunk types. */ | ||||||
|  | @ -112,8 +114,9 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|                         if (data[1] >= 128) { |                         if (data[1] >= 128) { | ||||||
|                             ERR_IF_DATA_OOB(4) |                             ERR_IF_DATA_OOB(4) | ||||||
|                             i = 256-data[1]; /* run */ |                             i = 256-data[1]; /* run */ | ||||||
|                             if (x + i + i > state->xsize) |                             if (x + i + i > state->xsize) { | ||||||
|                                 break; |                                 break; | ||||||
|  |                             } | ||||||
|                             for (j = 0; j < i; j++) { |                             for (j = 0; j < i; j++) { | ||||||
|                                 local_buf[x++] = data[2]; |                                 local_buf[x++] = data[2]; | ||||||
|                                 local_buf[x++] = data[3]; |                                 local_buf[x++] = data[3]; | ||||||
|  | @ -121,16 +124,18 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|                             data += 2 + 2; |                             data += 2 + 2; | ||||||
|                         } else { |                         } else { | ||||||
|                             i = 2 * (int) data[1]; /* chunk */ |                             i = 2 * (int) data[1]; /* chunk */ | ||||||
|                             if (x + i > state->xsize) |                             if (x + i > state->xsize) { | ||||||
|                                 break; |                                 break; | ||||||
|  |                             } | ||||||
|                             ERR_IF_DATA_OOB(2+i) |                             ERR_IF_DATA_OOB(2+i) | ||||||
|                             memcpy(local_buf + x, data + 2, i); |                             memcpy(local_buf + x, data + 2, i); | ||||||
|                             data += 2 + i; |                             data += 2 + i; | ||||||
|                             x += i; |                             x += i; | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     if (p < packets) |                     if (p < packets) { | ||||||
|                         break; /* didn't process all packets */ |                         break; /* didn't process all packets */ | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|                 if (l < lines) { |                 if (l < lines) { | ||||||
|                     /* didn't process all lines */ |                     /* didn't process all lines */ | ||||||
|  | @ -151,22 +156,25 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|                         x += data[0]; /* skip pixels */ |                         x += data[0]; /* skip pixels */ | ||||||
|                         if (data[1] & 0x80) { |                         if (data[1] & 0x80) { | ||||||
|                             i = 256-data[1]; /* run */ |                             i = 256-data[1]; /* run */ | ||||||
|                             if (x + i > state->xsize) |                             if (x + i > state->xsize) { | ||||||
|                                 break; |                                 break; | ||||||
|  |                             } | ||||||
|                             ERR_IF_DATA_OOB(3) |                             ERR_IF_DATA_OOB(3) | ||||||
|                             memset(out + x, data[2], i); |                             memset(out + x, data[2], i); | ||||||
|                             data += 3; |                             data += 3; | ||||||
|                         } else { |                         } else { | ||||||
|                             i = data[1]; /* chunk */ |                             i = data[1]; /* chunk */ | ||||||
|                             if (x + i > state->xsize) |                             if (x + i > state->xsize) { | ||||||
|                                 break; |                                 break; | ||||||
|  |                             } | ||||||
|                             ERR_IF_DATA_OOB(2+i) |                             ERR_IF_DATA_OOB(2+i) | ||||||
|                             memcpy(out + x, data + 2, i); |                             memcpy(out + x, data + 2, i); | ||||||
|                             data += i + 2; |                             data += i + 2; | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     if (p < packets) |                     if (p < packets) { | ||||||
|                         break; /* didn't process all packets */ |                         break; /* didn't process all packets */ | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|                 if (y < ymax) { |                 if (y < ymax) { | ||||||
|                     /* didn't process all lines */ |                     /* didn't process all lines */ | ||||||
|  | @ -176,8 +184,9 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|                 break; |                 break; | ||||||
|             case 13: |             case 13: | ||||||
|                 /* FLI BLACK chunk */ |                 /* FLI BLACK chunk */ | ||||||
|                 for (y = 0; y < state->ysize; y++) |                 for (y = 0; y < state->ysize; y++) { | ||||||
|                     memset(im->image[y], 0, state->xsize); |                     memset(im->image[y], 0, state->xsize); | ||||||
|  |                 } | ||||||
|                 break; |                 break; | ||||||
|             case 15: |             case 15: | ||||||
|                 /* FLI BRUN chunk */ |                 /* FLI BRUN chunk */ | ||||||
|  | @ -197,8 +206,9 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|                             data += i + 1; |                             data += i + 1; | ||||||
|                         } else { |                         } else { | ||||||
|                             i = data[0]; |                             i = data[0]; | ||||||
|                             if (x + i > state->xsize) |                             if (x + i > state->xsize) { | ||||||
|                                 break; /* safety first */ |                                 break; /* safety first */ | ||||||
|  |                             } | ||||||
|                             memset(out + x, data[1], i); |                             memset(out + x, data[1], i); | ||||||
|                             data += 2; |                             data += 2; | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|  | @ -20,10 +20,12 @@ ImagingFlipLeftRight(Imaging imOut, Imaging imIn) | ||||||
|     ImagingSectionCookie cookie; |     ImagingSectionCookie cookie; | ||||||
|     int x, y, xr; |     int x, y, xr; | ||||||
| 
 | 
 | ||||||
|     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) |     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|     if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) |     } | ||||||
|  |     if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) { | ||||||
|         return (Imaging) ImagingError_Mismatch(); |         return (Imaging) ImagingError_Mismatch(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, imIn); |     ImagingCopyPalette(imOut, imIn); | ||||||
| 
 | 
 | ||||||
|  | @ -32,8 +34,9 @@ ImagingFlipLeftRight(Imaging imOut, Imaging imIn) | ||||||
|         INT* in = (INT *)imIn->image[y]; \ |         INT* in = (INT *)imIn->image[y]; \ | ||||||
|         INT* out = (INT *)imOut->image[y]; \ |         INT* out = (INT *)imOut->image[y]; \ | ||||||
|         xr = imIn->xsize-1; \ |         xr = imIn->xsize-1; \ | ||||||
|         for (x = 0; x < imIn->xsize; x++, xr--) \ |         for (x = 0; x < imIn->xsize; x++, xr--) { \ | ||||||
|             out[xr] = in[x]; \ |             out[xr] = in[x]; \ | ||||||
|  |         } \ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
|  | @ -62,18 +65,21 @@ ImagingFlipTopBottom(Imaging imOut, Imaging imIn) | ||||||
|     ImagingSectionCookie cookie; |     ImagingSectionCookie cookie; | ||||||
|     int y, yr; |     int y, yr; | ||||||
| 
 | 
 | ||||||
|     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) |     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|     if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) |     } | ||||||
|  |     if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) { | ||||||
|         return (Imaging) ImagingError_Mismatch(); |         return (Imaging) ImagingError_Mismatch(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, imIn); |     ImagingCopyPalette(imOut, imIn); | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
| 
 | 
 | ||||||
|     yr = imIn->ysize - 1; |     yr = imIn->ysize - 1; | ||||||
|     for (y = 0; y < imIn->ysize; y++, yr--) |     for (y = 0; y < imIn->ysize; y++, yr--) { | ||||||
|         memcpy(imOut->image[yr], imIn->image[y], imIn->linesize); |         memcpy(imOut->image[yr], imIn->image[y], imIn->linesize); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingSectionLeave(&cookie); |     ImagingSectionLeave(&cookie); | ||||||
| 
 | 
 | ||||||
|  | @ -88,10 +94,12 @@ ImagingRotate90(Imaging imOut, Imaging imIn) | ||||||
|     int x, y, xx, yy, xr, xxsize, yysize; |     int x, y, xx, yy, xr, xxsize, yysize; | ||||||
|     int xxx, yyy, xxxsize, yyysize; |     int xxx, yyy, xxxsize, yyysize; | ||||||
| 
 | 
 | ||||||
|     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) |     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|     if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) |     } | ||||||
|  |     if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) { | ||||||
|         return (Imaging) ImagingError_Mismatch(); |         return (Imaging) ImagingError_Mismatch(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, imIn); |     ImagingCopyPalette(imOut, imIn); | ||||||
| 
 | 
 | ||||||
|  | @ -144,10 +152,12 @@ ImagingTranspose(Imaging imOut, Imaging imIn) | ||||||
|     int x, y, xx, yy, xxsize, yysize; |     int x, y, xx, yy, xxsize, yysize; | ||||||
|     int xxx, yyy, xxxsize, yyysize; |     int xxx, yyy, xxxsize, yyysize; | ||||||
| 
 | 
 | ||||||
|     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) |     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|     if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) |     } | ||||||
|  |     if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) { | ||||||
|         return (Imaging) ImagingError_Mismatch(); |         return (Imaging) ImagingError_Mismatch(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, imIn); |     ImagingCopyPalette(imOut, imIn); | ||||||
| 
 | 
 | ||||||
|  | @ -199,10 +209,12 @@ ImagingTransverse(Imaging imOut, Imaging imIn) | ||||||
|     int x, y, xr, yr, xx, yy, xxsize, yysize; |     int x, y, xr, yr, xx, yy, xxsize, yysize; | ||||||
|     int xxx, yyy, xxxsize, yyysize; |     int xxx, yyy, xxxsize, yyysize; | ||||||
| 
 | 
 | ||||||
|     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) |     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|     if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) |     } | ||||||
|  |     if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) { | ||||||
|         return (Imaging) ImagingError_Mismatch(); |         return (Imaging) ImagingError_Mismatch(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, imIn); |     ImagingCopyPalette(imOut, imIn); | ||||||
| 
 | 
 | ||||||
|  | @ -255,10 +267,12 @@ ImagingRotate180(Imaging imOut, Imaging imIn) | ||||||
|     ImagingSectionCookie cookie; |     ImagingSectionCookie cookie; | ||||||
|     int x, y, xr, yr; |     int x, y, xr, yr; | ||||||
| 
 | 
 | ||||||
|     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) |     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|     if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) |     } | ||||||
|  |     if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) { | ||||||
|         return (Imaging) ImagingError_Mismatch(); |         return (Imaging) ImagingError_Mismatch(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, imIn); |     ImagingCopyPalette(imOut, imIn); | ||||||
| 
 | 
 | ||||||
|  | @ -267,8 +281,9 @@ ImagingRotate180(Imaging imOut, Imaging imIn) | ||||||
|         INT* in = (INT *)imIn->image[y]; \ |         INT* in = (INT *)imIn->image[y]; \ | ||||||
|         INT* out = (INT *)imOut->image[yr]; \ |         INT* out = (INT *)imOut->image[yr]; \ | ||||||
|         xr = imIn->xsize-1; \ |         xr = imIn->xsize-1; \ | ||||||
|         for (x = 0; x < imIn->xsize; x++, xr--) \ |         for (x = 0; x < imIn->xsize; x++, xr--) { \ | ||||||
|             out[xr] = in[x]; \ |             out[xr] = in[x]; \ | ||||||
|  |         } \ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
|  | @ -299,10 +314,12 @@ ImagingRotate270(Imaging imOut, Imaging imIn) | ||||||
|     int x, y, xx, yy, yr, xxsize, yysize; |     int x, y, xx, yy, yr, xxsize, yysize; | ||||||
|     int xxx, yyy, xxxsize, yyysize; |     int xxx, yyy, xxxsize, yyysize; | ||||||
| 
 | 
 | ||||||
|     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) |     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|     if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) |     } | ||||||
|  |     if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) { | ||||||
|         return (Imaging) ImagingError_Mismatch(); |         return (Imaging) ImagingError_Mismatch(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, imIn); |     ImagingCopyPalette(imOut, imIn); | ||||||
| 
 | 
 | ||||||
|  | @ -415,8 +432,9 @@ nearest_filter8(void* out, Imaging im, double xin, double yin) | ||||||
| { | { | ||||||
|     int x = COORD(xin); |     int x = COORD(xin); | ||||||
|     int y = COORD(yin); |     int y = COORD(yin); | ||||||
|     if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) |     if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
|     ((UINT8*)out)[0] = im->image8[y][x]; |     ((UINT8*)out)[0] = im->image8[y][x]; | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  | @ -426,8 +444,9 @@ nearest_filter16(void* out, Imaging im, double xin, double yin) | ||||||
| { | { | ||||||
|     int x = COORD(xin); |     int x = COORD(xin); | ||||||
|     int y = COORD(yin); |     int y = COORD(yin); | ||||||
|     if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) |     if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
|     memcpy(out, im->image8[y] + x * sizeof(INT16), sizeof(INT16)); |     memcpy(out, im->image8[y] + x * sizeof(INT16), sizeof(INT16)); | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  | @ -437,8 +456,9 @@ nearest_filter32(void* out, Imaging im, double xin, double yin) | ||||||
| { | { | ||||||
|     int x = COORD(xin); |     int x = COORD(xin); | ||||||
|     int y = COORD(yin); |     int y = COORD(yin); | ||||||
|     if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) |     if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
|     memcpy(out, &im->image32[y][x], sizeof(INT32)); |     memcpy(out, &im->image32[y][x], sizeof(INT32)); | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  | @ -455,8 +475,9 @@ nearest_filter32(void* out, Imaging im, double xin, double yin) | ||||||
|     double v1, v2;\ |     double v1, v2;\ | ||||||
|     double dx, dy;\ |     double dx, dy;\ | ||||||
|     type* in;\ |     type* in;\ | ||||||
|     if (xin < 0.0 || xin >= im->xsize || yin < 0.0 || yin >= im->ysize)\ |     if (xin < 0.0 || xin >= im->xsize || yin < 0.0 || yin >= im->ysize) {\ | ||||||
|         return 0;\ |         return 0;\ | ||||||
|  |     }\ | ||||||
|     xin -= 0.5;\ |     xin -= 0.5;\ | ||||||
|     yin -= 0.5;\ |     yin -= 0.5;\ | ||||||
|     x = FLOOR(xin);\ |     x = FLOOR(xin);\ | ||||||
|  | @ -472,8 +493,9 @@ nearest_filter32(void* out, Imaging im, double xin, double yin) | ||||||
|     if (y+1 >= 0 && y+1 < im->ysize) {\ |     if (y+1 >= 0 && y+1 < im->ysize) {\ | ||||||
|         in = (type*) ((image)[y+1] + offset);\ |         in = (type*) ((image)[y+1] + offset);\ | ||||||
|         BILINEAR(v2, in[x0], in[x1], dx);\ |         BILINEAR(v2, in[x0], in[x1], dx);\ | ||||||
|     } else\ |     } else {\ | ||||||
|         v2 = v1;\ |         v2 = v1;\ | ||||||
|  |     }\ | ||||||
|     BILINEAR(v1, v1, v2, dy);\ |     BILINEAR(v1, v1, v2, dy);\ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -552,8 +574,9 @@ bilinear_filter32RGB(void* out, Imaging im, double xin, double yin) | ||||||
|     double v1, v2, v3, v4;\ |     double v1, v2, v3, v4;\ | ||||||
|     double dx, dy;\ |     double dx, dy;\ | ||||||
|     type* in;\ |     type* in;\ | ||||||
|     if (xin < 0.0 || xin >= im->xsize || yin < 0.0 || yin >= im->ysize)\ |     if (xin < 0.0 || xin >= im->xsize || yin < 0.0 || yin >= im->ysize) {\ | ||||||
|         return 0;\ |         return 0;\ | ||||||
|  |     }\ | ||||||
|     xin -= 0.5;\ |     xin -= 0.5;\ | ||||||
|     yin -= 0.5;\ |     yin -= 0.5;\ | ||||||
|     x = FLOOR(xin);\ |     x = FLOOR(xin);\ | ||||||
|  | @ -572,18 +595,21 @@ bilinear_filter32RGB(void* out, Imaging im, double xin, double yin) | ||||||
|     if (y+1 >= 0 && y+1 < im->ysize) {\ |     if (y+1 >= 0 && y+1 < im->ysize) {\ | ||||||
|         in = (type*) ((image)[y+1] + offset);\ |         in = (type*) ((image)[y+1] + offset);\ | ||||||
|         BICUBIC(v2, in[x0], in[x1], in[x2], in[x3], dx);\ |         BICUBIC(v2, in[x0], in[x1], in[x2], in[x3], dx);\ | ||||||
|     } else\ |     } else {\ | ||||||
|         v2 = v1;\ |         v2 = v1;\ | ||||||
|  |     }\ | ||||||
|     if (y+2 >= 0 && y+2 < im->ysize) {\ |     if (y+2 >= 0 && y+2 < im->ysize) {\ | ||||||
|         in = (type*) ((image)[y+2] + offset);\ |         in = (type*) ((image)[y+2] + offset);\ | ||||||
|         BICUBIC(v3, in[x0], in[x1], in[x2], in[x3], dx);\ |         BICUBIC(v3, in[x0], in[x1], in[x2], in[x3], dx);\ | ||||||
|     } else\ |     } else {\ | ||||||
|         v3 = v2;\ |         v3 = v2;\ | ||||||
|  |     }\ | ||||||
|     if (y+3 >= 0 && y+3 < im->ysize) {\ |     if (y+3 >= 0 && y+3 < im->ysize) {\ | ||||||
|         in = (type*) ((image)[y+3] + offset);\ |         in = (type*) ((image)[y+3] + offset);\ | ||||||
|         BICUBIC(v4, in[x0], in[x1], in[x2], in[x3], dx);\ |         BICUBIC(v4, in[x0], in[x1], in[x2], in[x3], dx);\ | ||||||
|     } else\ |     } else {\ | ||||||
|         v4 = v3;\ |         v4 = v3;\ | ||||||
|  |     }\ | ||||||
|     BICUBIC(v1, v1, v2, v3, v4, dy);\ |     BICUBIC(v1, v1, v2, v3, v4, dy);\ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -593,12 +619,13 @@ bicubic_filter8(void* out, Imaging im, double xin, double yin) | ||||||
| { | { | ||||||
|     BICUBIC_HEAD(UINT8); |     BICUBIC_HEAD(UINT8); | ||||||
|     BICUBIC_BODY(UINT8, im->image8, 1, 0); |     BICUBIC_BODY(UINT8, im->image8, 1, 0); | ||||||
|     if (v1 <= 0.0) |     if (v1 <= 0.0) { | ||||||
|         ((UINT8*)out)[0] = 0; |         ((UINT8*)out)[0] = 0; | ||||||
|     else if (v1 >= 255.0) |     } else if (v1 >= 255.0) { | ||||||
|         ((UINT8*)out)[0] = 255; |         ((UINT8*)out)[0] = 255; | ||||||
|     else |     } else { | ||||||
|         ((UINT8*)out)[0] = (UINT8) v1; |         ((UINT8*)out)[0] = (UINT8) v1; | ||||||
|  |     } | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -643,12 +670,13 @@ bicubic_filter32LA(void* out, Imaging im, double xin, double yin) | ||||||
|         ((UINT8*)out)[2] = (UINT8) v1; |         ((UINT8*)out)[2] = (UINT8) v1; | ||||||
|     } |     } | ||||||
|     BICUBIC_BODY(UINT8, im->image, 4, 3); |     BICUBIC_BODY(UINT8, im->image, 4, 3); | ||||||
|     if (v1 <= 0.0) |     if (v1 <= 0.0) { | ||||||
|         ((UINT8*)out)[3] = 0; |         ((UINT8*)out)[3] = 0; | ||||||
|     else if (v1 >= 255.0) |     } else if (v1 >= 255.0) { | ||||||
|         ((UINT8*)out)[3] = 255; |         ((UINT8*)out)[3] = 255; | ||||||
|     else |     } else { | ||||||
|         ((UINT8*)out)[3] = (UINT8) v1; |         ((UINT8*)out)[3] = (UINT8) v1; | ||||||
|  |     } | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -659,12 +687,13 @@ bicubic_filter32RGB(void* out, Imaging im, double xin, double yin) | ||||||
|     BICUBIC_HEAD(UINT8); |     BICUBIC_HEAD(UINT8); | ||||||
|     for (b = 0; b < im->bands; b++) { |     for (b = 0; b < im->bands; b++) { | ||||||
|         BICUBIC_BODY(UINT8, im->image, 4, b); |         BICUBIC_BODY(UINT8, im->image, 4, b); | ||||||
|         if (v1 <= 0.0) |         if (v1 <= 0.0) { | ||||||
|             ((UINT8*)out)[b] = 0; |             ((UINT8*)out)[b] = 0; | ||||||
|         else if (v1 >= 255.0) |         } else if (v1 >= 255.0) { | ||||||
|             ((UINT8*)out)[b] = 255; |             ((UINT8*)out)[b] = 255; | ||||||
|         else |         } else { | ||||||
|             ((UINT8*)out)[b] = (UINT8) v1; |             ((UINT8*)out)[b] = (UINT8) v1; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  | @ -678,7 +707,7 @@ getfilter(Imaging im, int filterid) | ||||||
| { | { | ||||||
|     switch (filterid) { |     switch (filterid) { | ||||||
|     case IMAGING_TRANSFORM_NEAREST: |     case IMAGING_TRANSFORM_NEAREST: | ||||||
|         if (im->image8) |         if (im->image8) { | ||||||
|             switch (im->type) { |             switch (im->type) { | ||||||
|             case IMAGING_TYPE_UINT8: |             case IMAGING_TYPE_UINT8: | ||||||
|                 return nearest_filter8; |                 return nearest_filter8; | ||||||
|  | @ -692,19 +721,21 @@ getfilter(Imaging im, int filterid) | ||||||
|                     return nearest_filter32; |                     return nearest_filter32; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         else |         } else { | ||||||
|             return nearest_filter32; |             return nearest_filter32; | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
|     case IMAGING_TRANSFORM_BILINEAR: |     case IMAGING_TRANSFORM_BILINEAR: | ||||||
|         if (im->image8) |         if (im->image8) { | ||||||
|             return bilinear_filter8; |             return bilinear_filter8; | ||||||
|         else if (im->image32) { |         } else if (im->image32) { | ||||||
|             switch (im->type) { |             switch (im->type) { | ||||||
|             case IMAGING_TYPE_UINT8: |             case IMAGING_TYPE_UINT8: | ||||||
|                 if (im->bands == 2) |                 if (im->bands == 2) { | ||||||
|                     return bilinear_filter32LA; |                     return bilinear_filter32LA; | ||||||
|                 else |                 } else { | ||||||
|                     return bilinear_filter32RGB; |                     return bilinear_filter32RGB; | ||||||
|  |                 } | ||||||
|             case IMAGING_TYPE_INT32: |             case IMAGING_TYPE_INT32: | ||||||
|                 return bilinear_filter32I; |                 return bilinear_filter32I; | ||||||
|             case IMAGING_TYPE_FLOAT32: |             case IMAGING_TYPE_FLOAT32: | ||||||
|  | @ -713,15 +744,16 @@ getfilter(Imaging im, int filterid) | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     case IMAGING_TRANSFORM_BICUBIC: |     case IMAGING_TRANSFORM_BICUBIC: | ||||||
|         if (im->image8) |         if (im->image8) { | ||||||
|             return bicubic_filter8; |             return bicubic_filter8; | ||||||
|         else if (im->image32) { |         } else if (im->image32) { | ||||||
|             switch (im->type) { |             switch (im->type) { | ||||||
|             case IMAGING_TYPE_UINT8: |             case IMAGING_TYPE_UINT8: | ||||||
|                 if (im->bands == 2) |                 if (im->bands == 2) { | ||||||
|                     return bicubic_filter32LA; |                     return bicubic_filter32LA; | ||||||
|                 else |                 } else { | ||||||
|                     return bicubic_filter32RGB; |                     return bicubic_filter32RGB; | ||||||
|  |                 } | ||||||
|             case IMAGING_TYPE_INT32: |             case IMAGING_TYPE_INT32: | ||||||
|                 return bicubic_filter32I; |                 return bicubic_filter32I; | ||||||
|             case IMAGING_TYPE_FLOAT32: |             case IMAGING_TYPE_FLOAT32: | ||||||
|  | @ -751,32 +783,39 @@ ImagingGenericTransform( | ||||||
|     double xx, yy; |     double xx, yy; | ||||||
| 
 | 
 | ||||||
|     ImagingTransformFilter filter = getfilter(imIn, filterid); |     ImagingTransformFilter filter = getfilter(imIn, filterid); | ||||||
|     if (!filter) |     if (!filter) { | ||||||
|         return (Imaging) ImagingError_ValueError("bad filter number"); |         return (Imaging) ImagingError_ValueError("bad filter number"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) |     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, imIn); |     ImagingCopyPalette(imOut, imIn); | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
| 
 | 
 | ||||||
|     if (x0 < 0) |     if (x0 < 0) { | ||||||
|         x0 = 0; |         x0 = 0; | ||||||
|     if (y0 < 0) |     } | ||||||
|  |     if (y0 < 0) { | ||||||
|         y0 = 0; |         y0 = 0; | ||||||
|     if (x1 > imOut->xsize) |     } | ||||||
|  |     if (x1 > imOut->xsize) { | ||||||
|         x1 = imOut->xsize; |         x1 = imOut->xsize; | ||||||
|     if (y1 > imOut->ysize) |     } | ||||||
|  |     if (y1 > imOut->ysize) { | ||||||
|         y1 = imOut->ysize; |         y1 = imOut->ysize; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     for (y = y0; y < y1; y++) { |     for (y = y0; y < y1; y++) { | ||||||
|         out = imOut->image[y] + x0*imOut->pixelsize; |         out = imOut->image[y] + x0*imOut->pixelsize; | ||||||
|         for (x = x0; x < x1; x++) { |         for (x = x0; x < x1; x++) { | ||||||
|             if ( ! transform(&xx, &yy, x-x0, y-y0, transform_data) || |             if ( ! transform(&xx, &yy, x-x0, y-y0, transform_data) || | ||||||
|                  ! filter(out, imIn, xx, yy)) { |                  ! filter(out, imIn, xx, yy)) { | ||||||
|                 if (fill) |                 if (fill) { | ||||||
|                     memset(out, 0, imOut->pixelsize); |                     memset(out, 0, imOut->pixelsize); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             out += imOut->pixelsize; |             out += imOut->pixelsize; | ||||||
|         } |         } | ||||||
|  | @ -801,19 +840,24 @@ ImagingScaleAffine(Imaging imOut, Imaging imIn, | ||||||
|     int xmin, xmax; |     int xmin, xmax; | ||||||
|     int *xintab; |     int *xintab; | ||||||
| 
 | 
 | ||||||
|     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) |     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, imIn); |     ImagingCopyPalette(imOut, imIn); | ||||||
| 
 | 
 | ||||||
|     if (x0 < 0) |     if (x0 < 0) { | ||||||
|         x0 = 0; |         x0 = 0; | ||||||
|     if (y0 < 0) |     } | ||||||
|  |     if (y0 < 0) { | ||||||
|         y0 = 0; |         y0 = 0; | ||||||
|     if (x1 > imOut->xsize) |     } | ||||||
|  |     if (x1 > imOut->xsize) { | ||||||
|         x1 = imOut->xsize; |         x1 = imOut->xsize; | ||||||
|     if (y1 > imOut->ysize) |     } | ||||||
|  |     if (y1 > imOut->ysize) { | ||||||
|         y1 = imOut->ysize; |         y1 = imOut->ysize; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* malloc check ok, uses calloc for overflow */ |     /* malloc check ok, uses calloc for overflow */ | ||||||
|     xintab = (int*) calloc(imOut->xsize, sizeof(int)); |     xintab = (int*) calloc(imOut->xsize, sizeof(int)); | ||||||
|  | @ -833,8 +877,9 @@ ImagingScaleAffine(Imaging imOut, Imaging imIn, | ||||||
|         xin = COORD(xo); |         xin = COORD(xo); | ||||||
|         if (xin >= 0 && xin < (int) imIn->xsize) { |         if (xin >= 0 && xin < (int) imIn->xsize) { | ||||||
|             xmax = x+1; |             xmax = x+1; | ||||||
|             if (x < xmin) |             if (x < xmin) { | ||||||
|                 xmin = x; |                 xmin = x; | ||||||
|  |             } | ||||||
|             xintab[x] = xin; |             xintab[x] = xin; | ||||||
|         } |         } | ||||||
|         xo += a[0]; |         xo += a[0]; | ||||||
|  | @ -845,12 +890,14 @@ ImagingScaleAffine(Imaging imOut, Imaging imIn, | ||||||
|         int yi = COORD(yo);\ |         int yi = COORD(yo);\ | ||||||
|         pixel *in, *out;\ |         pixel *in, *out;\ | ||||||
|         out = imOut->image[y];\ |         out = imOut->image[y];\ | ||||||
|         if (fill && x1 > x0)\ |         if (fill && x1 > x0) {\ | ||||||
|             memset(out+x0, 0, (x1-x0)*sizeof(pixel));\ |             memset(out+x0, 0, (x1-x0)*sizeof(pixel));\ | ||||||
|  |         }\ | ||||||
|         if (yi >= 0 && yi < imIn->ysize) {\ |         if (yi >= 0 && yi < imIn->ysize) {\ | ||||||
|             in = imIn->image[yi];\ |             in = imIn->image[yi];\ | ||||||
|             for (x = xmin; x < xmax; x++)\ |             for (x = xmin; x < xmax; x++) {\ | ||||||
|                 out[x] = in[xintab[x]];\ |                 out[x] = in[xintab[x]];\ | ||||||
|  |             }\ | ||||||
|         }\ |         }\ | ||||||
|         yo += a[4];\ |         yo += a[4];\ | ||||||
|     } |     } | ||||||
|  | @ -915,14 +962,16 @@ affine_fixed(Imaging imOut, Imaging imIn, | ||||||
|         xx = a2;\ |         xx = a2;\ | ||||||
|         yy = a5;\ |         yy = a5;\ | ||||||
|         out = imOut->image[y];\ |         out = imOut->image[y];\ | ||||||
|         if (fill && x1 > x0)\ |         if (fill && x1 > x0) {\ | ||||||
|             memset(out+x0, 0, (x1-x0)*sizeof(pixel));\ |             memset(out+x0, 0, (x1-x0)*sizeof(pixel));\ | ||||||
|  |         }\ | ||||||
|         for (x = x0; x < x1; x++, out++) {\ |         for (x = x0; x < x1; x++, out++) {\ | ||||||
|             xin = xx >> 16;\ |             xin = xx >> 16;\ | ||||||
|             if (xin >= 0 && xin < xsize) {\ |             if (xin >= 0 && xin < xsize) {\ | ||||||
|                 yin = yy >> 16;\ |                 yin = yy >> 16;\ | ||||||
|                 if (yin >= 0 && yin < ysize)\ |                 if (yin >= 0 && yin < ysize) {\ | ||||||
|                     *out = imIn->image[yin][xin];\ |                     *out = imIn->image[yin][xin];\ | ||||||
|  |                 }\ | ||||||
|             }\ |             }\ | ||||||
|             xx += a0;\ |             xx += a0;\ | ||||||
|             yy += a3;\ |             yy += a3;\ | ||||||
|  | @ -933,10 +982,11 @@ affine_fixed(Imaging imOut, Imaging imIn, | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
| 
 | 
 | ||||||
|     if (imIn->image8) |     if (imIn->image8) { | ||||||
|         AFFINE_TRANSFORM_FIXED(UINT8, image8) |         AFFINE_TRANSFORM_FIXED(UINT8, image8) | ||||||
|     else |     } else { | ||||||
|         AFFINE_TRANSFORM_FIXED(INT32, image32) |         AFFINE_TRANSFORM_FIXED(INT32, image32) | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingSectionLeave(&cookie); |     ImagingSectionLeave(&cookie); | ||||||
| 
 | 
 | ||||||
|  | @ -973,24 +1023,30 @@ ImagingTransformAffine(Imaging imOut, Imaging imIn, | ||||||
|         return ImagingScaleAffine(imOut, imIn, x0, y0, x1, y1, a, fill); |         return ImagingScaleAffine(imOut, imIn, x0, y0, x1, y1, a, fill); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) |     if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (x0 < 0) |     if (x0 < 0) { | ||||||
|         x0 = 0; |         x0 = 0; | ||||||
|     if (y0 < 0) |     } | ||||||
|  |     if (y0 < 0) { | ||||||
|         y0 = 0; |         y0 = 0; | ||||||
|     if (x1 > imOut->xsize) |     } | ||||||
|  |     if (x1 > imOut->xsize) { | ||||||
|         x1 = imOut->xsize; |         x1 = imOut->xsize; | ||||||
|     if (y1 > imOut->ysize) |     } | ||||||
|  |     if (y1 > imOut->ysize) { | ||||||
|         y1 = imOut->ysize; |         y1 = imOut->ysize; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* translate all four corners to check if they are within the
 |     /* translate all four corners to check if they are within the
 | ||||||
|        range that can be represented by the fixed point arithmetics */ |        range that can be represented by the fixed point arithmetics */ | ||||||
| 
 | 
 | ||||||
|     if (check_fixed(a, 0, 0) && check_fixed(a, x1-x0, y1-y0) && |     if (check_fixed(a, 0, 0) && check_fixed(a, x1-x0, y1-y0) && | ||||||
|         check_fixed(a, 0, y1-y0) && check_fixed(a, x1-x0, 0)) |         check_fixed(a, 0, y1-y0) && check_fixed(a, x1-x0, 0)) { | ||||||
|         return affine_fixed(imOut, imIn, x0, y0, x1, y1, a, filterid, fill); |         return affine_fixed(imOut, imIn, x0, y0, x1, y1, a, filterid, fill); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* FIXME: cannot really think of any reasonable case when the
 |     /* FIXME: cannot really think of any reasonable case when the
 | ||||||
|        following code is used.  maybe we should fall back on the slow |        following code is used.  maybe we should fall back on the slow | ||||||
|  | @ -1010,14 +1066,16 @@ ImagingTransformAffine(Imaging imOut, Imaging imIn, | ||||||
|         xx = xo;\ |         xx = xo;\ | ||||||
|         yy = yo;\ |         yy = yo;\ | ||||||
|         out = imOut->image[y];\ |         out = imOut->image[y];\ | ||||||
|         if (fill && x1 > x0)\ |         if (fill && x1 > x0) {\ | ||||||
|             memset(out+x0, 0, (x1-x0)*sizeof(pixel));\ |             memset(out+x0, 0, (x1-x0)*sizeof(pixel));\ | ||||||
|  |         }\ | ||||||
|         for (x = x0; x < x1; x++, out++) {\ |         for (x = x0; x < x1; x++, out++) {\ | ||||||
|             xin = COORD(xx);\ |             xin = COORD(xx);\ | ||||||
|             if (xin >= 0 && xin < xsize) {\ |             if (xin >= 0 && xin < xsize) {\ | ||||||
|                 yin = COORD(yy);\ |                 yin = COORD(yy);\ | ||||||
|                 if (yin >= 0 && yin < ysize)\ |                 if (yin >= 0 && yin < ysize) {\ | ||||||
|                     *out = imIn->image[yin][xin];\ |                     *out = imIn->image[yin][xin];\ | ||||||
|  |                 }\ | ||||||
|             }\ |             }\ | ||||||
|             xx += a[0];\ |             xx += a[0];\ | ||||||
|             yy += a[3];\ |             yy += a[3];\ | ||||||
|  | @ -1028,10 +1086,11 @@ ImagingTransformAffine(Imaging imOut, Imaging imIn, | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
| 
 | 
 | ||||||
|     if (imIn->image8) |     if (imIn->image8) { | ||||||
|         AFFINE_TRANSFORM(UINT8, image8) |         AFFINE_TRANSFORM(UINT8, image8) | ||||||
|     else |     } else { | ||||||
|         AFFINE_TRANSFORM(INT32, image32) |         AFFINE_TRANSFORM(INT32, image32) | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingSectionLeave(&cookie); |     ImagingSectionLeave(&cookie); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -36,17 +36,21 @@ ImagingGetBBox(Imaging im, int bbox[4]) | ||||||
| #define GETBBOX(image, mask)\ | #define GETBBOX(image, mask)\ | ||||||
|     for (y = 0; y < im->ysize; y++) {\ |     for (y = 0; y < im->ysize; y++) {\ | ||||||
|         has_data = 0;\ |         has_data = 0;\ | ||||||
|         for (x = 0; x < im->xsize; x++)\ |         for (x = 0; x < im->xsize; x++) {\ | ||||||
|             if (im->image[y][x] & mask) {\ |             if (im->image[y][x] & mask) {\ | ||||||
|                 has_data = 1;\ |                 has_data = 1;\ | ||||||
|                 if (x < bbox[0])\ |                 if (x < bbox[0]) {\ | ||||||
|                     bbox[0] = x;\ |                     bbox[0] = x;\ | ||||||
|                 if (x >= bbox[2])\ |                 }\ | ||||||
|  |                 if (x >= bbox[2]) {\ | ||||||
|                     bbox[2] = x+1;\ |                     bbox[2] = x+1;\ | ||||||
|  |                 }\ | ||||||
|             }\ |             }\ | ||||||
|  |         }\ | ||||||
|         if (has_data) {\ |         if (has_data) {\ | ||||||
|             if (bbox[1] < 0)\ |             if (bbox[1] < 0) {\ | ||||||
|             bbox[1] = y;\ |                 bbox[1] = y;\ | ||||||
|  |             }\ | ||||||
|             bbox[3] = y+1;\ |             bbox[3] = y+1;\ | ||||||
|         }\ |         }\ | ||||||
|     } |     } | ||||||
|  | @ -72,8 +76,9 @@ ImagingGetBBox(Imaging im, int bbox[4]) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Check that we got a box */ |     /* Check that we got a box */ | ||||||
|     if (bbox[1] < 0) |     if (bbox[1] < 0) { | ||||||
|         return 0; /* no data */ |         return 0; /* no data */ | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return 1; /* ok */ |     return 1; /* ok */ | ||||||
| } | } | ||||||
|  | @ -94,21 +99,24 @@ ImagingGetProjection(Imaging im, UINT8* xproj, UINT8* yproj) | ||||||
|     #define GETPROJ(image, mask)\ |     #define GETPROJ(image, mask)\ | ||||||
|         for (y = 0; y < im->ysize; y++) {\ |         for (y = 0; y < im->ysize; y++) {\ | ||||||
|             has_data = 0;\ |             has_data = 0;\ | ||||||
|             for (x = 0; x < im->xsize; x++)\ |             for (x = 0; x < im->xsize; x++) {\ | ||||||
|                 if (im->image[y][x] & mask) {\ |                 if (im->image[y][x] & mask) {\ | ||||||
|                     has_data = 1;\ |                     has_data = 1;\ | ||||||
|                     xproj[x] = 1;\ |                     xproj[x] = 1;\ | ||||||
|                 }\ |                 }\ | ||||||
|                 if (has_data)\ |             }\ | ||||||
|                     yproj[y] = 1;\ |             if (has_data) {\ | ||||||
|                 } |                 yproj[y] = 1;\ | ||||||
|  |             }\ | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     if (im->image8) { |     if (im->image8) { | ||||||
|         GETPROJ(image8, 0xff); |         GETPROJ(image8, 0xff); | ||||||
|     } else { |     } else { | ||||||
|         INT32 mask = 0xffffffff; |         INT32 mask = 0xffffffff; | ||||||
|         if (im->bands == 3) |         if (im->bands == 3) { | ||||||
|             ((UINT8*) &mask)[3] = 0; |             ((UINT8*) &mask)[3] = 0; | ||||||
|  |         } | ||||||
|         GETPROJ(image32, mask); |         GETPROJ(image32, mask); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -128,8 +136,9 @@ ImagingGetExtrema(Imaging im, void *extrema) | ||||||
|         return -1; /* mismatch */ |         return -1; /* mismatch */ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!im->xsize || !im->ysize) |     if (!im->xsize || !im->ysize) { | ||||||
|         return 0; /* zero size */ |         return 0; /* zero size */ | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     switch (im->type) { |     switch (im->type) { | ||||||
|     case IMAGING_TYPE_UINT8: |     case IMAGING_TYPE_UINT8: | ||||||
|  | @ -137,10 +146,11 @@ ImagingGetExtrema(Imaging im, void *extrema) | ||||||
|         for (y = 0; y < im->ysize; y++) { |         for (y = 0; y < im->ysize; y++) { | ||||||
|             UINT8* in = im->image8[y]; |             UINT8* in = im->image8[y]; | ||||||
|             for (x = 0; x < im->xsize; x++) { |             for (x = 0; x < im->xsize; x++) { | ||||||
|                 if (imin > in[x]) |                 if (imin > in[x]) { | ||||||
|                     imin = in[x]; |                     imin = in[x]; | ||||||
|                 else if (imax < in[x]) |                 } else if (imax < in[x]) { | ||||||
|                     imax = in[x]; |                     imax = in[x]; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         ((UINT8*) extrema)[0] = (UINT8) imin; |         ((UINT8*) extrema)[0] = (UINT8) imin; | ||||||
|  | @ -151,10 +161,11 @@ ImagingGetExtrema(Imaging im, void *extrema) | ||||||
|         for (y = 0; y < im->ysize; y++) { |         for (y = 0; y < im->ysize; y++) { | ||||||
|             INT32* in = im->image32[y]; |             INT32* in = im->image32[y]; | ||||||
|             for (x = 0; x < im->xsize; x++) { |             for (x = 0; x < im->xsize; x++) { | ||||||
|                 if (imin > in[x]) |                 if (imin > in[x]) { | ||||||
|                     imin = in[x]; |                     imin = in[x]; | ||||||
|                 else if (imax < in[x]) |                 } else if (imax < in[x]) { | ||||||
|                     imax = in[x]; |                     imax = in[x]; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         memcpy(extrema, &imin, sizeof(imin)); |         memcpy(extrema, &imin, sizeof(imin)); | ||||||
|  | @ -165,10 +176,11 @@ ImagingGetExtrema(Imaging im, void *extrema) | ||||||
|         for (y = 0; y < im->ysize; y++) { |         for (y = 0; y < im->ysize; y++) { | ||||||
|             FLOAT32* in = (FLOAT32*) im->image32[y]; |             FLOAT32* in = (FLOAT32*) im->image32[y]; | ||||||
|             for (x = 0; x < im->xsize; x++) { |             for (x = 0; x < im->xsize; x++) { | ||||||
|                 if (fmin > in[x]) |                 if (fmin > in[x]) { | ||||||
|                     fmin = in[x]; |                     fmin = in[x]; | ||||||
|                 else if (fmax < in[x]) |                 } else if (fmax < in[x]) { | ||||||
|                     fmax = in[x]; |                     fmax = in[x]; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         memcpy(extrema, &fmin, sizeof(fmin)); |         memcpy(extrema, &fmin, sizeof(fmin)); | ||||||
|  | @ -192,10 +204,11 @@ ImagingGetExtrema(Imaging im, void *extrema) | ||||||
| #else | #else | ||||||
|                   memcpy(&v, pixel, sizeof(v)); |                   memcpy(&v, pixel, sizeof(v)); | ||||||
| #endif | #endif | ||||||
|                   if (imin > v) |                   if (imin > v) { | ||||||
|                       imin = v; |                       imin = v; | ||||||
|                   else if (imax < v) |                   } else if (imax < v) { | ||||||
|                       imax = v; |                       imax = v; | ||||||
|  |                   } | ||||||
|               } |               } | ||||||
|           } |           } | ||||||
|           v = (UINT16) imin; |           v = (UINT16) imin; | ||||||
|  | @ -264,19 +277,23 @@ getcolors32(Imaging im, int maxcolors, int* size) | ||||||
|     /* printf("code_size=%d\n", code_size); */ |     /* printf("code_size=%d\n", code_size); */ | ||||||
|     /* printf("code_poly=%d\n", code_poly); */ |     /* printf("code_poly=%d\n", code_poly); */ | ||||||
| 
 | 
 | ||||||
|     if (!code_size) |     if (!code_size) { | ||||||
|         return ImagingError_MemoryError(); /* just give up */ |         return ImagingError_MemoryError(); /* just give up */ | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!im->image32) |     if (!im->image32) { | ||||||
|         return ImagingError_ModeError(); |         return ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     table = calloc(code_size + 1, sizeof(ImagingColorItem)); |     table = calloc(code_size + 1, sizeof(ImagingColorItem)); | ||||||
|     if (!table) |     if (!table) { | ||||||
|         return ImagingError_MemoryError(); |         return ImagingError_MemoryError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     pixel_mask = 0xffffffff; |     pixel_mask = 0xffffffff; | ||||||
|     if (im->bands == 3) |     if (im->bands == 3) { | ||||||
|         ((UINT8*) &pixel_mask)[3] = 0; |         ((UINT8*) &pixel_mask)[3] = 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     colors = 0; |     colors = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -289,8 +306,9 @@ getcolors32(Imaging im, int maxcolors, int* size) | ||||||
|             v = &table[i]; |             v = &table[i]; | ||||||
|             if (!v->count) { |             if (!v->count) { | ||||||
|                 /* add to table */ |                 /* add to table */ | ||||||
|                 if (colors++ == maxcolors) |                 if (colors++ == maxcolors) { | ||||||
|                     goto overflow; |                     goto overflow; | ||||||
|  |                 } | ||||||
|                 v->x = x; v->y = y; |                 v->x = x; v->y = y; | ||||||
|                 v->pixel = pixel; |                 v->pixel = pixel; | ||||||
|                 v->count = 1; |                 v->count = 1; | ||||||
|  | @ -300,15 +318,17 @@ getcolors32(Imaging im, int maxcolors, int* size) | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             incr = (h ^ (h >> 3)) & code_mask; |             incr = (h ^ (h >> 3)) & code_mask; | ||||||
|             if (!incr) |             if (!incr) { | ||||||
|                 incr = code_mask; |                 incr = code_mask; | ||||||
|  |             } | ||||||
|             for (;;) { |             for (;;) { | ||||||
|                 i = (i + incr) & code_mask; |                 i = (i + incr) & code_mask; | ||||||
|                 v = &table[i]; |                 v = &table[i]; | ||||||
|                 if (!v->count) { |                 if (!v->count) { | ||||||
|                     /* add to table */ |                     /* add to table */ | ||||||
|                     if (colors++ == maxcolors) |                     if (colors++ == maxcolors) { | ||||||
|                         goto overflow; |                         goto overflow; | ||||||
|  |                     } | ||||||
|                     v->x = x; v->y = y; |                     v->x = x; v->y = y; | ||||||
|                     v->pixel = pixel; |                     v->pixel = pixel; | ||||||
|                     v->count = 1; |                     v->count = 1; | ||||||
|  | @ -318,8 +338,9 @@ getcolors32(Imaging im, int maxcolors, int* size) | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 incr = incr << 1; |                 incr = incr << 1; | ||||||
|                 if (incr > code_mask) |                 if (incr > code_mask) { | ||||||
|                     incr = incr ^ code_poly; |                     incr = incr ^ code_poly; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -329,8 +350,9 @@ overflow: | ||||||
|     /* pack the table */ |     /* pack the table */ | ||||||
|     for (x = y = 0; x < (int) code_size; x++) |     for (x = y = 0; x < (int) code_size; x++) | ||||||
|         if (table[x].count) { |         if (table[x].count) { | ||||||
|             if (x != y) |             if (x != y) { | ||||||
|                 table[y] = table[x]; |                 table[y] = table[x]; | ||||||
|  |             } | ||||||
|             y++; |             y++; | ||||||
|         } |         } | ||||||
|     table[y].count = 0; /* mark end of table */ |     table[y].count = 0; /* mark end of table */ | ||||||
|  |  | ||||||
|  | @ -52,8 +52,9 @@ | ||||||
|             default:\ |             default:\ | ||||||
|                 return -1;\ |                 return -1;\ | ||||||
|         }\ |         }\ | ||||||
|     if (state->y < state->ysize)\ |     if (state->y < state->ysize) {\ | ||||||
|         out = im->image8[state->y + state->yoff] + state->xoff;\ |         out = im->image8[state->y + state->yoff] + state->xoff;\ | ||||||
|  |     }\ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -70,24 +71,25 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t | ||||||
| 
 | 
 | ||||||
|     if (!state->state) { |     if (!state->state) { | ||||||
| 
 | 
 | ||||||
|     /* Initialise state */ |         /* Initialise state */ | ||||||
|     if (context->bits < 0 || context->bits > 12) { |         if (context->bits < 0 || context->bits > 12) { | ||||||
|         state->errcode = IMAGING_CODEC_CONFIG; |             state->errcode = IMAGING_CODEC_CONFIG; | ||||||
|         return -1; |             return -1; | ||||||
|     } |         } | ||||||
| 
 | 
 | ||||||
|     /* Clear code */ |         /* Clear code */ | ||||||
|     context->clear = 1 << context->bits; |         context->clear = 1 << context->bits; | ||||||
| 
 | 
 | ||||||
|     /* End code */ |         /* End code */ | ||||||
|     context->end = context->clear + 1; |         context->end = context->clear + 1; | ||||||
| 
 | 
 | ||||||
|     /* Interlace */ |         /* Interlace */ | ||||||
|     if (context->interlace) { |         if (context->interlace) { | ||||||
|         context->interlace = 1; |             context->interlace = 1; | ||||||
|         context->step = context->repeat = 8; |             context->step = context->repeat = 8; | ||||||
|     } else |         } else { | ||||||
|         context->step = 1; |             context->step = 1; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         state->state = 1; |         state->state = 1; | ||||||
|     } |     } | ||||||
|  | @ -142,11 +144,13 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t | ||||||
|                     /* New GIF block */ |                     /* New GIF block */ | ||||||
| 
 | 
 | ||||||
|                     /* We don't start decoding unless we have a full block */ |                     /* We don't start decoding unless we have a full block */ | ||||||
|                     if (bytes < 1) |                     if (bytes < 1) { | ||||||
|                         return ptr - buffer; |                         return ptr - buffer; | ||||||
|  |                     } | ||||||
|                     c = *ptr; |                     c = *ptr; | ||||||
|                     if (bytes < c+1) |                     if (bytes < c+1) { | ||||||
|                         return ptr - buffer; |                         return ptr - buffer; | ||||||
|  |                     } | ||||||
| 
 | 
 | ||||||
|                     context->blocksize = c; |                     context->blocksize = c; | ||||||
| 
 | 
 | ||||||
|  | @ -167,13 +171,15 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t | ||||||
|                expanded. */ |                expanded. */ | ||||||
| 
 | 
 | ||||||
|             if (c == context->clear) { |             if (c == context->clear) { | ||||||
|                 if (state->state != 2) |                 if (state->state != 2) { | ||||||
|                     state->state = 1; |                     state->state = 1; | ||||||
|  |                 } | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (c == context->end) |             if (c == context->end) { | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             i = 1; |             i = 1; | ||||||
|             p = &context->lastdata; |             p = &context->lastdata; | ||||||
|  |  | ||||||
|  | @ -48,12 +48,14 @@ emit(GIFENCODERSTATE *context, int byte) | ||||||
|         /* add current block to end of flush queue */ |         /* add current block to end of flush queue */ | ||||||
|         if (context->block) { |         if (context->block) { | ||||||
|             block = context->flush; |             block = context->flush; | ||||||
|             while (block && block->next) |             while (block && block->next) { | ||||||
|                 block = block->next; |                 block = block->next; | ||||||
|             if (block) |             } | ||||||
|  |             if (block) { | ||||||
|                 block->next = context->block; |                 block->next = context->block; | ||||||
|             else |             } else { | ||||||
|                 context->flush = context->block; |                 context->flush = context->block; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /* get a new block */ |         /* get a new block */ | ||||||
|  | @ -63,8 +65,9 @@ emit(GIFENCODERSTATE *context, int byte) | ||||||
|         } else { |         } else { | ||||||
|             /* malloc check ok, small constant allocation */ |             /* malloc check ok, small constant allocation */ | ||||||
|             block = malloc(sizeof(GIFENCODERBLOCK)); |             block = malloc(sizeof(GIFENCODERBLOCK)); | ||||||
|             if (!block) |             if (!block) { | ||||||
|                 return 0; |                 return 0; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         block->size = 0; |         block->size = 0; | ||||||
|  | @ -154,14 +157,16 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|         if (context->interlace) { |         if (context->interlace) { | ||||||
|             context->interlace = 1; |             context->interlace = 1; | ||||||
|             context->step = 8; |             context->step = 8; | ||||||
|         } else |         } else { | ||||||
|             context->step = 1; |             context->step = 1; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         context->last = -1; |         context->last = -1; | ||||||
| 
 | 
 | ||||||
|         /* sanity check */ |         /* sanity check */ | ||||||
|         if (state->xsize <= 0 || state->ysize <= 0) |         if (state->xsize <= 0 || state->ysize <= 0) { | ||||||
|             state->state = ENCODE_EOF; |             state->state = ENCODE_EOF; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -231,9 +236,9 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
| 
 | 
 | ||||||
|                 this = state->buffer[state->x++]; |                 this = state->buffer[state->x++]; | ||||||
| 
 | 
 | ||||||
|                 if (this == context->last) |                 if (this == context->last) { | ||||||
|                     context->count++; |                     context->count++; | ||||||
|                 else { |                 } else { | ||||||
|                     EMIT_RUN(label1); |                     EMIT_RUN(label1); | ||||||
|                     context->last = this; |                     context->last = this; | ||||||
|                     context->count = 1; |                     context->count = 1; | ||||||
|  | @ -263,12 +268,14 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|                 if (context->block) { |                 if (context->block) { | ||||||
|                     GIFENCODERBLOCK* block; |                     GIFENCODERBLOCK* block; | ||||||
|                     block = context->flush; |                     block = context->flush; | ||||||
|                     while (block && block->next) |                     while (block && block->next) { | ||||||
|                         block = block->next; |                         block = block->next; | ||||||
|                     if (block) |                     } | ||||||
|  |                     if (block) { | ||||||
|                         block->next = context->block; |                         block->next = context->block; | ||||||
|                     else |                     } else { | ||||||
|                         context->flush = context->block; |                         context->flush = context->block; | ||||||
|  |                     } | ||||||
|                     context->block = NULL; |                     context->block = NULL; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  | @ -287,8 +294,9 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|                         if (block->size > 0) { |                         if (block->size > 0) { | ||||||
| 
 | 
 | ||||||
|                             /* make sure it fits into the output buffer */ |                             /* make sure it fits into the output buffer */ | ||||||
|                             if (bytes < block->size+1) |                             if (bytes < block->size+1) { | ||||||
|                                 return ptr - buf; |                                 return ptr - buf; | ||||||
|  |                             } | ||||||
| 
 | 
 | ||||||
|                             ptr[0] = block->size; |                             ptr[0] = block->size; | ||||||
|                             memcpy(ptr+1, block->data, block->size); |                             memcpy(ptr+1, block->data, block->size); | ||||||
|  | @ -300,16 +308,18 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
| 
 | 
 | ||||||
|                         context->flush = block->next; |                         context->flush = block->next; | ||||||
| 
 | 
 | ||||||
|                         if (context->free) |                         if (context->free) { | ||||||
|                             free(context->free); |                             free(context->free); | ||||||
|  |                         } | ||||||
|                         context->free = block; |                         context->free = block; | ||||||
| 
 | 
 | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     if (state->state == EXIT) { |                     if (state->state == EXIT) { | ||||||
|                         /* this was the last block! */ |                         /* this was the last block! */ | ||||||
|                         if (context->free) |                         if (context->free) { | ||||||
|                             free(context->free); |                             free(context->free); | ||||||
|  |                         } | ||||||
|                         state->errcode = IMAGING_CODEC_END; |                         state->errcode = IMAGING_CODEC_END; | ||||||
|                         return ptr - buf; |                         return ptr - buf; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|  | @ -30,8 +30,9 @@ ImagingHexDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
| 
 | 
 | ||||||
|     for (;;) { |     for (;;) { | ||||||
| 
 | 
 | ||||||
|         if (bytes < 2) |         if (bytes < 2) { | ||||||
|             return ptr - buf; |             return ptr - buf; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         a = HEX(ptr[0]); |         a = HEX(ptr[0]); | ||||||
|         b = HEX(ptr[1]); |         b = HEX(ptr[1]); | ||||||
|  |  | ||||||
|  | @ -29,8 +29,9 @@ | ||||||
| void | void | ||||||
| ImagingHistogramDelete(ImagingHistogram h) | ImagingHistogramDelete(ImagingHistogram h) | ||||||
| { | { | ||||||
|     if (h->histogram) |     if (h->histogram) { | ||||||
|         free(h->histogram); |         free(h->histogram); | ||||||
|  |     } | ||||||
|     free(h); |     free(h); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -59,15 +60,18 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax) | ||||||
|     INT32 imin, imax; |     INT32 imin, imax; | ||||||
|     FLOAT32 fmin, fmax, scale; |     FLOAT32 fmin, fmax, scale; | ||||||
| 
 | 
 | ||||||
|     if (!im) |     if (!im) { | ||||||
|         return ImagingError_ModeError(); |         return ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (imMask) { |     if (imMask) { | ||||||
|         /* Validate mask */ |         /* Validate mask */ | ||||||
|         if (im->xsize != imMask->xsize || im->ysize != imMask->ysize) |         if (im->xsize != imMask->xsize || im->ysize != imMask->ysize) { | ||||||
|             return ImagingError_Mismatch(); |             return ImagingError_Mismatch(); | ||||||
|         if (strcmp(imMask->mode, "1") != 0 && strcmp(imMask->mode, "L") != 0) |         } | ||||||
|  |         if (strcmp(imMask->mode, "1") != 0 && strcmp(imMask->mode, "L") != 0) { | ||||||
|             return ImagingError_ValueError("bad transparency mask"); |             return ImagingError_ValueError("bad transparency mask"); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     h = ImagingHistogramNew(im); |     h = ImagingHistogramNew(im); | ||||||
|  | @ -75,12 +79,15 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax) | ||||||
|     if (imMask) { |     if (imMask) { | ||||||
|         /* mask */ |         /* mask */ | ||||||
|         if (im->image8) { |         if (im->image8) { | ||||||
|                 ImagingSectionEnter(&cookie); |             ImagingSectionEnter(&cookie); | ||||||
|             for (y = 0; y < im->ysize; y++) |             for (y = 0; y < im->ysize; y++) { | ||||||
|                 for (x = 0; x < im->xsize; x++) |                 for (x = 0; x < im->xsize; x++) { | ||||||
|                     if (imMask->image8[y][x] != 0) |                     if (imMask->image8[y][x] != 0) { | ||||||
|                     h->histogram[im->image8[y][x]]++; |                         h->histogram[im->image8[y][x]]++; | ||||||
|                     ImagingSectionLeave(&cookie); |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             ImagingSectionLeave(&cookie); | ||||||
|         } else { /* yes, we need the braces. C isn't Python! */ |         } else { /* yes, we need the braces. C isn't Python! */ | ||||||
|             if (im->type != IMAGING_TYPE_UINT8) { |             if (im->type != IMAGING_TYPE_UINT8) { | ||||||
|                 ImagingHistogramDelete(h); |                 ImagingHistogramDelete(h); | ||||||
|  | @ -89,25 +96,29 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax) | ||||||
|             ImagingSectionEnter(&cookie); |             ImagingSectionEnter(&cookie); | ||||||
|             for (y = 0; y < im->ysize; y++) { |             for (y = 0; y < im->ysize; y++) { | ||||||
|                 UINT8* in = (UINT8*) im->image32[y]; |                 UINT8* in = (UINT8*) im->image32[y]; | ||||||
|                 for (x = 0; x < im->xsize; x++) |                 for (x = 0; x < im->xsize; x++) { | ||||||
|                     if (imMask->image8[y][x] != 0) { |                     if (imMask->image8[y][x] != 0) { | ||||||
|                         h->histogram[(*in++)]++; |                         h->histogram[(*in++)]++; | ||||||
|                         h->histogram[(*in++)+256]++; |                         h->histogram[(*in++)+256]++; | ||||||
|                         h->histogram[(*in++)+512]++; |                         h->histogram[(*in++)+512]++; | ||||||
|                         h->histogram[(*in++)+768]++; |                         h->histogram[(*in++)+768]++; | ||||||
|                     } else |                     } else { | ||||||
|                         in += 4; |                         in += 4; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             ImagingSectionLeave(&cookie); |             ImagingSectionLeave(&cookie); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         /* mask not given; process pixels in image */ |         /* mask not given; process pixels in image */ | ||||||
|         if (im->image8) { |         if (im->image8) { | ||||||
|                 ImagingSectionEnter(&cookie); |             ImagingSectionEnter(&cookie); | ||||||
|             for (y = 0; y < im->ysize; y++) |             for (y = 0; y < im->ysize; y++) { | ||||||
|                 for (x = 0; x < im->xsize; x++) |                 for (x = 0; x < im->xsize; x++) { | ||||||
|                     h->histogram[im->image8[y][x]]++; |                     h->histogram[im->image8[y][x]]++; | ||||||
|                     ImagingSectionLeave(&cookie); |                 } | ||||||
|  |             } | ||||||
|  |             ImagingSectionLeave(&cookie); | ||||||
|         } else { |         } else { | ||||||
|             switch (im->type) { |             switch (im->type) { | ||||||
|                 case IMAGING_TYPE_UINT8: |                 case IMAGING_TYPE_UINT8: | ||||||
|  | @ -128,20 +139,23 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax) | ||||||
|                         ImagingHistogramDelete(h); |                         ImagingHistogramDelete(h); | ||||||
|                         return ImagingError_ValueError("min/max not given"); |                         return ImagingError_ValueError("min/max not given"); | ||||||
|                     } |                     } | ||||||
|                     if (!im->xsize || !im->ysize) |                     if (!im->xsize || !im->ysize) { | ||||||
|                         break; |                         break; | ||||||
|  |                     } | ||||||
|                     memcpy(&imin, minmax, sizeof(imin)); |                     memcpy(&imin, minmax, sizeof(imin)); | ||||||
|                     memcpy(&imax, ((char*)minmax) + sizeof(imin), sizeof(imax)); |                     memcpy(&imax, ((char*)minmax) + sizeof(imin), sizeof(imax)); | ||||||
|                     if (imin >= imax) |                     if (imin >= imax) { | ||||||
|                         break; |                         break; | ||||||
|  |                     } | ||||||
|                     ImagingSectionEnter(&cookie); |                     ImagingSectionEnter(&cookie); | ||||||
|                     scale = 255.0F / (imax - imin); |                     scale = 255.0F / (imax - imin); | ||||||
|                     for (y = 0; y < im->ysize; y++) { |                     for (y = 0; y < im->ysize; y++) { | ||||||
|                         INT32* in = im->image32[y]; |                         INT32* in = im->image32[y]; | ||||||
|                         for (x = 0; x < im->xsize; x++) { |                         for (x = 0; x < im->xsize; x++) { | ||||||
|                             i = (int) (((*in++)-imin)*scale); |                             i = (int) (((*in++)-imin)*scale); | ||||||
|                             if (i >= 0 && i < 256) |                             if (i >= 0 && i < 256) { | ||||||
|                                 h->histogram[i]++; |                                 h->histogram[i]++; | ||||||
|  |                             } | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     ImagingSectionLeave(&cookie); |                     ImagingSectionLeave(&cookie); | ||||||
|  | @ -151,20 +165,23 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax) | ||||||
|                         ImagingHistogramDelete(h); |                         ImagingHistogramDelete(h); | ||||||
|                         return ImagingError_ValueError("min/max not given"); |                         return ImagingError_ValueError("min/max not given"); | ||||||
|                     } |                     } | ||||||
|                     if (!im->xsize || !im->ysize) |                     if (!im->xsize || !im->ysize) { | ||||||
|                         break; |                         break; | ||||||
|  |                     } | ||||||
|                     memcpy(&fmin, minmax, sizeof(fmin)); |                     memcpy(&fmin, minmax, sizeof(fmin)); | ||||||
|                     memcpy(&fmax, ((char*)minmax) + sizeof(fmin), sizeof(fmax)); |                     memcpy(&fmax, ((char*)minmax) + sizeof(fmin), sizeof(fmax)); | ||||||
|                     if (fmin >= fmax) |                     if (fmin >= fmax) { | ||||||
|                         break; |                         break; | ||||||
|  |                     } | ||||||
|                     ImagingSectionEnter(&cookie); |                     ImagingSectionEnter(&cookie); | ||||||
|                     scale = 255.0F / (fmax - fmin); |                     scale = 255.0F / (fmax - fmin); | ||||||
|                     for (y = 0; y < im->ysize; y++) { |                     for (y = 0; y < im->ysize; y++) { | ||||||
|                         FLOAT32* in = (FLOAT32*) im->image32[y]; |                         FLOAT32* in = (FLOAT32*) im->image32[y]; | ||||||
|                         for (x = 0; x < im->xsize; x++) { |                         for (x = 0; x < im->xsize; x++) { | ||||||
|                             i = (int) (((*in++)-fmin)*scale); |                             i = (int) (((*in++)-fmin)*scale); | ||||||
|                             if (i >= 0 && i < 256) |                             if (i >= 0 && i < 256) { | ||||||
|                                 h->histogram[i]++; |                                 h->histogram[i]++; | ||||||
|  |                             } | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     ImagingSectionLeave(&cookie); |                     ImagingSectionLeave(&cookie); | ||||||
|  |  | ||||||
|  | @ -84,10 +84,11 @@ struct j2k_decode_unpacker { | ||||||
| static inline | static inline | ||||||
| unsigned j2ku_shift(unsigned x, int n) | unsigned j2ku_shift(unsigned x, int n) | ||||||
| { | { | ||||||
|     if (n < 0) |     if (n < 0) { | ||||||
|         return x >> -n; |         return x >> -n; | ||||||
|     else |     } else { | ||||||
|         return x << n; |         return x << n; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -104,11 +105,13 @@ j2ku_gray_l(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
| 
 | 
 | ||||||
|     unsigned x, y; |     unsigned x, y; | ||||||
| 
 | 
 | ||||||
|     if (csiz == 3) |     if (csiz == 3) { | ||||||
|         csiz = 4; |         csiz = 4; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (shift < 0) |     if (shift < 0) { | ||||||
|         offset += 1 << (-shift - 1); |         offset += 1 << (-shift - 1); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* csiz*h*w + offset = tileinfo.datasize */ |     /* csiz*h*w + offset = tileinfo.datasize */ | ||||||
|     switch (csiz) { |     switch (csiz) { | ||||||
|  | @ -116,24 +119,27 @@ j2ku_gray_l(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
|         for (y = 0; y < h; ++y) { |         for (y = 0; y < h; ++y) { | ||||||
|             const UINT8 *data = &tiledata[y * w]; |             const UINT8 *data = &tiledata[y * w]; | ||||||
|             UINT8 *row = (UINT8 *)im->image[y0 + y] + x0; |             UINT8 *row = (UINT8 *)im->image[y0 + y] + x0; | ||||||
|             for (x = 0; x < w; ++x) |             for (x = 0; x < w; ++x) { | ||||||
|                 *row++ = j2ku_shift(offset + *data++, shift); |                 *row++ = j2ku_shift(offset + *data++, shift); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     case 2: |     case 2: | ||||||
|         for (y = 0; y < h; ++y) { |         for (y = 0; y < h; ++y) { | ||||||
|             const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w]; |             const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w]; | ||||||
|             UINT8 *row = (UINT8 *)im->image[y0 + y] + x0; |             UINT8 *row = (UINT8 *)im->image[y0 + y] + x0; | ||||||
|             for (x = 0; x < w; ++x) |             for (x = 0; x < w; ++x) { | ||||||
|                 *row++ = j2ku_shift(offset + *data++, shift); |                 *row++ = j2ku_shift(offset + *data++, shift); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     case 4: |     case 4: | ||||||
|         for (y = 0; y < h; ++y) { |         for (y = 0; y < h; ++y) { | ||||||
|             const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w]; |             const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w]; | ||||||
|             UINT8 *row = (UINT8 *)im->image[y0 + y] + x0; |             UINT8 *row = (UINT8 *)im->image[y0 + y] + x0; | ||||||
|             for (x = 0; x < w; ++x) |             for (x = 0; x < w; ++x) { | ||||||
|                 *row++ = j2ku_shift(offset + *data++, shift); |                 *row++ = j2ku_shift(offset + *data++, shift); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  | @ -154,35 +160,40 @@ j2ku_gray_i(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
| 
 | 
 | ||||||
|     unsigned x, y; |     unsigned x, y; | ||||||
| 
 | 
 | ||||||
|     if (csiz == 3) |     if (csiz == 3) { | ||||||
|         csiz = 4; |         csiz = 4; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (shift < 0) |     if (shift < 0) { | ||||||
|         offset += 1 << (-shift - 1); |         offset += 1 << (-shift - 1); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     switch (csiz) { |     switch (csiz) { | ||||||
|     case 1: |     case 1: | ||||||
|         for (y = 0; y < h; ++y) { |         for (y = 0; y < h; ++y) { | ||||||
|             const UINT8 *data = &tiledata[y * w]; |             const UINT8 *data = &tiledata[y * w]; | ||||||
|             UINT16 *row = (UINT16 *)im->image[y0 + y] + x0; |             UINT16 *row = (UINT16 *)im->image[y0 + y] + x0; | ||||||
|             for (x = 0; x < w; ++x) |             for (x = 0; x < w; ++x) { | ||||||
|                 *row++ = j2ku_shift(offset + *data++, shift); |                 *row++ = j2ku_shift(offset + *data++, shift); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     case 2: |     case 2: | ||||||
|         for (y = 0; y < h; ++y) { |         for (y = 0; y < h; ++y) { | ||||||
|             const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w]; |             const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w]; | ||||||
|             UINT16 *row = (UINT16 *)im->image[y0 + y] + x0; |             UINT16 *row = (UINT16 *)im->image[y0 + y] + x0; | ||||||
|             for (x = 0; x < w; ++x) |             for (x = 0; x < w; ++x) { | ||||||
|                 *row++ = j2ku_shift(offset + *data++, shift); |                 *row++ = j2ku_shift(offset + *data++, shift); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     case 4: |     case 4: | ||||||
|         for (y = 0; y < h; ++y) { |         for (y = 0; y < h; ++y) { | ||||||
|             const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w]; |             const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w]; | ||||||
|             UINT16 *row = (UINT16 *)im->image[y0 + y] + x0; |             UINT16 *row = (UINT16 *)im->image[y0 + y] + x0; | ||||||
|             for (x = 0; x < w; ++x) |             for (x = 0; x < w; ++x) { | ||||||
|                 *row++ = j2ku_shift(offset + *data++, shift); |                 *row++ = j2ku_shift(offset + *data++, shift); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  | @ -203,11 +214,13 @@ j2ku_gray_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
| 
 | 
 | ||||||
|     unsigned x, y; |     unsigned x, y; | ||||||
| 
 | 
 | ||||||
|     if (shift < 0) |     if (shift < 0) { | ||||||
|         offset += 1 << (-shift - 1); |         offset += 1 << (-shift - 1); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (csiz == 3) |     if (csiz == 3) { | ||||||
|         csiz = 4; |         csiz = 4; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     switch (csiz) { |     switch (csiz) { | ||||||
|     case 1: |     case 1: | ||||||
|  | @ -267,15 +280,19 @@ j2ku_graya_la(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
| 
 | 
 | ||||||
|     unsigned x, y; |     unsigned x, y; | ||||||
| 
 | 
 | ||||||
|     if (csiz == 3) |     if (csiz == 3) { | ||||||
|         csiz = 4; |         csiz = 4; | ||||||
|     if (acsiz == 3) |     } | ||||||
|  |     if (acsiz == 3) { | ||||||
|         acsiz = 4; |         acsiz = 4; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (shift < 0) |     if (shift < 0) { | ||||||
|         offset += 1 << (-shift - 1); |         offset += 1 << (-shift - 1); | ||||||
|     if (ashift < 0) |     } | ||||||
|  |     if (ashift < 0) { | ||||||
|         aoffset += 1 << (-ashift - 1); |         aoffset += 1 << (-ashift - 1); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     atiledata = tiledata + csiz * w * h; |     atiledata = tiledata + csiz * w * h; | ||||||
| 
 | 
 | ||||||
|  | @ -325,11 +342,13 @@ j2ku_srgb_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
|         offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0; |         offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0; | ||||||
|         csiz[n] = (in->comps[n].prec + 7) >> 3; |         csiz[n] = (in->comps[n].prec + 7) >> 3; | ||||||
| 
 | 
 | ||||||
|         if (csiz[n] == 3) |         if (csiz[n] == 3) { | ||||||
|             csiz[n] = 4; |             csiz[n] = 4; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (shifts[n] < 0) |         if (shifts[n] < 0) { | ||||||
|             offsets[n] += 1 << (-shifts[n] - 1); |             offsets[n] += 1 << (-shifts[n] - 1); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         cptr += csiz[n] * w * h; |         cptr += csiz[n] * w * h; | ||||||
|     } |     } | ||||||
|  | @ -337,8 +356,9 @@ j2ku_srgb_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
|     for (y = 0; y < h; ++y) { |     for (y = 0; y < h; ++y) { | ||||||
|         const UINT8 *data[3]; |         const UINT8 *data[3]; | ||||||
|         UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4; |         UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4; | ||||||
|         for (n = 0; n < 3; ++n) |         for (n = 0; n < 3; ++n) { | ||||||
|             data[n] = &cdata[n][csiz[n] * y * w]; |             data[n] = &cdata[n][csiz[n] * y * w]; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         for (x = 0; x < w; ++x) { |         for (x = 0; x < w; ++x) { | ||||||
|             for (n = 0; n < 3; ++n) { |             for (n = 0; n < 3; ++n) { | ||||||
|  | @ -377,11 +397,13 @@ j2ku_sycc_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
|         offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0; |         offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0; | ||||||
|         csiz[n] = (in->comps[n].prec + 7) >> 3; |         csiz[n] = (in->comps[n].prec + 7) >> 3; | ||||||
| 
 | 
 | ||||||
|         if (csiz[n] == 3) |         if (csiz[n] == 3) { | ||||||
|             csiz[n] = 4; |             csiz[n] = 4; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (shifts[n] < 0) |         if (shifts[n] < 0) { | ||||||
|             offsets[n] += 1 << (-shifts[n] - 1); |             offsets[n] += 1 << (-shifts[n] - 1); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         cptr += csiz[n] * w * h; |         cptr += csiz[n] * w * h; | ||||||
|     } |     } | ||||||
|  | @ -390,8 +412,9 @@ j2ku_sycc_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
|         const UINT8 *data[3]; |         const UINT8 *data[3]; | ||||||
|         UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4; |         UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4; | ||||||
|         UINT8 *row_start = row; |         UINT8 *row_start = row; | ||||||
|         for (n = 0; n < 3; ++n) |         for (n = 0; n < 3; ++n) { | ||||||
|             data[n] = &cdata[n][csiz[n] * y * w]; |             data[n] = &cdata[n][csiz[n] * y * w]; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         for (x = 0; x < w; ++x) { |         for (x = 0; x < w; ++x) { | ||||||
|             for (n = 0; n < 3; ++n) { |             for (n = 0; n < 3; ++n) { | ||||||
|  | @ -432,11 +455,13 @@ j2ku_srgba_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
|         offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0; |         offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0; | ||||||
|         csiz[n] = (in->comps[n].prec + 7) >> 3; |         csiz[n] = (in->comps[n].prec + 7) >> 3; | ||||||
| 
 | 
 | ||||||
|         if (csiz[n] == 3) |         if (csiz[n] == 3) { | ||||||
|             csiz[n] = 4; |             csiz[n] = 4; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (shifts[n] < 0) |         if (shifts[n] < 0) { | ||||||
|             offsets[n] += 1 << (-shifts[n] - 1); |             offsets[n] += 1 << (-shifts[n] - 1); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         cptr += csiz[n] * w * h; |         cptr += csiz[n] * w * h; | ||||||
|     } |     } | ||||||
|  | @ -444,8 +469,9 @@ j2ku_srgba_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
|     for (y = 0; y < h; ++y) { |     for (y = 0; y < h; ++y) { | ||||||
|         const UINT8 *data[4]; |         const UINT8 *data[4]; | ||||||
|         UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4; |         UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4; | ||||||
|         for (n = 0; n < 4; ++n) |         for (n = 0; n < 4; ++n) { | ||||||
|             data[n] = &cdata[n][csiz[n] * y * w]; |             data[n] = &cdata[n][csiz[n] * y * w]; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         for (x = 0; x < w; ++x) { |         for (x = 0; x < w; ++x) { | ||||||
|             for (n = 0; n < 4; ++n) { |             for (n = 0; n < 4; ++n) { | ||||||
|  | @ -483,11 +509,13 @@ j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
|         offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0; |         offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0; | ||||||
|         csiz[n] = (in->comps[n].prec + 7) >> 3; |         csiz[n] = (in->comps[n].prec + 7) >> 3; | ||||||
| 
 | 
 | ||||||
|         if (csiz[n] == 3) |         if (csiz[n] == 3) { | ||||||
|             csiz[n] = 4; |             csiz[n] = 4; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (shifts[n] < 0) |         if (shifts[n] < 0) { | ||||||
|             offsets[n] += 1 << (-shifts[n] - 1); |             offsets[n] += 1 << (-shifts[n] - 1); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         cptr += csiz[n] * w * h; |         cptr += csiz[n] * w * h; | ||||||
|     } |     } | ||||||
|  | @ -496,8 +524,9 @@ j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, | ||||||
|         const UINT8 *data[4]; |         const UINT8 *data[4]; | ||||||
|         UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4; |         UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4; | ||||||
|         UINT8 *row_start = row; |         UINT8 *row_start = row; | ||||||
|         for (n = 0; n < 4; ++n) |         for (n = 0; n < 4; ++n) { | ||||||
|             data[n] = &cdata[n][csiz[n] * y * w]; |             data[n] = &cdata[n][csiz[n] * y * w]; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         for (x = 0; x < w; ++x) { |         for (x = 0; x < w; ++x) { | ||||||
|             for (n = 0; n < 4; ++n) { |             for (n = 0; n < 4; ++n) { | ||||||
|  | @ -584,10 +613,11 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) | ||||||
|        possibly support is 4GB.  We can't go larger than this, because |        possibly support is 4GB.  We can't go larger than this, because | ||||||
|        OpenJPEG truncates this value for the final box in the file, and |        OpenJPEG truncates this value for the final box in the file, and | ||||||
|        the box lengths in OpenJPEG are currently 32 bit. */ |        the box lengths in OpenJPEG are currently 32 bit. */ | ||||||
|     if (context->length < 0) |     if (context->length < 0) { | ||||||
|         opj_stream_set_user_data_length(stream, 0xffffffff); |         opj_stream_set_user_data_length(stream, 0xffffffff); | ||||||
|     else |     } else { | ||||||
|         opj_stream_set_user_data_length(stream, context->length); |         opj_stream_set_user_data_length(stream, context->length); | ||||||
|  |     } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     /* Setup decompression context */ |     /* Setup decompression context */ | ||||||
|  | @ -696,8 +726,9 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) | ||||||
|             goto quick_exit; |             goto quick_exit; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!should_continue) |         if (!should_continue) { | ||||||
|             break; |             break; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         /* Adjust the tile co-ordinates based on the reduction (OpenJPEG
 |         /* Adjust the tile co-ordinates based on the reduction (OpenJPEG
 | ||||||
|            doesn't do this for us) */ |            doesn't do this for us) */ | ||||||
|  | @ -784,12 +815,15 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  quick_exit: |  quick_exit: | ||||||
|     if (codec) |     if (codec) { | ||||||
|         opj_destroy_codec(codec); |         opj_destroy_codec(codec); | ||||||
|     if (image) |     } | ||||||
|  |     if (image) { | ||||||
|         opj_image_destroy(image); |         opj_image_destroy(image); | ||||||
|     if (stream) |     } | ||||||
|  |     if (stream) { | ||||||
|         opj_stream_destroy(stream); |         opj_stream_destroy(stream); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
|  | @ -804,8 +838,9 @@ ImagingJpeg2KDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (state->state == J2K_STATE_DONE || state->state == J2K_STATE_FAILED) |     if (state->state == J2K_STATE_DONE || state->state == J2K_STATE_FAILED) { | ||||||
|         return -1; |         return -1; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (state->state == J2K_STATE_START) { |     if (state->state == J2K_STATE_START) { | ||||||
|         state->state = J2K_STATE_DECODING; |         state->state = J2K_STATE_DECODING; | ||||||
|  |  | ||||||
|  | @ -106,8 +106,9 @@ j2k_pack_l(Imaging im, UINT8 *buf, | ||||||
|     unsigned x,y; |     unsigned x,y; | ||||||
|     for (y = 0; y < h; ++y) { |     for (y = 0; y < h; ++y) { | ||||||
|         UINT8 *data = (UINT8 *)(im->image[y + y0] + x0); |         UINT8 *data = (UINT8 *)(im->image[y + y0] + x0); | ||||||
|         for (x = 0; x < w; ++x) |         for (x = 0; x < w; ++x) { | ||||||
|             *ptr++ = *data++; |             *ptr++ = *data++; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -240,8 +241,9 @@ j2k_set_cinema_params(Imaging im, int components, opj_cparameters_t *params) | ||||||
|             } else { |             } else { | ||||||
|                 rate = ((float)(components * im->xsize * im->ysize * 8) |                 rate = ((float)(components * im->xsize * im->ysize * 8) | ||||||
|                         / (params->tcp_rates[n] * 8)); |                         / (params->tcp_rates[n] * 8)); | ||||||
|                 if (rate > CINEMA_24_CS_LENGTH) |                 if (rate > CINEMA_24_CS_LENGTH) { | ||||||
|                     params->tcp_rates[n] = max_rate; |                     params->tcp_rates[n] = max_rate; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -257,8 +259,9 @@ j2k_set_cinema_params(Imaging im, int components, opj_cparameters_t *params) | ||||||
|             } else { |             } else { | ||||||
|                 rate = ((float)(components * im->xsize * im->ysize * 8) |                 rate = ((float)(components * im->xsize * im->ysize * 8) | ||||||
|                         / (params->tcp_rates[n] * 8)); |                         / (params->tcp_rates[n] * 8)); | ||||||
|                 if (rate > CINEMA_48_CS_LENGTH) |                 if (rate > CINEMA_48_CS_LENGTH) { | ||||||
|                     params->tcp_rates[n] = max_rate; |                     params->tcp_rates[n] = max_rate; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -397,8 +400,9 @@ j2k_encode_entry(Imaging im, ImagingCodecState state) | ||||||
|         float *pq; |         float *pq; | ||||||
| 
 | 
 | ||||||
|         if (len) { |         if (len) { | ||||||
|             if (len > sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0])) |             if (len > sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0])) { | ||||||
|                 len = sizeof(params.tcp_rates)/sizeof(params.tcp_rates[0]); |                 len = sizeof(params.tcp_rates)/sizeof(params.tcp_rates[0]); | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             params.tcp_numlayers = (int)len; |             params.tcp_numlayers = (int)len; | ||||||
| 
 | 
 | ||||||
|  | @ -423,8 +427,9 @@ j2k_encode_entry(Imaging im, ImagingCodecState state) | ||||||
|         params.cp_disto_alloc = 1; |         params.cp_disto_alloc = 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (context->num_resolutions) |     if (context->num_resolutions) { | ||||||
|         params.numresolution = context->num_resolutions; |         params.numresolution = context->num_resolutions; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (context->cblk_width >= 4 && context->cblk_width <= 1024 |     if (context->cblk_width >= 4 && context->cblk_width <= 1024 | ||||||
|         && context->cblk_height >= 4 && context->cblk_height <= 1024 |         && context->cblk_height >= 4 && context->cblk_height <= 1024 | ||||||
|  | @ -455,18 +460,21 @@ j2k_encode_entry(Imaging im, ImagingCodecState state) | ||||||
|     case OPJ_CINEMA2K_24: |     case OPJ_CINEMA2K_24: | ||||||
|     case OPJ_CINEMA2K_48: |     case OPJ_CINEMA2K_48: | ||||||
|         params.cp_rsiz = OPJ_CINEMA2K; |         params.cp_rsiz = OPJ_CINEMA2K; | ||||||
|         if (params.numresolution > 6) |         if (params.numresolution > 6) { | ||||||
|             params.numresolution = 6; |             params.numresolution = 6; | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
|     case OPJ_CINEMA4K_24: |     case OPJ_CINEMA4K_24: | ||||||
|         params.cp_rsiz = OPJ_CINEMA4K; |         params.cp_rsiz = OPJ_CINEMA4K; | ||||||
|         if (params.numresolution > 7) |         if (params.numresolution > 7) { | ||||||
|             params.numresolution = 7; |             params.numresolution = 7; | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (context->cinema_mode != OPJ_OFF) |     if (context->cinema_mode != OPJ_OFF) { | ||||||
|         j2k_set_cinema_params(im, components, ¶ms); |         j2k_set_cinema_params(im, components, ¶ms); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Set up the reference grid in the image */ |     /* Set up the reference grid in the image */ | ||||||
|     image->x0 = params.image_offset_x0; |     image->x0 = params.image_offset_x0; | ||||||
|  | @ -526,10 +534,12 @@ j2k_encode_entry(Imaging im, ImagingCodecState state) | ||||||
|         unsigned ty1 = ty0 + tile_height; |         unsigned ty1 = ty0 + tile_height; | ||||||
|         unsigned pixy, pixh; |         unsigned pixy, pixh; | ||||||
| 
 | 
 | ||||||
|         if (ty0 < params.image_offset_y0) |         if (ty0 < params.image_offset_y0) { | ||||||
|             ty0 = params.image_offset_y0; |             ty0 = params.image_offset_y0; | ||||||
|         if (ty1 > ysiz) |         } | ||||||
|  |         if (ty1 > ysiz) { | ||||||
|             ty1 = ysiz; |             ty1 = ysiz; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         pixy = ty0 - params.image_offset_y0; |         pixy = ty0 - params.image_offset_y0; | ||||||
|         pixh = ty1 - ty0; |         pixh = ty1 - ty0; | ||||||
|  | @ -540,10 +550,12 @@ j2k_encode_entry(Imaging im, ImagingCodecState state) | ||||||
|             unsigned pixx, pixw; |             unsigned pixx, pixw; | ||||||
|             unsigned data_size; |             unsigned data_size; | ||||||
| 
 | 
 | ||||||
|             if (tx0 < params.image_offset_x0) |             if (tx0 < params.image_offset_x0) { | ||||||
|                 tx0 = params.image_offset_x0; |                 tx0 = params.image_offset_x0; | ||||||
|             if (tx1 > xsiz) |             } | ||||||
|  |             if (tx1 > xsiz) { | ||||||
|                 tx1 = xsiz; |                 tx1 = xsiz; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             pixx = tx0 - params.image_offset_x0; |             pixx = tx0 - params.image_offset_x0; | ||||||
|             pixw = tx1 - tx0; |             pixw = tx1 - tx0; | ||||||
|  | @ -572,12 +584,15 @@ j2k_encode_entry(Imaging im, ImagingCodecState state) | ||||||
|     ret = -1; |     ret = -1; | ||||||
| 
 | 
 | ||||||
|  quick_exit: |  quick_exit: | ||||||
|     if (codec) |     if (codec) { | ||||||
|         opj_destroy_codec(codec); |         opj_destroy_codec(codec); | ||||||
|     if (image) |     } | ||||||
|  |     if (image) { | ||||||
|         opj_image_destroy(image); |         opj_image_destroy(image); | ||||||
|     if (stream) |     } | ||||||
|  |     if (stream) { | ||||||
|         opj_stream_destroy(stream); |         opj_stream_destroy(stream); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  | @ -585,8 +600,9 @@ j2k_encode_entry(Imaging im, ImagingCodecState state) | ||||||
| int | int | ||||||
| ImagingJpeg2KEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) | ImagingJpeg2KEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) | ||||||
| { | { | ||||||
|     if (state->state == J2K_STATE_FAILED) |     if (state->state == J2K_STATE_FAILED) { | ||||||
|         return -1; |         return -1; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (state->state == J2K_STATE_START) { |     if (state->state == J2K_STATE_START) { | ||||||
| 
 | 
 | ||||||
|  | @ -611,8 +627,9 @@ ImagingJpeg2KEncodeCleanup(ImagingCodecState state) { | ||||||
|         context->quality_layers = NULL; |         context->quality_layers = NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (context->error_msg) |     if (context->error_msg) { | ||||||
|         free ((void *)context->error_msg); |         free ((void *)context->error_msg); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     context->error_msg = NULL; |     context->error_msg = NULL; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -176,8 +176,9 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t by | ||||||
| 
 | 
 | ||||||
|     if (context->source.skip > 0) { |     if (context->source.skip > 0) { | ||||||
|         skip_input_data(&context->cinfo, context->source.skip); |         skip_input_data(&context->cinfo, context->source.skip); | ||||||
|         if (context->source.skip > 0) |         if (context->source.skip > 0) { | ||||||
|             return context->source.pub.next_input_byte - buf; |             return context->source.pub.next_input_byte - buf; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     switch (state->state) { |     switch (state->state) { | ||||||
|  | @ -193,43 +194,46 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t by | ||||||
| 
 | 
 | ||||||
|         } while (ok == JPEG_HEADER_TABLES_ONLY); |         } while (ok == JPEG_HEADER_TABLES_ONLY); | ||||||
| 
 | 
 | ||||||
|         if (ok == JPEG_SUSPENDED) |         if (ok == JPEG_SUSPENDED) { | ||||||
|             break; |             break; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         /* Decoder settings */ |         /* Decoder settings */ | ||||||
| 
 | 
 | ||||||
|         /* jpegmode indicates whats in the file; if not set, we'll
 |         /* jpegmode indicates whats in the file; if not set, we'll
 | ||||||
|            trust the decoder */ |            trust the decoder */ | ||||||
|         if (strcmp(context->jpegmode, "L") == 0) |         if (strcmp(context->jpegmode, "L") == 0) { | ||||||
|             context->cinfo.jpeg_color_space = JCS_GRAYSCALE; |             context->cinfo.jpeg_color_space = JCS_GRAYSCALE; | ||||||
|         else if (strcmp(context->jpegmode, "RGB") == 0) |         } else if (strcmp(context->jpegmode, "RGB") == 0) { | ||||||
|             context->cinfo.jpeg_color_space = JCS_RGB; |             context->cinfo.jpeg_color_space = JCS_RGB; | ||||||
|         else if (strcmp(context->jpegmode, "CMYK") == 0) |         } else if (strcmp(context->jpegmode, "CMYK") == 0) { | ||||||
|             context->cinfo.jpeg_color_space = JCS_CMYK; |             context->cinfo.jpeg_color_space = JCS_CMYK; | ||||||
|         else if (strcmp(context->jpegmode, "YCbCr") == 0) |         } else if (strcmp(context->jpegmode, "YCbCr") == 0) { | ||||||
|             context->cinfo.jpeg_color_space = JCS_YCbCr; |             context->cinfo.jpeg_color_space = JCS_YCbCr; | ||||||
|         else if (strcmp(context->jpegmode, "YCbCrK") == 0) { |         } else if (strcmp(context->jpegmode, "YCbCrK") == 0) { | ||||||
|             context->cinfo.jpeg_color_space = JCS_YCCK; |             context->cinfo.jpeg_color_space = JCS_YCCK; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /* rawmode indicates what we want from the decoder.  if not
 |         /* rawmode indicates what we want from the decoder.  if not
 | ||||||
|            set, conversions are disabled */ |            set, conversions are disabled */ | ||||||
|         if (strcmp(context->rawmode, "L") == 0) |         if (strcmp(context->rawmode, "L") == 0) { | ||||||
|             context->cinfo.out_color_space = JCS_GRAYSCALE; |             context->cinfo.out_color_space = JCS_GRAYSCALE; | ||||||
|         else if (strcmp(context->rawmode, "RGB") == 0) |         } else if (strcmp(context->rawmode, "RGB") == 0) { | ||||||
|             context->cinfo.out_color_space = JCS_RGB; |             context->cinfo.out_color_space = JCS_RGB; | ||||||
|  |         } | ||||||
|     #ifdef JCS_EXTENSIONS |     #ifdef JCS_EXTENSIONS | ||||||
|         else if (strcmp(context->rawmode, "RGBX") == 0) |         else if (strcmp(context->rawmode, "RGBX") == 0) { | ||||||
|                 context->cinfo.out_color_space = JCS_EXT_RGBX; |                 context->cinfo.out_color_space = JCS_EXT_RGBX; | ||||||
|  |         } | ||||||
|     #endif |     #endif | ||||||
|         else if (strcmp(context->rawmode, "CMYK") == 0 || |         else if (strcmp(context->rawmode, "CMYK") == 0 || | ||||||
|                  strcmp(context->rawmode, "CMYK;I") == 0) |                  strcmp(context->rawmode, "CMYK;I") == 0) { | ||||||
|             context->cinfo.out_color_space = JCS_CMYK; |             context->cinfo.out_color_space = JCS_CMYK; | ||||||
|         else if (strcmp(context->rawmode, "YCbCr") == 0) |         } else if (strcmp(context->rawmode, "YCbCr") == 0) { | ||||||
|             context->cinfo.out_color_space = JCS_YCbCr; |             context->cinfo.out_color_space = JCS_YCbCr; | ||||||
|         else if (strcmp(context->rawmode, "YCbCrK") == 0) |         } else if (strcmp(context->rawmode, "YCbCrK") == 0) { | ||||||
|             context->cinfo.out_color_space = JCS_YCCK; |             context->cinfo.out_color_space = JCS_YCCK; | ||||||
|         else { |         } else { | ||||||
|             /* Disable decoder conversions */ |             /* Disable decoder conversions */ | ||||||
|             context->cinfo.jpeg_color_space = JCS_UNKNOWN; |             context->cinfo.jpeg_color_space = JCS_UNKNOWN; | ||||||
|             context->cinfo.out_color_space = JCS_UNKNOWN; |             context->cinfo.out_color_space = JCS_UNKNOWN; | ||||||
|  | @ -251,8 +255,9 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t by | ||||||
| 
 | 
 | ||||||
|         /* Set things up for decompression (this processes the entire
 |         /* Set things up for decompression (this processes the entire
 | ||||||
|            file if necessary to return data line by line) */ |            file if necessary to return data line by line) */ | ||||||
|         if (!jpeg_start_decompress(&context->cinfo)) |         if (!jpeg_start_decompress(&context->cinfo)) { | ||||||
|             break; |             break; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         state->state++; |         state->state++; | ||||||
|         /* fall through */ |         /* fall through */ | ||||||
|  | @ -263,15 +268,17 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t by | ||||||
|         ok = 1; |         ok = 1; | ||||||
|         while (state->y < state->ysize) { |         while (state->y < state->ysize) { | ||||||
|             ok = jpeg_read_scanlines(&context->cinfo, &state->buffer, 1); |             ok = jpeg_read_scanlines(&context->cinfo, &state->buffer, 1); | ||||||
|             if (ok != 1) |             if (ok != 1) { | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
|             state->shuffle((UINT8*) im->image[state->y + state->yoff] + |             state->shuffle((UINT8*) im->image[state->y + state->yoff] + | ||||||
|                            state->xoff * im->pixelsize, state->buffer, |                            state->xoff * im->pixelsize, state->buffer, | ||||||
|                            state->xsize); |                            state->xsize); | ||||||
|             state->y++; |             state->y++; | ||||||
|         } |         } | ||||||
|         if (ok != 1) |         if (ok != 1) { | ||||||
|             break; |             break; | ||||||
|  |         } | ||||||
|         state->state++; |         state->state++; | ||||||
|         /* fall through */ |         /* fall through */ | ||||||
| 
 | 
 | ||||||
|  | @ -280,8 +287,9 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t by | ||||||
|         /* Finish decompression */ |         /* Finish decompression */ | ||||||
|         if (!jpeg_finish_decompress(&context->cinfo)) { |         if (!jpeg_finish_decompress(&context->cinfo)) { | ||||||
|             /* FIXME: add strictness mode test */ |             /* FIXME: add strictness mode test */ | ||||||
|             if (state->y < state->ysize) |             if (state->y < state->ysize) { | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /* Clean up */ |         /* Clean up */ | ||||||
|  |  | ||||||
|  | @ -127,17 +127,19 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|                     break; |                     break; | ||||||
|                 case 24: |                 case 24: | ||||||
|                     context->cinfo.input_components = 3; |                     context->cinfo.input_components = 3; | ||||||
|                     if (strcmp(im->mode, "YCbCr") == 0) |                     if (strcmp(im->mode, "YCbCr") == 0) { | ||||||
|                         context->cinfo.in_color_space = JCS_YCbCr; |                         context->cinfo.in_color_space = JCS_YCbCr; | ||||||
|                     else |                     } else { | ||||||
|                         context->cinfo.in_color_space = JCS_RGB; |                         context->cinfo.in_color_space = JCS_RGB; | ||||||
|  |                     } | ||||||
|                     break; |                     break; | ||||||
|                 case 32: |                 case 32: | ||||||
|                     context->cinfo.input_components = 4; |                     context->cinfo.input_components = 4; | ||||||
|                     context->cinfo.in_color_space = JCS_CMYK; |                     context->cinfo.in_color_space = JCS_CMYK; | ||||||
|                 #ifdef JCS_EXTENSIONS |                 #ifdef JCS_EXTENSIONS | ||||||
|                     if (strcmp(context->rawmode, "RGBX") == 0) |                     if (strcmp(context->rawmode, "RGBX") == 0) { | ||||||
|                         context->cinfo.in_color_space = JCS_EXT_RGBX; |                         context->cinfo.in_color_space = JCS_EXT_RGBX; | ||||||
|  |                     } | ||||||
|                 #endif |                 #endif | ||||||
|                     break; |                     break; | ||||||
|                 default: |                 default: | ||||||
|  | @ -214,8 +216,9 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 } |                 } | ||||||
|             if (context->progressive) |                 if (context->progressive) { | ||||||
|                 jpeg_simple_progression(&context->cinfo); |                     jpeg_simple_progression(&context->cinfo); | ||||||
|  |                 } | ||||||
|                 context->cinfo.smoothing_factor = context->smooth; |                 context->cinfo.smoothing_factor = context->smooth; | ||||||
|                 context->cinfo.optimize_coding = (boolean) context->optimize; |                 context->cinfo.optimize_coding = (boolean) context->optimize; | ||||||
|                 if (context->xdpi > 0 && context->ydpi > 0) { |                 if (context->xdpi > 0 && context->ydpi > 0) { | ||||||
|  | @ -261,19 +264,22 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|             if (context->extra) { |             if (context->extra) { | ||||||
|                 /* copy extra buffer to output buffer */ |                 /* copy extra buffer to output buffer */ | ||||||
|                 unsigned int n = context->extra_size - context->extra_offset; |                 unsigned int n = context->extra_size - context->extra_offset; | ||||||
|                 if (n > context->destination.pub.free_in_buffer) |                 if (n > context->destination.pub.free_in_buffer) { | ||||||
|                     n = context->destination.pub.free_in_buffer; |                     n = context->destination.pub.free_in_buffer; | ||||||
|  |                 } | ||||||
|                 memcpy(context->destination.pub.next_output_byte, |                 memcpy(context->destination.pub.next_output_byte, | ||||||
|                        context->extra + context->extra_offset, n); |                        context->extra + context->extra_offset, n); | ||||||
|                 context->destination.pub.next_output_byte += n; |                 context->destination.pub.next_output_byte += n; | ||||||
|                 context->destination.pub.free_in_buffer -= n; |                 context->destination.pub.free_in_buffer -= n; | ||||||
|                 context->extra_offset += n; |                 context->extra_offset += n; | ||||||
|                 if (context->extra_offset >= context->extra_size) |                 if (context->extra_offset >= context->extra_size) { | ||||||
|                     state->state++; |                     state->state++; | ||||||
|                 else |                 } else { | ||||||
|                     break; |                     break; | ||||||
|             } else |                 } | ||||||
|  |             } else { | ||||||
|                 state->state++; |                 state->state++; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|         case 4: |         case 4: | ||||||
|             if (1024 > context->destination.pub.free_in_buffer){ |             if (1024 > context->destination.pub.free_in_buffer){ | ||||||
|  | @ -286,21 +292,24 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|                        (UINT8*) im->image[state->y + state->yoff] + |                        (UINT8*) im->image[state->y + state->yoff] + | ||||||
|                        state->xoff * im->pixelsize, state->xsize); |                        state->xoff * im->pixelsize, state->xsize); | ||||||
|                 ok = jpeg_write_scanlines(&context->cinfo, &state->buffer, 1); |                 ok = jpeg_write_scanlines(&context->cinfo, &state->buffer, 1); | ||||||
|                 if (ok != 1) |                 if (ok != 1) { | ||||||
|                     break; |                     break; | ||||||
|  |                 } | ||||||
|                 state->y++; |                 state->y++; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (ok != 1) |             if (ok != 1) { | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
|             state->state++; |             state->state++; | ||||||
|             /* fall through */ |             /* fall through */ | ||||||
| 
 | 
 | ||||||
|         case 5: |         case 5: | ||||||
| 
 | 
 | ||||||
|             /* Finish compression */ |             /* Finish compression */ | ||||||
|             if (context->destination.pub.free_in_buffer < 100) |             if (context->destination.pub.free_in_buffer < 100) { | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
|             jpeg_finish_compress(&context->cinfo); |             jpeg_finish_compress(&context->cinfo); | ||||||
| 
 | 
 | ||||||
|             /* Clean up */ |             /* Clean up */ | ||||||
|  |  | ||||||
|  | @ -27,14 +27,16 @@ ImagingConvertMatrix(Imaging im, const char *mode, float m[]) | ||||||
|     int x, y; |     int x, y; | ||||||
| 
 | 
 | ||||||
|     /* Assume there's enough data in the buffer */ |     /* Assume there's enough data in the buffer */ | ||||||
|     if (!im) |     if (!im) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (strcmp(mode, "L") == 0 && im->bands == 3) { |     if (strcmp(mode, "L") == 0 && im->bands == 3) { | ||||||
| 
 | 
 | ||||||
|         imOut = ImagingNewDirty("L", im->xsize, im->ysize); |         imOut = ImagingNewDirty("L", im->xsize, im->ysize); | ||||||
|         if (!imOut) |         if (!imOut) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         for (y = 0; y < im->ysize; y++) { |         for (y = 0; y < im->ysize; y++) { | ||||||
|             UINT8* in = (UINT8*) im->image[y]; |             UINT8* in = (UINT8*) im->image[y]; | ||||||
|  | @ -50,8 +52,9 @@ ImagingConvertMatrix(Imaging im, const char *mode, float m[]) | ||||||
|     } else if (strlen(mode) == 3 && im->bands == 3) { |     } else if (strlen(mode) == 3 && im->bands == 3) { | ||||||
| 
 | 
 | ||||||
|         imOut = ImagingNewDirty(mode, im->xsize, im->ysize); |         imOut = ImagingNewDirty(mode, im->xsize, im->ysize); | ||||||
|         if (!imOut) |         if (!imOut) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         for (y = 0; y < im->ysize; y++) { |         for (y = 0; y < im->ysize; y++) { | ||||||
|             UINT8* in = (UINT8*) im->image[y]; |             UINT8* in = (UINT8*) im->image[y]; | ||||||
|  | @ -67,8 +70,9 @@ ImagingConvertMatrix(Imaging im, const char *mode, float m[]) | ||||||
|                 in += 4; out += 4; |                 in += 4; out += 4; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } else |     } else { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return imOut; |     return imOut; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -25,12 +25,14 @@ ImagingModeFilter(Imaging im, int size) | ||||||
|     UINT8 maxpixel; |     UINT8 maxpixel; | ||||||
|     int histogram[256]; |     int histogram[256]; | ||||||
| 
 | 
 | ||||||
|     if (!im || im->bands != 1 || im->type != IMAGING_TYPE_UINT8) |     if (!im || im->bands != 1 || im->type != IMAGING_TYPE_UINT8) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); |     imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     size = size / 2; |     size = size / 2; | ||||||
| 
 | 
 | ||||||
|  | @ -46,27 +48,32 @@ ImagingModeFilter(Imaging im, int size) | ||||||
|                the added complexity... */ |                the added complexity... */ | ||||||
| 
 | 
 | ||||||
|             memset(histogram, 0, sizeof(histogram)); |             memset(histogram, 0, sizeof(histogram)); | ||||||
|             for (yy = y - size; yy <= y + size; yy++) |             for (yy = y - size; yy <= y + size; yy++) { | ||||||
|                 if (yy >= 0 && yy < imOut->ysize) { |                 if (yy >= 0 && yy < imOut->ysize) { | ||||||
|                     UINT8* in = &IMAGING_PIXEL_L(im, 0, yy); |                     UINT8* in = &IMAGING_PIXEL_L(im, 0, yy); | ||||||
|                     for (xx = x - size; xx <= x + size; xx++) |                     for (xx = x - size; xx <= x + size; xx++) { | ||||||
|                         if (xx >= 0 && xx < imOut->xsize) |                         if (xx >= 0 && xx < imOut->xsize) { | ||||||
|                             histogram[in[xx]]++; |                             histogram[in[xx]]++; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             /* find most frequent pixel value in this region */ |             /* find most frequent pixel value in this region */ | ||||||
|             maxpixel = 0; |             maxpixel = 0; | ||||||
|             maxcount = histogram[maxpixel]; |             maxcount = histogram[maxpixel]; | ||||||
|             for (i = 1; i < 256; i++) |             for (i = 1; i < 256; i++) { | ||||||
|                 if (histogram[i] > maxcount) { |                 if (histogram[i] > maxcount) { | ||||||
|                     maxcount = histogram[i]; |                     maxcount = histogram[i]; | ||||||
|                     maxpixel = (UINT8) i; |                     maxpixel = (UINT8) i; | ||||||
|                 } |                 } | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             if (maxcount > 2) |             if (maxcount > 2) { | ||||||
|                 out[x] = maxpixel; |                 out[x] = maxpixel; | ||||||
|             else |             } else { | ||||||
|                 out[x] = IMAGING_PIXEL_L(im, x, y); |                 out[x] = IMAGING_PIXEL_L(im, x, y); | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -26,16 +26,20 @@ ImagingNegative(Imaging im) | ||||||
|     Imaging imOut; |     Imaging imOut; | ||||||
|     int x, y; |     int x, y; | ||||||
| 
 | 
 | ||||||
|     if (!im) |     if (!im) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); |     imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     for (y = 0; y < im->ysize; y++) |     for (y = 0; y < im->ysize; y++) { | ||||||
|         for (x = 0; x < im->linesize; x++) |         for (x = 0; x < im->linesize; x++) { | ||||||
|             imOut->image[y][x] = ~im->image[y][x]; |             imOut->image[y][x] = ~im->image[y][x]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return imOut; |     return imOut; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,38 +24,44 @@ ImagingOffset(Imaging im, int xoffset, int yoffset) | ||||||
|     int x, y; |     int x, y; | ||||||
|     Imaging imOut; |     Imaging imOut; | ||||||
| 
 | 
 | ||||||
|     if (!im) |     if (!im) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); |     imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, im); |     ImagingCopyPalette(imOut, im); | ||||||
| 
 | 
 | ||||||
|     /* make offsets positive to avoid negative coordinates */ |     /* make offsets positive to avoid negative coordinates */ | ||||||
|     xoffset %= im->xsize; |     xoffset %= im->xsize; | ||||||
|     xoffset = im->xsize - xoffset; |     xoffset = im->xsize - xoffset; | ||||||
|     if (xoffset < 0) |     if (xoffset < 0) { | ||||||
|         xoffset += im->xsize; |         xoffset += im->xsize; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     yoffset %= im->ysize; |     yoffset %= im->ysize; | ||||||
|     yoffset = im->ysize - yoffset; |     yoffset = im->ysize - yoffset; | ||||||
|     if (yoffset < 0) |     if (yoffset < 0) { | ||||||
|         yoffset += im->ysize; |         yoffset += im->ysize; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
| #define OFFSET(image)\ | #define OFFSET(image)\ | ||||||
|     for (y = 0; y < im->ysize; y++)\ |     for (y = 0; y < im->ysize; y++) {\ | ||||||
|         for (x = 0; x < im->xsize; x++) {\ |         for (x = 0; x < im->xsize; x++) {\ | ||||||
|             int yi = (y + yoffset) % im->ysize;\ |             int yi = (y + yoffset) % im->ysize;\ | ||||||
|             int xi = (x + xoffset) % im->xsize;\ |             int xi = (x + xoffset) % im->xsize;\ | ||||||
|             imOut->image[y][x] = im->image[yi][xi];\ |             imOut->image[y][x] = im->image[yi][xi];\ | ||||||
|  |         }\ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (im->image8) |     if (im->image8) { | ||||||
|         OFFSET(image8) |         OFFSET(image8) | ||||||
|     else |     } else { | ||||||
|         OFFSET(image32) |         OFFSET(image32) | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return imOut; |     return imOut; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -80,16 +80,18 @@ pack1(UINT8* out, const UINT8* in, int pixels) | ||||||
|     /* bilevel (black is 0) */ |     /* bilevel (black is 0) */ | ||||||
|     b = 0; m = 128; |     b = 0; m = 128; | ||||||
|     for (i = 0; i < pixels; i++) { |     for (i = 0; i < pixels; i++) { | ||||||
|         if (in[i] != 0) |         if (in[i] != 0) { | ||||||
|             b |= m; |             b |= m; | ||||||
|  |         } | ||||||
|         m >>= 1; |         m >>= 1; | ||||||
|         if (m == 0) { |         if (m == 0) { | ||||||
|             *out++ = b; |             *out++ = b; | ||||||
|             b = 0; m = 128; |             b = 0; m = 128; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if (m != 128) |     if (m != 128) { | ||||||
|         *out++ = b; |         *out++ = b; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -99,16 +101,18 @@ pack1I(UINT8* out, const UINT8* in, int pixels) | ||||||
|     /* bilevel (black is 1) */ |     /* bilevel (black is 1) */ | ||||||
|     b = 0; m = 128; |     b = 0; m = 128; | ||||||
|     for (i = 0; i < pixels; i++) { |     for (i = 0; i < pixels; i++) { | ||||||
|         if (in[i] == 0) |         if (in[i] == 0) { | ||||||
|             b |= m; |             b |= m; | ||||||
|  |         } | ||||||
|         m >>= 1; |         m >>= 1; | ||||||
|         if (m == 0) { |         if (m == 0) { | ||||||
|             *out++ = b; |             *out++ = b; | ||||||
|             b = 0; m = 128; |             b = 0; m = 128; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if (m != 128) |     if (m != 128) { | ||||||
|         *out++ = b; |         *out++ = b; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -118,16 +122,18 @@ pack1R(UINT8* out, const UINT8* in, int pixels) | ||||||
|     /* bilevel, lsb first (black is 0) */ |     /* bilevel, lsb first (black is 0) */ | ||||||
|     b = 0; m = 1; |     b = 0; m = 1; | ||||||
|     for (i = 0; i < pixels; i++) { |     for (i = 0; i < pixels; i++) { | ||||||
|         if (in[i] != 0) |         if (in[i] != 0) { | ||||||
|             b |= m; |             b |= m; | ||||||
|  |         } | ||||||
|         m <<= 1; |         m <<= 1; | ||||||
|         if (m == 256){ |         if (m == 256){ | ||||||
|             *out++ = b; |             *out++ = b; | ||||||
|             b = 0; m = 1; |             b = 0; m = 1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if (m != 1) |     if (m != 1) { | ||||||
|         *out++ = b; |         *out++ = b; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -137,16 +143,18 @@ pack1IR(UINT8* out, const UINT8* in, int pixels) | ||||||
|     /* bilevel, lsb first (black is 1) */ |     /* bilevel, lsb first (black is 1) */ | ||||||
|     b = 0; m = 1; |     b = 0; m = 1; | ||||||
|     for (i = 0; i < pixels; i++) { |     for (i = 0; i < pixels; i++) { | ||||||
|         if (in[i] == 0) |         if (in[i] == 0) { | ||||||
|             b |= m; |             b |= m; | ||||||
|  |         } | ||||||
|         m <<= 1; |         m <<= 1; | ||||||
|         if (m == 256){ |         if (m == 256){ | ||||||
|             *out++ = b; |             *out++ = b; | ||||||
|             b = 0; m = 1; |             b = 0; m = 1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if (m != 1) |     if (m != 1) { | ||||||
|         *out++ = b; |         *out++ = b; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -154,8 +162,9 @@ pack1L(UINT8* out, const UINT8* in, int pixels) | ||||||
| { | { | ||||||
|     int i; |     int i; | ||||||
|     /* bilevel, stored as bytes */ |     /* bilevel, stored as bytes */ | ||||||
|     for (i = 0; i < pixels; i++) |     for (i = 0; i < pixels; i++) { | ||||||
|         out[i] = (in[i] != 0) ? 255 : 0; |         out[i] = (in[i] != 0) ? 255 : 0; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -167,8 +176,9 @@ packP4(UINT8* out, const UINT8* in, int pixels) | ||||||
|         in += 2; pixels -= 2; |         in += 2; pixels -= 2; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (pixels) |     if (pixels) { | ||||||
|         out[0] = (in[0] << 4); |         out[0] = (in[0] << 4); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -407,12 +417,13 @@ packI16B(UINT8* out, const UINT8* in_, int pixels) | ||||||
|     for (i = 0; i < pixels; i++) { |     for (i = 0; i < pixels; i++) { | ||||||
|         INT32 in; |         INT32 in; | ||||||
|         memcpy(&in, in_, sizeof(in)); |         memcpy(&in, in_, sizeof(in)); | ||||||
|         if (in <= 0) |         if (in <= 0) { | ||||||
|             tmp_ = 0; |             tmp_ = 0; | ||||||
|         else if (in > 65535) |         } else if (in > 65535) { | ||||||
|             tmp_ = 65535; |             tmp_ = 65535; | ||||||
|         else |         } else { | ||||||
|             tmp_ = in; |             tmp_ = in; | ||||||
|  |         } | ||||||
|         C16B; |         C16B; | ||||||
|         out += 2; in_ += sizeof(in); |         out += 2; in_ += sizeof(in); | ||||||
|     } |     } | ||||||
|  | @ -496,40 +507,45 @@ copy4I(UINT8* out, const UINT8* in, int pixels) | ||||||
| { | { | ||||||
|     /* RGBA, CMYK quadruples, inverted */ |     /* RGBA, CMYK quadruples, inverted */ | ||||||
|     int i; |     int i; | ||||||
|     for (i = 0; i < pixels*4; i++) |     for (i = 0; i < pixels*4; i++) { | ||||||
|         out[i] = ~in[i]; |         out[i] = ~in[i]; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| band0(UINT8* out, const UINT8* in, int pixels) | band0(UINT8* out, const UINT8* in, int pixels) | ||||||
| { | { | ||||||
|     int i; |     int i; | ||||||
|     for (i = 0; i < pixels; i++, in += 4) |     for (i = 0; i < pixels; i++, in += 4) { | ||||||
|         out[i] = in[0]; |         out[i] = in[0]; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| band1(UINT8* out, const UINT8* in, int pixels) | band1(UINT8* out, const UINT8* in, int pixels) | ||||||
| { | { | ||||||
|     int i; |     int i; | ||||||
|     for (i = 0; i < pixels; i++, in += 4) |     for (i = 0; i < pixels; i++, in += 4) { | ||||||
|         out[i] = in[1]; |         out[i] = in[1]; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| band2(UINT8* out, const UINT8* in, int pixels) | band2(UINT8* out, const UINT8* in, int pixels) | ||||||
| { | { | ||||||
|     int i; |     int i; | ||||||
|     for (i = 0; i < pixels; i++, in += 4) |     for (i = 0; i < pixels; i++, in += 4) { | ||||||
|         out[i] = in[2]; |         out[i] = in[2]; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| band3(UINT8* out, const UINT8* in, int pixels) | band3(UINT8* out, const UINT8* in, int pixels) | ||||||
| { | { | ||||||
|     int i; |     int i; | ||||||
|     for (i = 0; i < pixels; i++, in += 4) |     for (i = 0; i < pixels; i++, in += 4) { | ||||||
|         out[i] = in[3]; |         out[i] = in[3]; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct { | static struct { | ||||||
|  | @ -673,12 +689,14 @@ ImagingFindPacker(const char* mode, const char* rawmode, int* bits_out) | ||||||
|     int i; |     int i; | ||||||
| 
 | 
 | ||||||
|     /* find a suitable pixel packer */ |     /* find a suitable pixel packer */ | ||||||
|     for (i = 0; packers[i].rawmode; i++) |     for (i = 0; packers[i].rawmode; i++) { | ||||||
|         if (strcmp(packers[i].mode, mode) == 0 && |         if (strcmp(packers[i].mode, mode) == 0 && | ||||||
|             strcmp(packers[i].rawmode, rawmode) == 0) { |             strcmp(packers[i].rawmode, rawmode) == 0) { | ||||||
|             if (bits_out) |             if (bits_out) { | ||||||
|                 *bits_out = packers[i].bits; |                 *bits_out = packers[i].bits; | ||||||
|  |             } | ||||||
|             return packers[i].pack; |             return packers[i].pack; | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -28,8 +28,9 @@ ImagingPackbitsDecode(Imaging im, ImagingCodecState state, | ||||||
| 
 | 
 | ||||||
|     for (;;) { |     for (;;) { | ||||||
| 
 | 
 | ||||||
|         if (bytes < 1) |         if (bytes < 1) { | ||||||
|             return ptr - buf; |             return ptr - buf; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (ptr[0] & 0x80) { |         if (ptr[0] & 0x80) { | ||||||
| 
 | 
 | ||||||
|  | @ -40,8 +41,9 @@ ImagingPackbitsDecode(Imaging im, ImagingCodecState state, | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             /* Run */ |             /* Run */ | ||||||
|             if (bytes < 2) |             if (bytes < 2) { | ||||||
|                 return ptr - buf; |                 return ptr - buf; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             for (n = 257 - ptr[0]; n > 0; n--) { |             for (n = 257 - ptr[0]; n > 0; n--) { | ||||||
|                 if (state->x >= state->bytes) { |                 if (state->x >= state->bytes) { | ||||||
|  | @ -58,8 +60,9 @@ ImagingPackbitsDecode(Imaging im, ImagingCodecState state, | ||||||
|             /* Literal */ |             /* Literal */ | ||||||
|             n = ptr[0]+2; |             n = ptr[0]+2; | ||||||
| 
 | 
 | ||||||
|             if (bytes < n) |             if (bytes < n) { | ||||||
|                 return ptr - buf; |                 return ptr - buf; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             for (i = 1; i < n; i++) { |             for (i = 1; i < n; i++) { | ||||||
|                 if (state->x >= state->bytes) { |                 if (state->x >= state->bytes) { | ||||||
|  |  | ||||||
|  | @ -30,12 +30,14 @@ ImagingPaletteNew(const char* mode) | ||||||
|     int i; |     int i; | ||||||
|     ImagingPalette palette; |     ImagingPalette palette; | ||||||
| 
 | 
 | ||||||
|     if (strcmp(mode, "RGB") && strcmp(mode, "RGBA")) |     if (strcmp(mode, "RGB") && strcmp(mode, "RGBA")) { | ||||||
|         return (ImagingPalette) ImagingError_ModeError(); |         return (ImagingPalette) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     palette = calloc(1, sizeof(struct ImagingPaletteInstance)); |     palette = calloc(1, sizeof(struct ImagingPaletteInstance)); | ||||||
|     if (!palette) |     if (!palette) { | ||||||
|         return (ImagingPalette) ImagingError_MemoryError(); |         return (ImagingPalette) ImagingError_MemoryError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     strncpy(palette->mode, mode, IMAGING_MODE_LENGTH-1); |     strncpy(palette->mode, mode, IMAGING_MODE_LENGTH-1); | ||||||
|     palette->mode[IMAGING_MODE_LENGTH-1] = 0; |     palette->mode[IMAGING_MODE_LENGTH-1] = 0; | ||||||
|  | @ -60,8 +62,9 @@ ImagingPaletteNewBrowser(void) | ||||||
|     ImagingPalette palette; |     ImagingPalette palette; | ||||||
| 
 | 
 | ||||||
|     palette = ImagingPaletteNew("RGB"); |     palette = ImagingPaletteNew("RGB"); | ||||||
|     if (!palette) |     if (!palette) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Blank out unused entries */ |     /* Blank out unused entries */ | ||||||
|     /* FIXME: Add 10-level windows palette here? */ |     /* FIXME: Add 10-level windows palette here? */ | ||||||
|  | @ -74,14 +77,16 @@ ImagingPaletteNewBrowser(void) | ||||||
| 
 | 
 | ||||||
|     /* Simple 6x6x6 colour cube */ |     /* Simple 6x6x6 colour cube */ | ||||||
| 
 | 
 | ||||||
|     for (b = 0; b < 256; b += 51) |     for (b = 0; b < 256; b += 51) { | ||||||
|         for (g = 0; g < 256; g += 51) |         for (g = 0; g < 256; g += 51) { | ||||||
|             for (r = 0; r < 256; r += 51) { |             for (r = 0; r < 256; r += 51) { | ||||||
|                 palette->palette[i*4+0] = r; |                 palette->palette[i*4+0] = r; | ||||||
|                 palette->palette[i*4+1] = g; |                 palette->palette[i*4+1] = g; | ||||||
|                 palette->palette[i*4+2] = b; |                 palette->palette[i*4+2] = b; | ||||||
|                 i++; |                 i++; | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Blank out unused entries */ |     /* Blank out unused entries */ | ||||||
|     /* FIXME: add 30-level greyscale wedge here? */ |     /* FIXME: add 30-level greyscale wedge here? */ | ||||||
|  | @ -102,12 +107,14 @@ ImagingPaletteDuplicate(ImagingPalette palette) | ||||||
| 
 | 
 | ||||||
|     ImagingPalette new_palette; |     ImagingPalette new_palette; | ||||||
| 
 | 
 | ||||||
|     if (!palette) |     if (!palette) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
|     /* malloc check ok, small constant allocation */ |     /* malloc check ok, small constant allocation */ | ||||||
|     new_palette = malloc(sizeof(struct ImagingPaletteInstance)); |     new_palette = malloc(sizeof(struct ImagingPaletteInstance)); | ||||||
|     if (!new_palette) |     if (!new_palette) { | ||||||
|         return (ImagingPalette) ImagingError_MemoryError(); |         return (ImagingPalette) ImagingError_MemoryError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance)); |     memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance)); | ||||||
| 
 | 
 | ||||||
|  | @ -123,8 +130,9 @@ ImagingPaletteDelete(ImagingPalette palette) | ||||||
|     /* Destroy palette object */ |     /* Destroy palette object */ | ||||||
| 
 | 
 | ||||||
|     if (palette) { |     if (palette) { | ||||||
|         if (palette->cache) |         if (palette->cache) { | ||||||
|             free(palette->cache); |             free(palette->cache); | ||||||
|  |         } | ||||||
|         free(palette); |         free(palette); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -209,8 +217,9 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) | ||||||
|         tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0); |         tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0); | ||||||
| 
 | 
 | ||||||
|         dmin[i] = tmin; |         dmin[i] = tmin; | ||||||
|         if (tmax < dmax) |         if (tmax < dmax) { | ||||||
|             dmax = tmax; /* keep the smallest max distance only */ |             dmax = tmax; /* keep the smallest max distance only */ | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -220,10 +229,11 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) | ||||||
|      * all slots in that box.  We only check boxes for which the min |      * all slots in that box.  We only check boxes for which the min | ||||||
|      * distance is less than or equal the smallest max distance */ |      * distance is less than or equal the smallest max distance */ | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < BOXVOLUME; i++) |     for (i = 0; i < BOXVOLUME; i++) { | ||||||
|         d[i] = (unsigned int) ~0; |         d[i] = (unsigned int) ~0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < 256; i++) |     for (i = 0; i < 256; i++) { | ||||||
| 
 | 
 | ||||||
|         if (dmin[i] <= dmax) { |         if (dmin[i] <= dmax) { | ||||||
| 
 | 
 | ||||||
|  | @ -262,6 +272,7 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) | ||||||
|                 rx += 2 * RSTEP * RSTEP; |                 rx += 2 * RSTEP * RSTEP; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Step 3 -- Update cache */ |     /* Step 3 -- Update cache */ | ||||||
| 
 | 
 | ||||||
|  | @ -269,10 +280,13 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) | ||||||
|      * cache slot in the box.  Update the cache. */ |      * cache slot in the box.  Update the cache. */ | ||||||
| 
 | 
 | ||||||
|     j = 0; |     j = 0; | ||||||
|     for (r = r0; r < r1; r+=4) |     for (r = r0; r < r1; r+=4) { | ||||||
|         for (g = g0; g < g1; g+=4) |         for (g = g0; g < g1; g+=4) { | ||||||
|             for (b = b0; b < b1; b+=4) |             for (b = b0; b < b1; b+=4) { | ||||||
|                 ImagingPaletteCache(palette, r, g, b) = c[j++]; |                 ImagingPaletteCache(palette, r, g, b) = c[j++]; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -297,8 +311,9 @@ ImagingPaletteCachePrepare(ImagingPalette palette) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /* Mark all entries as empty */ |         /* Mark all entries as empty */ | ||||||
|         for (i = 0; i < entries; i++) |         for (i = 0; i < entries; i++) { | ||||||
|             palette->cache[i] = 0x100; |             palette->cache[i] = 0x100; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -37,8 +37,9 @@ paste(Imaging imOut, Imaging imIn, int dx, int dy, int sx, int sy, | ||||||
| 
 | 
 | ||||||
|     xsize *= pixelsize; |     xsize *= pixelsize; | ||||||
| 
 | 
 | ||||||
|     for (y = 0; y < ysize; y++) |     for (y = 0; y < ysize; y++) { | ||||||
|         memcpy(imOut->image[y+dy]+dx, imIn->image[y+sy]+sx, xsize); |         memcpy(imOut->image[y+dy]+dx, imIn->image[y+sy]+sx, xsize); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void | static inline void | ||||||
|  | @ -57,8 +58,9 @@ paste_mask_1(Imaging imOut, Imaging imIn, Imaging imMask, | ||||||
|             UINT8* in = imIn->image8[y+sy]+sx; |             UINT8* in = imIn->image8[y+sy]+sx; | ||||||
|             UINT8* mask = imMask->image8[y+sy]+sx; |             UINT8* mask = imMask->image8[y+sy]+sx; | ||||||
|             for (x = 0; x < xsize; x++) { |             for (x = 0; x < xsize; x++) { | ||||||
|                 if (*mask++) |                 if (*mask++) { | ||||||
|                     *out = *in; |                     *out = *in; | ||||||
|  |                 } | ||||||
|                 out++, in++; |                 out++, in++; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -70,8 +72,9 @@ paste_mask_1(Imaging imOut, Imaging imIn, Imaging imMask, | ||||||
|             INT32* in = imIn->image32[y+sy]+sx; |             INT32* in = imIn->image32[y+sy]+sx; | ||||||
|             UINT8* mask = imMask->image8[y+sy]+sx; |             UINT8* mask = imMask->image8[y+sy]+sx; | ||||||
|             for (x = 0; x < xsize; x++) { |             for (x = 0; x < xsize; x++) { | ||||||
|                 if (*mask++) |                 if (*mask++) { | ||||||
|                     *out = *in; |                     *out = *in; | ||||||
|  |                 } | ||||||
|                 out++, in++; |                 out++, in++; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -231,17 +234,22 @@ ImagingPaste(Imaging imOut, Imaging imIn, Imaging imMask, | ||||||
| 
 | 
 | ||||||
|     /* Determine which region to copy */ |     /* Determine which region to copy */ | ||||||
|     sx0 = sy0 = 0; |     sx0 = sy0 = 0; | ||||||
|     if (dx0 < 0) |     if (dx0 < 0) { | ||||||
|         xsize += dx0, sx0 = -dx0, dx0 = 0; |         xsize += dx0, sx0 = -dx0, dx0 = 0; | ||||||
|     if (dx0 + xsize > imOut->xsize) |     } | ||||||
|  |     if (dx0 + xsize > imOut->xsize) { | ||||||
|         xsize = imOut->xsize - dx0; |         xsize = imOut->xsize - dx0; | ||||||
|     if (dy0 < 0) |     } | ||||||
|  |     if (dy0 < 0) { | ||||||
|         ysize += dy0, sy0 = -dy0, dy0 = 0; |         ysize += dy0, sy0 = -dy0, dy0 = 0; | ||||||
|     if (dy0 + ysize > imOut->ysize) |     } | ||||||
|  |     if (dy0 + ysize > imOut->ysize) { | ||||||
|         ysize = imOut->ysize - dy0; |         ysize = imOut->ysize - dy0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (xsize <= 0 || ysize <= 0) |     if (xsize <= 0 || ysize <= 0) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!imMask) { |     if (!imMask) { | ||||||
|         ImagingSectionEnter(&cookie); |         ImagingSectionEnter(&cookie); | ||||||
|  | @ -297,15 +305,17 @@ fill(Imaging imOut, const void* ink_, int dx, int dy, | ||||||
| 
 | 
 | ||||||
|         dx *= pixelsize; |         dx *= pixelsize; | ||||||
|         xsize *= pixelsize; |         xsize *= pixelsize; | ||||||
|         for (y = 0; y < ysize; y++) |         for (y = 0; y < ysize; y++) { | ||||||
|             memset(imOut->image[y+dy]+dx, ink8, xsize); |             memset(imOut->image[y+dy]+dx, ink8, xsize); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } else { |     } else { | ||||||
| 
 | 
 | ||||||
|         for (y = 0; y < ysize; y++) { |         for (y = 0; y < ysize; y++) { | ||||||
|             INT32* out = imOut->image32[y+dy]+dx; |             INT32* out = imOut->image32[y+dy]+dx; | ||||||
|             for (x = 0; x < xsize; x++) |             for (x = 0; x < xsize; x++) { | ||||||
|                 out[x] = ink32; |                 out[x] = ink32; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
|  | @ -331,8 +341,9 @@ fill_mask_1(Imaging imOut, const void* ink_, Imaging imMask, | ||||||
|             UINT8* out = imOut->image8[y+dy]+dx; |             UINT8* out = imOut->image8[y+dy]+dx; | ||||||
|             UINT8* mask = imMask->image8[y+sy]+sx; |             UINT8* mask = imMask->image8[y+sy]+sx; | ||||||
|             for (x = 0; x < xsize; x++) { |             for (x = 0; x < xsize; x++) { | ||||||
|                 if (*mask++) |                 if (*mask++) { | ||||||
|                     *out = ink8; |                     *out = ink8; | ||||||
|  |                 } | ||||||
|                 out++; |                 out++; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -343,8 +354,9 @@ fill_mask_1(Imaging imOut, const void* ink_, Imaging imMask, | ||||||
|             INT32* out = imOut->image32[y+dy]+dx; |             INT32* out = imOut->image32[y+dy]+dx; | ||||||
|             UINT8* mask = imMask->image8[y+sy]+sx; |             UINT8* mask = imMask->image8[y+sy]+sx; | ||||||
|             for (x = 0; x < xsize; x++) { |             for (x = 0; x < xsize; x++) { | ||||||
|                 if (*mask++) |                 if (*mask++) { | ||||||
|                     *out = ink32; |                     *out = ink32; | ||||||
|  |                 } | ||||||
|                 out++; |                 out++; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -494,17 +506,22 @@ ImagingFill2(Imaging imOut, const void* ink, Imaging imMask, | ||||||
| 
 | 
 | ||||||
|     /* Determine which region to fill */ |     /* Determine which region to fill */ | ||||||
|     sx0 = sy0 = 0; |     sx0 = sy0 = 0; | ||||||
|     if (dx0 < 0) |     if (dx0 < 0) { | ||||||
|         xsize += dx0, sx0 = -dx0, dx0 = 0; |         xsize += dx0, sx0 = -dx0, dx0 = 0; | ||||||
|     if (dx0 + xsize > imOut->xsize) |     } | ||||||
|  |     if (dx0 + xsize > imOut->xsize) { | ||||||
|         xsize = imOut->xsize - dx0; |         xsize = imOut->xsize - dx0; | ||||||
|     if (dy0 < 0) |     } | ||||||
|  |     if (dy0 < 0) { | ||||||
|         ysize += dy0, sy0 = -dy0, dy0 = 0; |         ysize += dy0, sy0 = -dy0, dy0 = 0; | ||||||
|     if (dy0 + ysize > imOut->ysize) |     } | ||||||
|  |     if (dy0 + ysize > imOut->ysize) { | ||||||
|         ysize = imOut->ysize - dy0; |         ysize = imOut->ysize - dy0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (xsize <= 0 || ysize <= 0) |     if (xsize <= 0 || ysize <= 0) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!imMask) { |     if (!imMask) { | ||||||
|         ImagingSectionEnter(&cookie); |         ImagingSectionEnter(&cookie); | ||||||
|  |  | ||||||
|  | @ -38,8 +38,9 @@ ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|     for (;;) { |     for (;;) { | ||||||
| 
 | 
 | ||||||
|         /* We need data for two full lines before we can do anything */ |         /* We need data for two full lines before we can do anything */ | ||||||
|         if (bytes < chunk) |         if (bytes < chunk) { | ||||||
|             return ptr - buf; |             return ptr - buf; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         /* Unpack first line */ |         /* Unpack first line */ | ||||||
|         out = state->buffer; |         out = state->buffer; | ||||||
|  | @ -53,8 +54,9 @@ ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|         state->shuffle((UINT8*) im->image[state->y], |         state->shuffle((UINT8*) im->image[state->y], | ||||||
|                    state->buffer, state->xsize); |                    state->buffer, state->xsize); | ||||||
| 
 | 
 | ||||||
|         if (++state->y >= state->ysize) |         if (++state->y >= state->ysize) { | ||||||
|             return -1; /* This can hardly happen */ |             return -1; /* This can hardly happen */ | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         /* Unpack second line */ |         /* Unpack second line */ | ||||||
|         out = state->buffer; |         out = state->buffer; | ||||||
|  | @ -68,8 +70,9 @@ ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|         state->shuffle((UINT8*) im->image[state->y], |         state->shuffle((UINT8*) im->image[state->y], | ||||||
|                    state->buffer, state->xsize); |                    state->buffer, state->xsize); | ||||||
| 
 | 
 | ||||||
|         if (++state->y >= state->ysize) |         if (++state->y >= state->ysize) { | ||||||
|             return -1; |             return -1; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         ptr += chunk; |         ptr += chunk; | ||||||
|         bytes -= chunk; |         bytes -= chunk; | ||||||
|  |  | ||||||
|  | @ -31,14 +31,16 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
| 
 | 
 | ||||||
|     for (;;) { |     for (;;) { | ||||||
| 
 | 
 | ||||||
|         if (bytes < 1) |         if (bytes < 1) { | ||||||
|             return ptr - buf; |             return ptr - buf; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if ((*ptr & 0xC0) == 0xC0) { |         if ((*ptr & 0xC0) == 0xC0) { | ||||||
| 
 | 
 | ||||||
|             /* Run */ |             /* Run */ | ||||||
|             if (bytes < 2) |             if (bytes < 2) { | ||||||
|                 return ptr - buf; |                 return ptr - buf; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             n = ptr[0] & 0x3F; |             n = ptr[0] & 0x3F; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -35,8 +35,9 @@ im_point_8_8(Imaging imOut, Imaging imIn, im_point_context* context) | ||||||
|     for (y = 0; y < imIn->ysize; y++) { |     for (y = 0; y < imIn->ysize; y++) { | ||||||
|         UINT8* in = imIn->image8[y]; |         UINT8* in = imIn->image8[y]; | ||||||
|         UINT8* out = imOut->image8[y]; |         UINT8* out = imOut->image8[y]; | ||||||
|         for (x = 0; x < imIn->xsize; x++) |         for (x = 0; x < imIn->xsize; x++) { | ||||||
|             out[x] = table[in[x]]; |             out[x] = table[in[x]]; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -103,8 +104,9 @@ im_point_8_32(Imaging imOut, Imaging imIn, im_point_context* context) | ||||||
|     for (y = 0; y < imIn->ysize; y++) { |     for (y = 0; y < imIn->ysize; y++) { | ||||||
|         UINT8* in = imIn->image8[y]; |         UINT8* in = imIn->image8[y]; | ||||||
|         INT32* out = imOut->image32[y]; |         INT32* out = imOut->image32[y]; | ||||||
|         for (x = 0; x < imIn->xsize; x++) |         for (x = 0; x < imIn->xsize; x++) { | ||||||
|             memcpy(out + x, table + in[x] * sizeof(INT32), sizeof(INT32)); |             memcpy(out + x, table + in[x] * sizeof(INT32), sizeof(INT32)); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -119,10 +121,11 @@ im_point_32_8(Imaging imOut, Imaging imIn, im_point_context* context) | ||||||
|         UINT8* out = imOut->image8[y]; |         UINT8* out = imOut->image8[y]; | ||||||
|         for (x = 0; x < imIn->xsize; x++) { |         for (x = 0; x < imIn->xsize; x++) { | ||||||
|             int v = in[x]; |             int v = in[x]; | ||||||
|             if (v < 0) |             if (v < 0) { | ||||||
|                 v = 0; |                 v = 0; | ||||||
|             else if (v > 65535) |             } else if (v > 65535) { | ||||||
|                 v = 65535; |                 v = 65535; | ||||||
|  |             } | ||||||
|             out[x] = table[v]; |             out[x] = table[v]; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -138,21 +141,26 @@ ImagingPoint(Imaging imIn, const char* mode, const void* table) | ||||||
|     im_point_context context; |     im_point_context context; | ||||||
|     void (*point)(Imaging imIn, Imaging imOut, im_point_context* context); |     void (*point)(Imaging imIn, Imaging imOut, im_point_context* context); | ||||||
| 
 | 
 | ||||||
|     if (!imIn) |     if (!imIn) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!mode) |     if (!mode) { | ||||||
|         mode = imIn->mode; |         mode = imIn->mode; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (imIn->type != IMAGING_TYPE_UINT8) { |     if (imIn->type != IMAGING_TYPE_UINT8) { | ||||||
|         if (imIn->type != IMAGING_TYPE_INT32 || strcmp(mode, "L") != 0) |         if (imIn->type != IMAGING_TYPE_INT32 || strcmp(mode, "L") != 0) { | ||||||
|             goto mode_mismatch; |             goto mode_mismatch; | ||||||
|     } else if (!imIn->image8 && strcmp(imIn->mode, mode) != 0) |         } | ||||||
|  |     } else if (!imIn->image8 && strcmp(imIn->mode, mode) != 0) { | ||||||
|         goto mode_mismatch; |         goto mode_mismatch; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNew(mode, imIn->xsize, imIn->ysize); |     imOut = ImagingNew(mode, imIn->xsize, imIn->ysize); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* find appropriate handler */ |     /* find appropriate handler */ | ||||||
|     if (imIn->type == IMAGING_TYPE_UINT8) { |     if (imIn->type == IMAGING_TYPE_UINT8) { | ||||||
|  | @ -175,10 +183,12 @@ ImagingPoint(Imaging imIn, const char* mode, const void* table) | ||||||
|                 point = im_point_8_8; |                 point = im_point_8_8; | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } else |         } else { | ||||||
|             point = im_point_8_32; |             point = im_point_8_32; | ||||||
|     } else |         } | ||||||
|  |     } else { | ||||||
|         point = im_point_32_8; |         point = im_point_32_8; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingCopyPalette(imOut, imIn); |     ImagingCopyPalette(imOut, imIn); | ||||||
| 
 | 
 | ||||||
|  | @ -209,12 +219,14 @@ ImagingPointTransform(Imaging imIn, double scale, double offset) | ||||||
| 
 | 
 | ||||||
|     if (!imIn || (strcmp(imIn->mode, "I") != 0 && |     if (!imIn || (strcmp(imIn->mode, "I") != 0 && | ||||||
|                   strcmp(imIn->mode, "I;16") != 0 && |                   strcmp(imIn->mode, "I;16") != 0 && | ||||||
|                   strcmp(imIn->mode, "F") != 0)) |                   strcmp(imIn->mode, "F") != 0)) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize); |     imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     switch (imIn->type) { |     switch (imIn->type) { | ||||||
|     case IMAGING_TYPE_INT32: |     case IMAGING_TYPE_INT32: | ||||||
|  | @ -223,8 +235,9 @@ ImagingPointTransform(Imaging imIn, double scale, double offset) | ||||||
|             INT32* in  = imIn->image32[y]; |             INT32* in  = imIn->image32[y]; | ||||||
|             INT32* out = imOut->image32[y]; |             INT32* out = imOut->image32[y]; | ||||||
|             /* FIXME: add clipping? */ |             /* FIXME: add clipping? */ | ||||||
|             for (x = 0; x < imIn->xsize; x++) |             for (x = 0; x < imIn->xsize; x++) { | ||||||
|                 out[x] = in[x] * scale + offset; |                 out[x] = in[x] * scale + offset; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         ImagingSectionLeave(&cookie); |         ImagingSectionLeave(&cookie); | ||||||
|         break; |         break; | ||||||
|  | @ -233,8 +246,9 @@ ImagingPointTransform(Imaging imIn, double scale, double offset) | ||||||
|         for (y = 0; y < imIn->ysize; y++) { |         for (y = 0; y < imIn->ysize; y++) { | ||||||
|             FLOAT32* in  = (FLOAT32*) imIn->image32[y]; |             FLOAT32* in  = (FLOAT32*) imIn->image32[y]; | ||||||
|             FLOAT32* out = (FLOAT32*) imOut->image32[y]; |             FLOAT32* out = (FLOAT32*) imOut->image32[y]; | ||||||
|             for (x = 0; x < imIn->xsize; x++) |             for (x = 0; x < imIn->xsize; x++) { | ||||||
|                 out[x] = in[x] * scale + offset; |                 out[x] = in[x] * scale + offset; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         ImagingSectionLeave(&cookie); |         ImagingSectionLeave(&cookie); | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|  | @ -157,7 +157,9 @@ create_pixel_hash(Pixel *pixelData,uint32_t nPixels) | ||||||
| 
 | 
 | ||||||
|    /* malloc check ok, small constant allocation */ |    /* malloc check ok, small constant allocation */ | ||||||
|    d=malloc(sizeof(PixelHashData)); |    d=malloc(sizeof(PixelHashData)); | ||||||
|    if (!d) return NULL; |    if (!d) { | ||||||
|  |        return NULL; | ||||||
|  |    } | ||||||
|    hash=hashtable_new(pixel_hash,pixel_cmp); |    hash=hashtable_new(pixel_hash,pixel_cmp); | ||||||
|    hashtable_set_user_data(hash,d); |    hashtable_set_user_data(hash,d); | ||||||
|    d->scale=0; |    d->scale=0; | ||||||
|  | @ -197,7 +199,9 @@ static void | ||||||
| destroy_pixel_hash(HashTable *hash) | destroy_pixel_hash(HashTable *hash) | ||||||
| { | { | ||||||
|    PixelHashData *d=(PixelHashData *)hashtable_get_user_data(hash); |    PixelHashData *d=(PixelHashData *)hashtable_get_user_data(hash); | ||||||
|    if (d) free(d); |    if (d) { | ||||||
|  |        free(d); | ||||||
|  |    } | ||||||
|    hashtable_free(hash); |    hashtable_free(hash); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -214,7 +218,9 @@ static int | ||||||
| compute_box_volume(BoxNode *b) | compute_box_volume(BoxNode *b) | ||||||
| { | { | ||||||
|    unsigned char rl,rh,gl,gh,bl,bh; |    unsigned char rl,rh,gl,gh,bl,bh; | ||||||
|    if (b->volume>=0) return b->volume; |    if (b->volume>=0) { | ||||||
|  |       return b->volume; | ||||||
|  |    } | ||||||
|    if (!b->head[0]) { |    if (!b->head[0]) { | ||||||
|       b->volume=0; |       b->volume=0; | ||||||
|    } else { |    } else { | ||||||
|  | @ -242,7 +248,9 @@ hash_to_list(const HashTable *h, const Pixel pixel, const uint32_t count, void * | ||||||
| 
 | 
 | ||||||
|    /* malloc check ok, small constant allocation */ |    /* malloc check ok, small constant allocation */ | ||||||
|    p=malloc(sizeof(PixelList)); |    p=malloc(sizeof(PixelList)); | ||||||
|    if (!p) return; |    if (!p) { | ||||||
|  |       return; | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    p->flag=0; |    p->flag=0; | ||||||
|    p->p=q; |    p->p=q; | ||||||
|  | @ -250,7 +258,9 @@ hash_to_list(const HashTable *h, const Pixel pixel, const uint32_t count, void * | ||||||
|    for (i=0;i<3;i++) { |    for (i=0;i<3;i++) { | ||||||
|       p->next[i]=pl[i]; |       p->next[i]=pl[i]; | ||||||
|       p->prev[i]=NULL; |       p->prev[i]=NULL; | ||||||
|       if (pl[i]) pl[i]->prev[i]=p; |       if (pl[i]) { | ||||||
|  |          pl[i]->prev[i]=p; | ||||||
|  |       } | ||||||
|       pl[i]=p; |       pl[i]=p; | ||||||
|    } |    } | ||||||
| } | } | ||||||
|  | @ -268,7 +278,9 @@ mergesort_pixels(PixelList *head, int i) | ||||||
|    } |    } | ||||||
|    for (c=t=head;c&&t;c=c->next[i],t=(t->next[i])?t->next[i]->next[i]:NULL); |    for (c=t=head;c&&t;c=c->next[i],t=(t->next[i])?t->next[i]->next[i]:NULL); | ||||||
|    if (c) { |    if (c) { | ||||||
|       if (c->prev[i]) c->prev[i]->next[i]=NULL; |       if (c->prev[i]) { | ||||||
|  |          c->prev[i]->next[i]=NULL; | ||||||
|  |       } | ||||||
|       c->prev[i]=NULL; |       c->prev[i]=NULL; | ||||||
|    } |    } | ||||||
|    a=mergesort_pixels(head,i); |    a=mergesort_pixels(head,i); | ||||||
|  | @ -285,9 +297,13 @@ mergesort_pixels(PixelList *head, int i) | ||||||
|       } |       } | ||||||
|       c->prev[i]=p; |       c->prev[i]=p; | ||||||
|       c->next[i]=NULL; |       c->next[i]=NULL; | ||||||
|       if (p) p->next[i]=c; |       if (p) { | ||||||
|  |          p->next[i]=c; | ||||||
|  |       } | ||||||
|       p=c; |       p=c; | ||||||
|       if (!head) head=c; |       if (!head) { | ||||||
|  |          head=c; | ||||||
|  |       } | ||||||
|    } |    } | ||||||
|    if (a) { |    if (a) { | ||||||
|       c->next[i]=a; |       c->next[i]=a; | ||||||
|  | @ -442,17 +458,29 @@ splitlists(PixelList *h[3], | ||||||
|       for (c=h[i];c;c=n) { |       for (c=h[i];c;c=n) { | ||||||
|          n=c->next[i]; |          n=c->next[i]; | ||||||
|          if (c->flag) {    /* move pixel to right  list*/ |          if (c->flag) {    /* move pixel to right  list*/ | ||||||
|             if (r) r->next[i]=c; else nh[1][i]=c; |             if (r) { | ||||||
|  |                r->next[i]=c; | ||||||
|  |             } else { | ||||||
|  |                nh[1][i]=c; | ||||||
|  |             } | ||||||
|             c->prev[i]=r; |             c->prev[i]=r; | ||||||
|             r=c; |             r=c; | ||||||
|          } else {          /* move pixel to left list */ |          } else {          /* move pixel to left list */ | ||||||
|             if (l) l->next[i]=c; else nh[0][i]=c; |             if (l) { | ||||||
|  |                l->next[i]=c; | ||||||
|  |             } else { | ||||||
|  |                nh[0][i]=c; | ||||||
|  |             } | ||||||
|             c->prev[i]=l; |             c->prev[i]=l; | ||||||
|             l=c; |             l=c; | ||||||
|          } |          } | ||||||
|       } |       } | ||||||
|       if (l) l->next[i]=NULL; |       if (l) { | ||||||
|       if (r) r->next[i]=NULL; |          l->next[i]=NULL; | ||||||
|  |       } | ||||||
|  |       if (r) { | ||||||
|  |          r->next[i]=NULL; | ||||||
|  |       } | ||||||
|       nt[0][i]=l; |       nt[0][i]=l; | ||||||
|       nt[1][i]=r; |       nt[1][i]=r; | ||||||
|    } |    } | ||||||
|  | @ -661,8 +689,12 @@ static void | ||||||
| free_box_tree(BoxNode *n) | free_box_tree(BoxNode *n) | ||||||
| { | { | ||||||
|    PixelList *p,*pp; |    PixelList *p,*pp; | ||||||
|    if (n->l) free_box_tree(n->l); |    if (n->l) { | ||||||
|    if (n->r) free_box_tree(n->r); |       free_box_tree(n->l); | ||||||
|  |    } | ||||||
|  |    if (n->r) { | ||||||
|  |       free_box_tree(n->r); | ||||||
|  |    } | ||||||
|    for (p=n->head[0];p;p=pp) { |    for (p=n->head[0];p;p=pp) { | ||||||
|       pp=p->next[0]; |       pp=p->next[0]; | ||||||
|       free(p); |       free(p); | ||||||
|  | @ -720,7 +752,9 @@ annotate_hash_table(BoxNode *n,HashTable *h,uint32_t *box) | ||||||
|          return 0; |          return 0; | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
|    if (n->head[0]) (*box)++; |    if (n->head[0]) { | ||||||
|  |       (*box)++; | ||||||
|  |    } | ||||||
|    return 1; |    return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -756,7 +790,9 @@ resort_distance_tables(uint32_t *avgDist, | ||||||
|          for (k=j;k&&(*(skRow[k-1])>*(skRow[k]));k--) { |          for (k=j;k&&(*(skRow[k-1])>*(skRow[k]));k--) { | ||||||
|             skRow[k]=skRow[k-1]; |             skRow[k]=skRow[k-1]; | ||||||
|          } |          } | ||||||
|          if (k!=j) skRow[k]=skElt; |          if (k!=j) { | ||||||
|  |             skRow[k]=skElt; | ||||||
|  |          } | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
|    return 1; |    return 1; | ||||||
|  | @ -976,7 +1012,9 @@ compute_palette_from_median_cut( | ||||||
|       /* malloc check ok, using calloc */ |       /* malloc check ok, using calloc */ | ||||||
|       if (!(avg[i]=calloc(nPaletteEntries, sizeof(uint32_t)))) { |       if (!(avg[i]=calloc(nPaletteEntries, sizeof(uint32_t)))) { | ||||||
|          for(i=0;i<3;i++) { |          for(i=0;i<3;i++) { | ||||||
|             if (avg[i]) free (avg[i]); |             if (avg[i]) { | ||||||
|  |                free (avg[i]); | ||||||
|  |             } | ||||||
|          } |          } | ||||||
|          free(count); |          free(count); | ||||||
|          return 0; |          return 0; | ||||||
|  | @ -987,7 +1025,9 @@ compute_palette_from_median_cut( | ||||||
|       if (!(i%100)) { printf ("%05d\r",i); fflush(stdout); } |       if (!(i%100)) { printf ("%05d\r",i); fflush(stdout); } | ||||||
|       if (checkContained(root,pixelData+i)>1) { |       if (checkContained(root,pixelData+i)>1) { | ||||||
|          printf ("pixel in two boxes\n"); |          printf ("pixel in two boxes\n"); | ||||||
|          for(i=0;i<3;i++) free (avg[i]); |          for(i=0;i<3;i++) { | ||||||
|  |             free (avg[i]); | ||||||
|  |          } | ||||||
|          free(count); |          free(count); | ||||||
|          return 0; |          return 0; | ||||||
|       } |       } | ||||||
|  | @ -996,7 +1036,9 @@ compute_palette_from_median_cut( | ||||||
| #ifndef NO_OUTPUT | #ifndef NO_OUTPUT | ||||||
|          printf ("pixel lookup failed\n"); |          printf ("pixel lookup failed\n"); | ||||||
| #endif | #endif | ||||||
|          for(i=0;i<3;i++) free (avg[i]); |          for(i=0;i<3;i++) { | ||||||
|  |             free (avg[i]); | ||||||
|  |          } | ||||||
|          free(count); |          free(count); | ||||||
|          return 0; |          return 0; | ||||||
|       } |       } | ||||||
|  | @ -1004,7 +1046,9 @@ compute_palette_from_median_cut( | ||||||
| #ifndef NO_OUTPUT | #ifndef NO_OUTPUT | ||||||
|          printf ("panic - paletteEntry>=nPaletteEntries (%d>=%d)\n",(int)paletteEntry,(int)nPaletteEntries); |          printf ("panic - paletteEntry>=nPaletteEntries (%d>=%d)\n",(int)paletteEntry,(int)nPaletteEntries); | ||||||
| #endif | #endif | ||||||
|          for(i=0;i<3;i++) free (avg[i]); |          for(i=0;i<3;i++) { | ||||||
|  |             free (avg[i]); | ||||||
|  |          } | ||||||
|          free(count); |          free(count); | ||||||
|          return 0; |          return 0; | ||||||
|       } |       } | ||||||
|  | @ -1016,7 +1060,9 @@ compute_palette_from_median_cut( | ||||||
|    /* malloc check ok, using calloc */ |    /* malloc check ok, using calloc */ | ||||||
|    p=calloc(nPaletteEntries, sizeof(Pixel)); |    p=calloc(nPaletteEntries, sizeof(Pixel)); | ||||||
|    if (!p) { |    if (!p) { | ||||||
|       for(i=0;i<3;i++) free (avg[i]); |       for(i=0;i<3;i++) { | ||||||
|  |          free (avg[i]); | ||||||
|  |       } | ||||||
|       free(count); |       free(count); | ||||||
|       return 0; |       return 0; | ||||||
|    } |    } | ||||||
|  | @ -1026,7 +1072,9 @@ compute_palette_from_median_cut( | ||||||
|       p[i].c.b=(int)(.5+(double)avg[2][i]/(double)count[i]); |       p[i].c.b=(int)(.5+(double)avg[2][i]/(double)count[i]); | ||||||
|    } |    } | ||||||
|    *palette=p; |    *palette=p; | ||||||
|    for(i=0;i<3;i++) free (avg[i]); |    for(i=0;i<3;i++) { | ||||||
|  |       free (avg[i]); | ||||||
|  |    } | ||||||
|    free(count); |    free(count); | ||||||
|    return 1; |    return 1; | ||||||
| } | } | ||||||
|  | @ -1156,24 +1204,46 @@ k_means(Pixel *pixelData, | ||||||
| #ifndef NO_OUTPUT | #ifndef NO_OUTPUT | ||||||
|       printf (".(%d)",changes);fflush(stdout); |       printf (".(%d)",changes);fflush(stdout); | ||||||
| #endif | #endif | ||||||
|       if (changes<=threshold) break; |       if (changes<=threshold) { | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|    } |    } | ||||||
| #ifndef NO_OUTPUT | #ifndef NO_OUTPUT | ||||||
|    printf("]\n"); |    printf("]\n"); | ||||||
| #endif | #endif | ||||||
|    if (avgDistSortKey) free(avgDistSortKey); |    if (avgDistSortKey) { | ||||||
|    if (avgDist) free(avgDist); |       free(avgDistSortKey); | ||||||
|    for(i=0;i<3;i++) if (avg[i]) free (avg[i]); |    } | ||||||
|    if (count) free(count); |    if (avgDist) { | ||||||
|  |       free(avgDist); | ||||||
|  |    } | ||||||
|  |    for(i=0;i<3;i++) { | ||||||
|  |       if (avg[i]) { | ||||||
|  |          free (avg[i]); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |    if (count) { | ||||||
|  |       free(count); | ||||||
|  |    } | ||||||
|    return 1; |    return 1; | ||||||
| 
 | 
 | ||||||
| error_3: | error_3: | ||||||
|    if (avgDistSortKey) free(avgDistSortKey); |    if (avgDistSortKey) { | ||||||
|  |       free(avgDistSortKey); | ||||||
|  |    } | ||||||
| error_2: | error_2: | ||||||
|    if (avgDist) free(avgDist); |    if (avgDist) { | ||||||
|  |       free(avgDist); | ||||||
|  |    } | ||||||
| error_1: | error_1: | ||||||
|    for(i=0;i<3;i++) if (avg[i]) free (avg[i]); |    for(i=0;i<3;i++) { | ||||||
|    if (count) free(count); |       if (avg[i]) { | ||||||
|  |          free (avg[i]); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |    if (count) { | ||||||
|  |       free(count); | ||||||
|  |    } | ||||||
|    return 0; |    return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1345,7 +1415,9 @@ quantize(Pixel *pixelData, | ||||||
| #ifndef NO_OUTPUT | #ifndef NO_OUTPUT | ||||||
|    printf ("k means...\n"); fflush(stdout); timer=clock(); |    printf ("k means...\n"); fflush(stdout); timer=clock(); | ||||||
| #endif | #endif | ||||||
|    if (kmeans) k_means(pixelData,nPixels,p,nPaletteEntries,qp,kmeans-1); |    if (kmeans) { | ||||||
|  |       k_means(pixelData,nPixels,p,nPaletteEntries,qp,kmeans-1); | ||||||
|  |    } | ||||||
| #ifndef NO_OUTPUT | #ifndef NO_OUTPUT | ||||||
|    printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC); |    printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC); | ||||||
| #endif | #endif | ||||||
|  | @ -1357,8 +1429,12 @@ quantize(Pixel *pixelData, | ||||||
| #ifndef NO_OUTPUT | #ifndef NO_OUTPUT | ||||||
|    printf ("cleanup..."); fflush(stdout); timer=clock(); |    printf ("cleanup..."); fflush(stdout); timer=clock(); | ||||||
| #endif | #endif | ||||||
|    if (avgDist) free(avgDist); |    if (avgDist) { | ||||||
|    if (avgDistSortKey) free(avgDistSortKey); |       free(avgDist); | ||||||
|  |    } | ||||||
|  |    if (avgDistSortKey) { | ||||||
|  |       free(avgDistSortKey); | ||||||
|  |    } | ||||||
|    destroy_pixel_hash(h); |    destroy_pixel_hash(h); | ||||||
| #ifndef NO_OUTPUT | #ifndef NO_OUTPUT | ||||||
|    printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC); |    printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC); | ||||||
|  | @ -1367,15 +1443,25 @@ quantize(Pixel *pixelData, | ||||||
|    return 1; |    return 1; | ||||||
| 
 | 
 | ||||||
| error_7: | error_7: | ||||||
|    if (avgDistSortKey) free(avgDistSortKey); |    if (avgDistSortKey) { | ||||||
|  |       free(avgDistSortKey); | ||||||
|  |    } | ||||||
| error_6: | error_6: | ||||||
|    if (avgDist) free(avgDist); |    if (avgDist) { | ||||||
|  |       free(avgDist); | ||||||
|  |    } | ||||||
| error_5: | error_5: | ||||||
|    if (qp) free(qp); |    if (qp) { | ||||||
|  |       free(qp); | ||||||
|  |    } | ||||||
| error_4: | error_4: | ||||||
|    if (p) free(p); |    if (p) { | ||||||
|  |       free(p); | ||||||
|  |    } | ||||||
| error_3: | error_3: | ||||||
|    if (root) free_box_tree(root); |    if (root) { | ||||||
|  |       free_box_tree(root); | ||||||
|  |    } | ||||||
| error_1: | error_1: | ||||||
|    destroy_pixel_hash(h); |    destroy_pixel_hash(h); | ||||||
| error_0: | error_0: | ||||||
|  | @ -1430,7 +1516,9 @@ quantize2(Pixel *pixelData, | ||||||
| 
 | 
 | ||||||
|    /* malloc check ok, using calloc */ |    /* malloc check ok, using calloc */ | ||||||
|    p=calloc(nQuantPixels, sizeof(Pixel)); |    p=calloc(nQuantPixels, sizeof(Pixel)); | ||||||
|    if (!p) return 0; |    if (!p) { | ||||||
|  |       return 0; | ||||||
|  |    } | ||||||
|    mean[0]=mean[1]=mean[2]=0; |    mean[0]=mean[1]=mean[2]=0; | ||||||
|    h=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp); |    h=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp); | ||||||
|    for (i=0;i<nPixels;i++) { |    for (i=0;i<nPixels;i++) { | ||||||
|  | @ -1474,7 +1562,9 @@ quantize2(Pixel *pixelData, | ||||||
|    if (!map_image_pixels(pixelData,nPixels,p,nQuantPixels,avgDist,avgDistSortKey,qp)) { |    if (!map_image_pixels(pixelData,nPixels,p,nQuantPixels,avgDist,avgDistSortKey,qp)) { | ||||||
|       goto error_4; |       goto error_4; | ||||||
|    } |    } | ||||||
|    if (kmeans) k_means(pixelData,nPixels,p,nQuantPixels,qp,kmeans-1); |    if (kmeans) { | ||||||
|  |       k_means(pixelData,nPixels,p,nQuantPixels,qp,kmeans-1); | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    *paletteLength=nQuantPixels; |    *paletteLength=nQuantPixels; | ||||||
|    *palette=p; |    *palette=p; | ||||||
|  | @ -1509,28 +1599,33 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans) | ||||||
|     int withAlpha = 0; |     int withAlpha = 0; | ||||||
|     ImagingSectionCookie cookie; |     ImagingSectionCookie cookie; | ||||||
| 
 | 
 | ||||||
|     if (!im) |     if (!im) { | ||||||
|         return ImagingError_ModeError(); |         return ImagingError_ModeError(); | ||||||
|     if (colors < 1 || colors > 256) |     } | ||||||
|  |     if (colors < 1 || colors > 256) { | ||||||
|         /* FIXME: for colors > 256, consider returning an RGB image
 |         /* FIXME: for colors > 256, consider returning an RGB image
 | ||||||
|            instead (see @PIL205) */ |            instead (see @PIL205) */ | ||||||
|         return (Imaging) ImagingError_ValueError("bad number of colors"); |         return (Imaging) ImagingError_ValueError("bad number of colors"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (strcmp(im->mode, "L") != 0 && strcmp(im->mode, "P") != 0 && |     if (strcmp(im->mode, "L") != 0 && strcmp(im->mode, "P") != 0 && | ||||||
|         strcmp(im->mode, "RGB") != 0 && strcmp(im->mode, "RGBA") !=0) |         strcmp(im->mode, "RGB") != 0 && strcmp(im->mode, "RGBA") !=0) { | ||||||
|         return ImagingError_ModeError(); |         return ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* only octree and imagequant supports RGBA */ |     /* only octree and imagequant supports RGBA */ | ||||||
|     if (!strcmp(im->mode, "RGBA") && mode != 2 && mode != 3) |     if (!strcmp(im->mode, "RGBA") && mode != 2 && mode != 3) { | ||||||
|        return ImagingError_ModeError(); |        return ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (im->xsize > INT_MAX / im->ysize) { |     if (im->xsize > INT_MAX / im->ysize) { | ||||||
|         return ImagingError_MemoryError(); |         return ImagingError_MemoryError(); | ||||||
|     } |     } | ||||||
|     /* malloc check ok, using calloc for final overflow, x*y above */ |     /* malloc check ok, using calloc for final overflow, x*y above */ | ||||||
|     p = calloc(im->xsize * im->ysize, sizeof(Pixel)); |     p = calloc(im->xsize * im->ysize, sizeof(Pixel)); | ||||||
|     if (!p) |     if (!p) { | ||||||
|         return ImagingError_MemoryError(); |         return ImagingError_MemoryError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* collect statistics */ |     /* collect statistics */ | ||||||
| 
 | 
 | ||||||
|  | @ -1543,18 +1638,19 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans) | ||||||
|         /* FIXME: converting a "L" image to "P" with 256 colors
 |         /* FIXME: converting a "L" image to "P" with 256 colors
 | ||||||
|            should be done by a simple copy... */ |            should be done by a simple copy... */ | ||||||
| 
 | 
 | ||||||
|         for (i = y = 0; y < im->ysize; y++) |         for (i = y = 0; y < im->ysize; y++) { | ||||||
|             for (x = 0; x < im->xsize; x++, i++) { |             for (x = 0; x < im->xsize; x++, i++) { | ||||||
|                 p[i].c.r = p[i].c.g = p[i].c.b = im->image8[y][x]; |                 p[i].c.r = p[i].c.g = p[i].c.b = im->image8[y][x]; | ||||||
|                 p[i].c.a = 255; |                 p[i].c.a = 255; | ||||||
|             } |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } else if (!strcmp(im->mode, "P")) { |     } else if (!strcmp(im->mode, "P")) { | ||||||
|         /* palette */ |         /* palette */ | ||||||
| 
 | 
 | ||||||
|         pp = im->palette->palette; |         pp = im->palette->palette; | ||||||
| 
 | 
 | ||||||
|         for (i = y = 0; y < im->ysize; y++) |         for (i = y = 0; y < im->ysize; y++) { | ||||||
|             for (x = 0; x < im->xsize; x++, i++) { |             for (x = 0; x < im->xsize; x++, i++) { | ||||||
|                 v = im->image8[y][x]; |                 v = im->image8[y][x]; | ||||||
|                 p[i].c.r = pp[v*4+0]; |                 p[i].c.r = pp[v*4+0]; | ||||||
|  | @ -1562,13 +1658,16 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans) | ||||||
|                 p[i].c.b = pp[v*4+2]; |                 p[i].c.b = pp[v*4+2]; | ||||||
|                 p[i].c.a = pp[v*4+3]; |                 p[i].c.a = pp[v*4+3]; | ||||||
|             } |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } else if (!strcmp(im->mode, "RGB") || !strcmp(im->mode, "RGBA")) { |     } else if (!strcmp(im->mode, "RGB") || !strcmp(im->mode, "RGBA")) { | ||||||
|         /* true colour */ |         /* true colour */ | ||||||
| 
 | 
 | ||||||
|         for (i = y = 0; y < im->ysize; y++) |         for (i = y = 0; y < im->ysize; y++) { | ||||||
|             for (x = 0; x < im->xsize; x++, i++) |             for (x = 0; x < im->xsize; x++, i++) { | ||||||
|                 p[i].v = im->image32[y][x]; |                 p[i].v = im->image32[y][x]; | ||||||
|  |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } else { |     } else { | ||||||
|         free(p); |         free(p); | ||||||
|  | @ -1647,9 +1746,11 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans) | ||||||
|         imOut = ImagingNewDirty("P", im->xsize, im->ysize); |         imOut = ImagingNewDirty("P", im->xsize, im->ysize); | ||||||
|         ImagingSectionEnter(&cookie); |         ImagingSectionEnter(&cookie); | ||||||
| 
 | 
 | ||||||
|         for (i = y = 0; y < im->ysize; y++) |         for (i = y = 0; y < im->ysize; y++) { | ||||||
|             for (x = 0; x < im->xsize; x++) |             for (x = 0; x < im->xsize; x++) { | ||||||
|                 imOut->image8[y][x] = (unsigned char) newData[i++]; |                 imOut->image8[y][x] = (unsigned char) newData[i++]; | ||||||
|  |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         free(newData); |         free(newData); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -67,7 +67,9 @@ static uint32_t _findPrime(uint32_t start,int dir) { | ||||||
|          continue; |          continue; | ||||||
|       } |       } | ||||||
|       for (t=2;t<sqrt((double)start);t++) { |       for (t=2;t<sqrt((double)start);t++) { | ||||||
|          if (!start%t) break; |          if (!start%t) { | ||||||
|  |              break; | ||||||
|  |          } | ||||||
|       } |       } | ||||||
|       if (t>=sqrt((double)start)) { |       if (t>=sqrt((double)start)) { | ||||||
|          break; |          break; | ||||||
|  | @ -144,7 +146,9 @@ static int _hashtable_insert_node(HashTable *h,HashNode *node,int resize,int upd | ||||||
|       node->next=*n; |       node->next=*n; | ||||||
|       *n=node; |       *n=node; | ||||||
|       h->count++; |       h->count++; | ||||||
|       if (resize) _hashtable_resize(h); |       if (resize) { | ||||||
|  |           _hashtable_resize(h); | ||||||
|  |       } | ||||||
|       return 1; |       return 1; | ||||||
|    } else { |    } else { | ||||||
|       return 0; |       return 0; | ||||||
|  | @ -169,13 +173,17 @@ static int _hashtable_insert(HashTable *h,HashKey_t key,HashVal_t val,int resize | ||||||
|    } |    } | ||||||
|    if (!update) { |    if (!update) { | ||||||
|       t=malloc(sizeof(HashNode)); |       t=malloc(sizeof(HashNode)); | ||||||
|       if (!t) return 0; |       if (!t) { | ||||||
|  |           return 0; | ||||||
|  |       } | ||||||
|       t->next=*n; |       t->next=*n; | ||||||
|       *n=t; |       *n=t; | ||||||
|       t->key=key; |       t->key=key; | ||||||
|       t->value=val; |       t->value=val; | ||||||
|       h->count++; |       h->count++; | ||||||
|       if (resize) _hashtable_resize(h); |       if (resize) { | ||||||
|  |           _hashtable_resize(h); | ||||||
|  |       } | ||||||
|       return 1; |       return 1; | ||||||
|    } else { |    } else { | ||||||
|       return 0; |       return 0; | ||||||
|  | @ -206,7 +214,9 @@ int hashtable_insert_or_update_computed(HashTable *h, | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
|    t=malloc(sizeof(HashNode)); |    t=malloc(sizeof(HashNode)); | ||||||
|    if (!t) return 0; |    if (!t) { | ||||||
|  |        return 0; | ||||||
|  |    } | ||||||
|    t->key=key; |    t->key=key; | ||||||
|    t->next=*n; |    t->next=*n; | ||||||
|    *n=t; |    *n=t; | ||||||
|  |  | ||||||
|  | @ -46,15 +46,21 @@ void ImagingQuantHeapFree(Heap *h) { | ||||||
| 
 | 
 | ||||||
| static int _heap_grow(Heap *h,unsigned int newsize) { | static int _heap_grow(Heap *h,unsigned int newsize) { | ||||||
|    void *newheap; |    void *newheap; | ||||||
|    if (!newsize) newsize=h->heapsize<<1; |    if (!newsize) { | ||||||
|    if (newsize<h->heapsize) return 0; |        newsize=h->heapsize<<1; | ||||||
|  |    } | ||||||
|  |    if (newsize<h->heapsize) { | ||||||
|  |        return 0; | ||||||
|  |    } | ||||||
|    if (newsize > INT_MAX / sizeof(void *)){ |    if (newsize > INT_MAX / sizeof(void *)){ | ||||||
|        return 0; |        return 0; | ||||||
|    } |    } | ||||||
|    /* malloc check ok, using calloc for overflow, also checking
 |    /* malloc check ok, using calloc for overflow, also checking
 | ||||||
|       above due to memcpy below*/ |       above due to memcpy below*/ | ||||||
|    newheap=calloc(newsize, sizeof(void *)); |    newheap=calloc(newsize, sizeof(void *)); | ||||||
|    if (!newheap) return 0; |    if (!newheap) { | ||||||
|  |        return 0; | ||||||
|  |    } | ||||||
|    memcpy(newheap,h->heap,sizeof(void *)*h->heapsize); |    memcpy(newheap,h->heap,sizeof(void *)*h->heapsize); | ||||||
|    free(h->heap); |    free(h->heap); | ||||||
|    h->heap=newheap; |    h->heap=newheap; | ||||||
|  | @ -140,7 +146,9 @@ Heap *ImagingQuantHeapNew(HeapCmpFunc cf) { | ||||||
| 
 | 
 | ||||||
|    /* malloc check ok, small constant allocation */ |    /* malloc check ok, small constant allocation */ | ||||||
|    h=malloc(sizeof(Heap)); |    h=malloc(sizeof(Heap)); | ||||||
|    if (!h) return NULL; |    if (!h) { | ||||||
|  |        return NULL; | ||||||
|  |    } | ||||||
|    h->heapsize=INITIAL_SIZE; |    h->heapsize=INITIAL_SIZE; | ||||||
|    /* malloc check ok, using calloc for overflow */ |    /* malloc check ok, using calloc for overflow */ | ||||||
|    h->heap=calloc(h->heapsize, sizeof(void *)); |    h->heap=calloc(h->heapsize, sizeof(void *)); | ||||||
|  |  | ||||||
|  | @ -56,7 +56,9 @@ new_color_cube(int r, int g, int b, int a) { | ||||||
| 
 | 
 | ||||||
|    /* malloc check ok, small constant allocation */ |    /* malloc check ok, small constant allocation */ | ||||||
|    cube = malloc(sizeof(struct _ColorCube)); |    cube = malloc(sizeof(struct _ColorCube)); | ||||||
|    if (!cube) return NULL; |    if (!cube) { | ||||||
|  |        return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|    cube->rBits = MAX(r, 0); |    cube->rBits = MAX(r, 0); | ||||||
|    cube->gBits = MAX(g, 0); |    cube->gBits = MAX(g, 0); | ||||||
|  | @ -175,7 +177,9 @@ create_sorted_color_palette(const ColorCube cube) { | ||||||
|    } |    } | ||||||
|    /* malloc check ok, calloc + overflow check above for memcpy */ |    /* malloc check ok, calloc + overflow check above for memcpy */ | ||||||
|    buckets = calloc(cube->size, sizeof(struct _ColorBucket)); |    buckets = calloc(cube->size, sizeof(struct _ColorBucket)); | ||||||
|    if (!buckets) return NULL; |    if (!buckets) { | ||||||
|  |        return NULL; | ||||||
|  |    } | ||||||
|    memcpy(buckets, cube->buckets, sizeof(struct _ColorBucket)*cube->size); |    memcpy(buckets, cube->buckets, sizeof(struct _ColorBucket)*cube->size); | ||||||
| 
 | 
 | ||||||
|    qsort(buckets, cube->size, sizeof(struct _ColorBucket), |    qsort(buckets, cube->size, sizeof(struct _ColorBucket), | ||||||
|  | @ -203,7 +207,9 @@ static ColorCube copy_color_cube(const ColorCube cube, | ||||||
|    ColorCube result; |    ColorCube result; | ||||||
| 
 | 
 | ||||||
|    result = new_color_cube(rBits, gBits, bBits, aBits); |    result = new_color_cube(rBits, gBits, bBits, aBits); | ||||||
|    if (!result) return NULL; |    if (!result) { | ||||||
|  |        return NULL; | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    if (cube->rBits > rBits) { |    if (cube->rBits > rBits) { | ||||||
|       dst_reduce[0] = cube->rBits - result->rBits; |       dst_reduce[0] = cube->rBits - result->rBits; | ||||||
|  | @ -268,7 +274,9 @@ subtract_color_buckets(ColorCube cube, ColorBucket buckets, long nBuckets) { | ||||||
|       subtrahend = &buckets[i]; |       subtrahend = &buckets[i]; | ||||||
| 
 | 
 | ||||||
|       // If the subtrahend contains no buckets, there is nothing to subtract.
 |       // If the subtrahend contains no buckets, there is nothing to subtract.
 | ||||||
|       if (subtrahend->count == 0) continue; |       if (subtrahend->count == 0) { | ||||||
|  |           continue; | ||||||
|  |       } | ||||||
| 
 | 
 | ||||||
|       avg_color_from_color_bucket(subtrahend, &p); |       avg_color_from_color_bucket(subtrahend, &p); | ||||||
|       minuend = color_bucket_from_cube(cube, &p); |       minuend = color_bucket_from_cube(cube, &p); | ||||||
|  | @ -325,7 +333,9 @@ create_palette_array(const ColorBucket palette, unsigned int paletteLength) { | ||||||
| 
 | 
 | ||||||
|    /* malloc check ok, calloc for overflow */ |    /* malloc check ok, calloc for overflow */ | ||||||
|    paletteArray = calloc(paletteLength, sizeof(Pixel)); |    paletteArray = calloc(paletteLength, sizeof(Pixel)); | ||||||
|    if (!paletteArray) return NULL; |    if (!paletteArray) { | ||||||
|  |        return NULL; | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    for (i=0; i<paletteLength; i++) { |    for (i=0; i<paletteLength; i++) { | ||||||
|       avg_color_from_color_bucket(&palette[i], &paletteArray[i]); |       avg_color_from_color_bucket(&palette[i], &paletteArray[i]); | ||||||
|  | @ -393,7 +403,9 @@ int quantize_octree(Pixel *pixelData, | ||||||
|    /* create fine cube */ |    /* create fine cube */ | ||||||
|    fineCube = new_color_cube(cubeBits[0], cubeBits[1], |    fineCube = new_color_cube(cubeBits[0], cubeBits[1], | ||||||
|                              cubeBits[2], cubeBits[3]); |                              cubeBits[2], cubeBits[3]); | ||||||
|    if (!fineCube) goto error; |    if (!fineCube) { | ||||||
|  |        goto error; | ||||||
|  |    } | ||||||
|    for (i=0; i<nPixels; i++) { |    for (i=0; i<nPixels; i++) { | ||||||
|       add_color_to_color_cube(fineCube, &pixelData[i]); |       add_color_to_color_cube(fineCube, &pixelData[i]); | ||||||
|    } |    } | ||||||
|  | @ -401,19 +413,24 @@ int quantize_octree(Pixel *pixelData, | ||||||
|    /* create coarse cube */ |    /* create coarse cube */ | ||||||
|    coarseCube = copy_color_cube(fineCube, cubeBits[4], cubeBits[5], |    coarseCube = copy_color_cube(fineCube, cubeBits[4], cubeBits[5], | ||||||
|                                           cubeBits[6], cubeBits[7]); |                                           cubeBits[6], cubeBits[7]); | ||||||
|    if (!coarseCube) goto error; |    if (!coarseCube) { | ||||||
|  |        goto error; | ||||||
|  |    } | ||||||
|    nCoarseColors = count_used_color_buckets(coarseCube); |    nCoarseColors = count_used_color_buckets(coarseCube); | ||||||
| 
 | 
 | ||||||
|    /* limit to nQuantPixels */ |    /* limit to nQuantPixels */ | ||||||
|    if (nCoarseColors > nQuantPixels) |    if (nCoarseColors > nQuantPixels) { | ||||||
|       nCoarseColors = nQuantPixels; |       nCoarseColors = nQuantPixels; | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    /* how many space do we have in our palette for fine colors? */ |    /* how many space do we have in our palette for fine colors? */ | ||||||
|    nFineColors = nQuantPixels - nCoarseColors; |    nFineColors = nQuantPixels - nCoarseColors; | ||||||
| 
 | 
 | ||||||
|    /* create fine color palette */ |    /* create fine color palette */ | ||||||
|    paletteBucketsFine = create_sorted_color_palette(fineCube); |    paletteBucketsFine = create_sorted_color_palette(fineCube); | ||||||
|    if (!paletteBucketsFine) goto error; |    if (!paletteBucketsFine) { | ||||||
|  |        goto error; | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    /* remove the used fine colors from the coarse cube */ |    /* remove the used fine colors from the coarse cube */ | ||||||
|    subtract_color_buckets(coarseCube, paletteBucketsFine, nFineColors); |    subtract_color_buckets(coarseCube, paletteBucketsFine, nFineColors); | ||||||
|  | @ -430,7 +447,9 @@ int quantize_octree(Pixel *pixelData, | ||||||
| 
 | 
 | ||||||
|    /* create our palette buckets with fine and coarse combined */ |    /* create our palette buckets with fine and coarse combined */ | ||||||
|    paletteBucketsCoarse = create_sorted_color_palette(coarseCube); |    paletteBucketsCoarse = create_sorted_color_palette(coarseCube); | ||||||
|    if (!paletteBucketsCoarse) goto error; |    if (!paletteBucketsCoarse) { | ||||||
|  |        goto error; | ||||||
|  |    } | ||||||
|    paletteBuckets = combined_palette(paletteBucketsCoarse, nCoarseColors, |    paletteBuckets = combined_palette(paletteBucketsCoarse, nCoarseColors, | ||||||
|                                      paletteBucketsFine, nFineColors); |                                      paletteBucketsFine, nFineColors); | ||||||
| 
 | 
 | ||||||
|  | @ -438,19 +457,25 @@ int quantize_octree(Pixel *pixelData, | ||||||
|    paletteBucketsFine = NULL; |    paletteBucketsFine = NULL; | ||||||
|    free(paletteBucketsCoarse); |    free(paletteBucketsCoarse); | ||||||
|    paletteBucketsCoarse = NULL; |    paletteBucketsCoarse = NULL; | ||||||
|    if (!paletteBuckets) goto error; |    if (!paletteBuckets) { | ||||||
|  |        goto error; | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    /* add all coarse colors to our coarse lookup cube. */ |    /* add all coarse colors to our coarse lookup cube. */ | ||||||
|    coarseLookupCube = new_color_cube(cubeBits[4], cubeBits[5], |    coarseLookupCube = new_color_cube(cubeBits[4], cubeBits[5], | ||||||
|                                      cubeBits[6], cubeBits[7]); |                                      cubeBits[6], cubeBits[7]); | ||||||
|    if (!coarseLookupCube) goto error; |    if (!coarseLookupCube) { | ||||||
|  |        goto error; | ||||||
|  |    } | ||||||
|    add_lookup_buckets(coarseLookupCube, paletteBuckets, nCoarseColors, 0); |    add_lookup_buckets(coarseLookupCube, paletteBuckets, nCoarseColors, 0); | ||||||
| 
 | 
 | ||||||
|    /* expand coarse cube (64) to larger fine cube (4k). the value of each
 |    /* expand coarse cube (64) to larger fine cube (4k). the value of each
 | ||||||
|       coarse bucket is then present in the according 64 fine buckets. */ |       coarse bucket is then present in the according 64 fine buckets. */ | ||||||
|    lookupCube = copy_color_cube(coarseLookupCube, cubeBits[0], cubeBits[1], |    lookupCube = copy_color_cube(coarseLookupCube, cubeBits[0], cubeBits[1], | ||||||
|                                                   cubeBits[2], cubeBits[3]); |                                                   cubeBits[2], cubeBits[3]); | ||||||
|    if (!lookupCube) goto error; |    if (!lookupCube) { | ||||||
|  |        goto error; | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    /* add fine colors to the lookup cube */ |    /* add fine colors to the lookup cube */ | ||||||
|    add_lookup_buckets(lookupCube, paletteBuckets, nFineColors, nCoarseColors); |    add_lookup_buckets(lookupCube, paletteBuckets, nFineColors, nCoarseColors); | ||||||
|  | @ -458,12 +483,16 @@ int quantize_octree(Pixel *pixelData, | ||||||
|    /* create result pixels and map palette indices */ |    /* create result pixels and map palette indices */ | ||||||
|    /* malloc check ok, calloc for overflow */ |    /* malloc check ok, calloc for overflow */ | ||||||
|    qp = calloc(nPixels, sizeof(Pixel)); |    qp = calloc(nPixels, sizeof(Pixel)); | ||||||
|    if (!qp) goto error; |    if (!qp) { | ||||||
|  |        goto error; | ||||||
|  |    } | ||||||
|    map_image_pixels(pixelData, nPixels, lookupCube, qp); |    map_image_pixels(pixelData, nPixels, lookupCube, qp); | ||||||
| 
 | 
 | ||||||
|    /* convert palette buckets to RGB pixel palette */ |    /* convert palette buckets to RGB pixel palette */ | ||||||
|    *palette = create_palette_array(paletteBuckets, nQuantPixels); |    *palette = create_palette_array(paletteBuckets, nQuantPixels); | ||||||
|    if (!(*palette)) goto error; |    if (!(*palette)) { | ||||||
|  |        goto error; | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    *quantizedPixels = qp; |    *quantizedPixels = qp; | ||||||
|    *paletteLength = nQuantPixels; |    *paletteLength = nQuantPixels; | ||||||
|  |  | ||||||
|  | @ -95,9 +95,15 @@ quantize_pngquant( | ||||||
|     result = 1; |     result = 1; | ||||||
| 
 | 
 | ||||||
| err: | err: | ||||||
|     if (attr) liq_attr_destroy(attr); |     if (attr) { | ||||||
|     if (image) liq_image_destroy(image); |         liq_attr_destroy(attr); | ||||||
|     if (remap) liq_result_destroy(remap); |     } | ||||||
|  |     if (image) { | ||||||
|  |         liq_image_destroy(image); | ||||||
|  |     } | ||||||
|  |     if (remap) { | ||||||
|  |         liq_result_destroy(remap); | ||||||
|  |     } | ||||||
|     free(charMatrix); |     free(charMatrix); | ||||||
|     free(charMatrixRows); |     free(charMatrixRows); | ||||||
|     if (!result)  { |     if (!result)  { | ||||||
|  |  | ||||||
|  | @ -30,15 +30,23 @@ static type Rank##type(type a[], int n, int k)\ | ||||||
|         i = l;\ |         i = l;\ | ||||||
|         j = m;\ |         j = m;\ | ||||||
|         do {\ |         do {\ | ||||||
|             while (a[i] < x) i++;\ |             while (a[i] < x) {\ | ||||||
|             while (x < a[j]) j--;\ |                 i++;\ | ||||||
|  |             }\ | ||||||
|  |             while (x < a[j]) {\ | ||||||
|  |                 j--;\ | ||||||
|  |             }\ | ||||||
|             if (i <= j) {\ |             if (i <= j) {\ | ||||||
|                 SWAP(type, a[i], a[j]);\ |                 SWAP(type, a[i], a[j]);\ | ||||||
|                 i++; j--;\ |                 i++; j--;\ | ||||||
|             }\ |             }\ | ||||||
|         } while (i <= j);\ |         } while (i <= j);\ | ||||||
|         if (j < k) l = i;\ |         if (j < k) {\ | ||||||
|         if (k < i) m = j;\ |             l = i;\ | ||||||
|  |         }\ | ||||||
|  |         if (k < i) {\ | ||||||
|  |             m = j;\ | ||||||
|  |         }\ | ||||||
|     }\ |     }\ | ||||||
|     return a[k];\ |     return a[k];\ | ||||||
| } | } | ||||||
|  | @ -54,11 +62,13 @@ ImagingRankFilter(Imaging im, int size, int rank) | ||||||
|     int x, y; |     int x, y; | ||||||
|     int i, margin, size2; |     int i, margin, size2; | ||||||
| 
 | 
 | ||||||
|     if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL) |     if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!(size & 1)) |     if (!(size & 1)) { | ||||||
|         return (Imaging) ImagingError_ValueError("bad filter size"); |         return (Imaging) ImagingError_ValueError("bad filter size"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* malloc check ok, for overflow in the define below */ |     /* malloc check ok, for overflow in the define below */ | ||||||
|     if (size > INT_MAX / size || |     if (size > INT_MAX / size || | ||||||
|  | @ -69,35 +79,40 @@ ImagingRankFilter(Imaging im, int size, int rank) | ||||||
|     size2 = size * size; |     size2 = size * size; | ||||||
|     margin = (size-1) / 2; |     margin = (size-1) / 2; | ||||||
| 
 | 
 | ||||||
|     if (rank < 0 || rank >= size2) |     if (rank < 0 || rank >= size2) { | ||||||
|         return (Imaging) ImagingError_ValueError("bad rank value"); |         return (Imaging) ImagingError_ValueError("bad rank value"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNew(im->mode, im->xsize - 2*margin, im->ysize - 2*margin); |     imOut = ImagingNew(im->mode, im->xsize - 2*margin, im->ysize - 2*margin); | ||||||
|     if (!imOut) |     if (!imOut) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* malloc check ok, checked above */ |     /* malloc check ok, checked above */ | ||||||
| #define RANK_BODY(type) do {\ | #define RANK_BODY(type) do {\ | ||||||
|     type* buf = malloc(size2 * sizeof(type));\ |     type* buf = malloc(size2 * sizeof(type));\ | ||||||
|     if (!buf)\ |     if (!buf) {\ | ||||||
|         goto nomemory;\ |         goto nomemory;\ | ||||||
|     for (y = 0; y < imOut->ysize; y++)\ |     }\ | ||||||
|  |     for (y = 0; y < imOut->ysize; y++) {\ | ||||||
|         for (x = 0; x < imOut->xsize; x++) {\ |         for (x = 0; x < imOut->xsize; x++) {\ | ||||||
|             for (i = 0; i < size; i++)\ |             for (i = 0; i < size; i++) {\ | ||||||
|                 memcpy(buf + i*size, &IMAGING_PIXEL_##type(im, x, y+i),\ |                 memcpy(buf + i*size, &IMAGING_PIXEL_##type(im, x, y+i),\ | ||||||
|                        size * sizeof(type));\ |                        size * sizeof(type));\ | ||||||
|  |             }\ | ||||||
|             IMAGING_PIXEL_##type(imOut, x, y) = Rank##type(buf, size2, rank);\ |             IMAGING_PIXEL_##type(imOut, x, y) = Rank##type(buf, size2, rank);\ | ||||||
|         }\ |         }\ | ||||||
|  |     }\ | ||||||
|     free(buf); \ |     free(buf); \ | ||||||
| } while (0) | } while (0) | ||||||
| 
 | 
 | ||||||
|     if (im->image8) |     if (im->image8) { | ||||||
|         RANK_BODY(UINT8); |         RANK_BODY(UINT8); | ||||||
|     else if (im->type == IMAGING_TYPE_INT32) |     } else if (im->type == IMAGING_TYPE_INT32) { | ||||||
|         RANK_BODY(INT32); |         RANK_BODY(INT32); | ||||||
|     else if (im->type == IMAGING_TYPE_FLOAT32) |     } else if (im->type == IMAGING_TYPE_FLOAT32) { | ||||||
|         RANK_BODY(FLOAT32); |         RANK_BODY(FLOAT32); | ||||||
|     else { |     } else { | ||||||
|         /* safety net (we shouldn't end up here) */ |         /* safety net (we shouldn't end up here) */ | ||||||
|         ImagingDelete(imOut); |         ImagingDelete(imOut); | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |  | ||||||
|  | @ -47,8 +47,9 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|         if (state->ystep < 0) { |         if (state->ystep < 0) { | ||||||
|             state->y = state->ysize-1; |             state->y = state->ysize-1; | ||||||
|             state->ystep = -1; |             state->ystep = -1; | ||||||
|         } else |         } else { | ||||||
|             state->ystep = 1; |             state->ystep = 1; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         state->state = LINE; |         state->state = LINE; | ||||||
| 
 | 
 | ||||||
|  | @ -62,8 +63,9 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
| 
 | 
 | ||||||
|             /* Skip padding between lines */ |             /* Skip padding between lines */ | ||||||
| 
 | 
 | ||||||
|             if (bytes < rawstate->skip) |             if (bytes < rawstate->skip) { | ||||||
|                 return ptr - buf; |                 return ptr - buf; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             ptr += rawstate->skip; |             ptr += rawstate->skip; | ||||||
|             bytes -= rawstate->skip; |             bytes -= rawstate->skip; | ||||||
|  | @ -72,8 +74,9 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
| 
 | 
 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (bytes < state->bytes) |         if (bytes < state->bytes) { | ||||||
|             return ptr - buf; |             return ptr - buf; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         /* Unpack data */ |         /* Unpack data */ | ||||||
|         state->shuffle((UINT8*) im->image[state->y + state->yoff] + |         state->shuffle((UINT8*) im->image[state->y + state->yoff] + | ||||||
|  |  | ||||||
|  | @ -41,16 +41,18 @@ ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|             } |             } | ||||||
|             state->count = state->bytes; |             state->count = state->bytes; | ||||||
|             state->bytes = bytes; |             state->bytes = bytes; | ||||||
|         } else |         } else { | ||||||
|             state->count = state->bytes; |             state->count = state->bytes; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         /* The "ystep" field specifies the orientation */ |         /* The "ystep" field specifies the orientation */ | ||||||
| 
 | 
 | ||||||
|         if (state->ystep < 0) { |         if (state->ystep < 0) { | ||||||
|             state->y = state->ysize-1; |             state->y = state->ysize-1; | ||||||
|             state->ystep = -1; |             state->ystep = -1; | ||||||
|         } else |         } else { | ||||||
|             state->ystep = 1; |             state->ystep = 1; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         state->state = 1; |         state->state = 1; | ||||||
| 
 | 
 | ||||||
|  | @ -68,9 +70,10 @@ ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|         state->shuffle(ptr, (UINT8*) im->image[state->y + state->yoff] + |         state->shuffle(ptr, (UINT8*) im->image[state->y + state->yoff] + | ||||||
|                    state->xoff * im->pixelsize, state->xsize); |                    state->xoff * im->pixelsize, state->xsize); | ||||||
| 
 | 
 | ||||||
|         if (state->bytes > state->count) |         if (state->bytes > state->count) { | ||||||
|             /* zero-pad the buffer, if necessary */ |             /* zero-pad the buffer, if necessary */ | ||||||
|             memset(ptr + state->count, 0, state->bytes - state->count); |             memset(ptr + state->count, 0, state->bytes - state->count); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         ptr += state->bytes; |         ptr += state->bytes; | ||||||
|         bytes -= state->bytes; |         bytes -= state->bytes; | ||||||
|  |  | ||||||
|  | @ -1374,11 +1374,13 @@ ImagingReduce(Imaging imIn, int xscale, int yscale, int box[4]) | ||||||
|     ImagingSectionCookie cookie; |     ImagingSectionCookie cookie; | ||||||
|     Imaging imOut = NULL; |     Imaging imOut = NULL; | ||||||
| 
 | 
 | ||||||
|     if (strcmp(imIn->mode, "P") == 0 || strcmp(imIn->mode, "1") == 0) |     if (strcmp(imIn->mode, "P") == 0 || strcmp(imIn->mode, "1") == 0) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (imIn->type == IMAGING_TYPE_SPECIAL) |     if (imIn->type == IMAGING_TYPE_SPECIAL) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     imOut = ImagingNewDirty(imIn->mode, |     imOut = ImagingNewDirty(imIn->mode, | ||||||
|                             (box[2] + xscale - 1) / xscale, |                             (box[2] + xscale - 1) / xscale, | ||||||
|  |  | ||||||
|  | @ -13,28 +13,34 @@ struct filter { | ||||||
| 
 | 
 | ||||||
| static inline double box_filter(double x) | static inline double box_filter(double x) | ||||||
| { | { | ||||||
|     if (x > -0.5 && x <= 0.5) |     if (x > -0.5 && x <= 0.5) { | ||||||
|         return 1.0; |         return 1.0; | ||||||
|  |     } | ||||||
|     return 0.0; |     return 0.0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline double bilinear_filter(double x) | static inline double bilinear_filter(double x) | ||||||
| { | { | ||||||
|     if (x < 0.0) |     if (x < 0.0) { | ||||||
|         x = -x; |         x = -x; | ||||||
|     if (x < 1.0) |     } | ||||||
|  |     if (x < 1.0) { | ||||||
|         return 1.0-x; |         return 1.0-x; | ||||||
|  |     } | ||||||
|     return 0.0; |     return 0.0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline double hamming_filter(double x) | static inline double hamming_filter(double x) | ||||||
| { | { | ||||||
|     if (x < 0.0) |     if (x < 0.0) { | ||||||
|         x = -x; |         x = -x; | ||||||
|     if (x == 0.0) |     } | ||||||
|  |     if (x == 0.0) { | ||||||
|         return 1.0; |         return 1.0; | ||||||
|     if (x >= 1.0) |     } | ||||||
|  |     if (x >= 1.0) { | ||||||
|         return 0.0; |         return 0.0; | ||||||
|  |     } | ||||||
|     x = x * M_PI; |     x = x * M_PI; | ||||||
|     return sin(x) / x * (0.54f + 0.46f * cos(x)); |     return sin(x) / x * (0.54f + 0.46f * cos(x)); | ||||||
| } | } | ||||||
|  | @ -43,20 +49,24 @@ static inline double bicubic_filter(double x) | ||||||
| { | { | ||||||
|     /* https://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm */ |     /* https://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm */ | ||||||
| #define a -0.5 | #define a -0.5 | ||||||
|     if (x < 0.0) |     if (x < 0.0) { | ||||||
|         x = -x; |         x = -x; | ||||||
|     if (x < 1.0) |     } | ||||||
|  |     if (x < 1.0) { | ||||||
|         return ((a + 2.0) * x - (a + 3.0)) * x*x + 1; |         return ((a + 2.0) * x - (a + 3.0)) * x*x + 1; | ||||||
|     if (x < 2.0) |     } | ||||||
|  |     if (x < 2.0) { | ||||||
|         return (((x - 5) * x + 8) * x - 4) * a; |         return (((x - 5) * x + 8) * x - 4) * a; | ||||||
|  |     } | ||||||
|     return 0.0; |     return 0.0; | ||||||
| #undef a | #undef a | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline double sinc_filter(double x) | static inline double sinc_filter(double x) | ||||||
| { | { | ||||||
|     if (x == 0.0) |     if (x == 0.0) { | ||||||
|         return 1.0; |         return 1.0; | ||||||
|  |     } | ||||||
|     x = x * M_PI; |     x = x * M_PI; | ||||||
|     return sin(x) / x; |     return sin(x) / x; | ||||||
| } | } | ||||||
|  | @ -64,8 +74,9 @@ static inline double sinc_filter(double x) | ||||||
| static inline double lanczos_filter(double x) | static inline double lanczos_filter(double x) | ||||||
| { | { | ||||||
|     /* truncated sinc */ |     /* truncated sinc */ | ||||||
|     if (-3.0 <= x && x < 3.0) |     if (-3.0 <= x && x < 3.0) { | ||||||
|         return sinc_filter(x) * sinc_filter(x/3); |         return sinc_filter(x) * sinc_filter(x/3); | ||||||
|  |     } | ||||||
|     return 0.0; |     return 0.0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -224,12 +235,14 @@ precompute_coeffs(int inSize, float in0, float in1, int outSize, | ||||||
|         ss = 1.0 / filterscale; |         ss = 1.0 / filterscale; | ||||||
|         // Round the value
 |         // Round the value
 | ||||||
|         xmin = (int) (center - support + 0.5); |         xmin = (int) (center - support + 0.5); | ||||||
|         if (xmin < 0) |         if (xmin < 0) { | ||||||
|             xmin = 0; |             xmin = 0; | ||||||
|  |         } | ||||||
|         // Round the value
 |         // Round the value
 | ||||||
|         xmax = (int) (center + support + 0.5); |         xmax = (int) (center + support + 0.5); | ||||||
|         if (xmax > inSize) |         if (xmax > inSize) { | ||||||
|             xmax = inSize; |             xmax = inSize; | ||||||
|  |         } | ||||||
|         xmax -= xmin; |         xmax -= xmin; | ||||||
|         k = &kk[xx * ksize]; |         k = &kk[xx * ksize]; | ||||||
|         for (x = 0; x < xmax; x++) { |         for (x = 0; x < xmax; x++) { | ||||||
|  | @ -238,8 +251,9 @@ precompute_coeffs(int inSize, float in0, float in1, int outSize, | ||||||
|             ww += w; |             ww += w; | ||||||
|         } |         } | ||||||
|         for (x = 0; x < xmax; x++) { |         for (x = 0; x < xmax; x++) { | ||||||
|             if (ww != 0.0) |             if (ww != 0.0) { | ||||||
|                 k[x] /= ww; |                 k[x] /= ww; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         // Remaining values should stay empty if they are used despite of xmax.
 |         // Remaining values should stay empty if they are used despite of xmax.
 | ||||||
|         for (; x < ksize; x++) { |         for (; x < ksize; x++) { | ||||||
|  | @ -295,8 +309,9 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset, | ||||||
|                 xmax = bounds[xx * 2 + 1]; |                 xmax = bounds[xx * 2 + 1]; | ||||||
|                 k = &kk[xx * ksize]; |                 k = &kk[xx * ksize]; | ||||||
|                 ss0 = 1 << (PRECISION_BITS -1); |                 ss0 = 1 << (PRECISION_BITS -1); | ||||||
|                 for (x = 0; x < xmax; x++) |                 for (x = 0; x < xmax; x++) { | ||||||
|                     ss0 += ((UINT8) imIn->image8[yy + offset][x + xmin]) * k[x]; |                     ss0 += ((UINT8) imIn->image8[yy + offset][x + xmin]) * k[x]; | ||||||
|  |                 } | ||||||
|                 imOut->image8[yy][xx] = clip8(ss0); |                 imOut->image8[yy][xx] = clip8(ss0); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -379,8 +394,9 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset, | ||||||
|             ymax = bounds[yy * 2 + 1]; |             ymax = bounds[yy * 2 + 1]; | ||||||
|             for (xx = 0; xx < imOut->xsize; xx++) { |             for (xx = 0; xx < imOut->xsize; xx++) { | ||||||
|                 ss0 = 1 << (PRECISION_BITS -1); |                 ss0 = 1 << (PRECISION_BITS -1); | ||||||
|                 for (y = 0; y < ymax; y++) |                 for (y = 0; y < ymax; y++) { | ||||||
|                     ss0 += ((UINT8) imIn->image8[y + ymin][xx]) * k[y]; |                     ss0 += ((UINT8) imIn->image8[y + ymin][xx]) * k[y]; | ||||||
|  |                 } | ||||||
|                 imOut->image8[yy][xx] = clip8(ss0); |                 imOut->image8[yy][xx] = clip8(ss0); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -460,8 +476,9 @@ ImagingResampleHorizontal_32bpc(Imaging imOut, Imaging imIn, int offset, | ||||||
|                     xmax = bounds[xx * 2 + 1]; |                     xmax = bounds[xx * 2 + 1]; | ||||||
|                     k = &kk[xx * ksize]; |                     k = &kk[xx * ksize]; | ||||||
|                     ss = 0.0; |                     ss = 0.0; | ||||||
|                     for (x = 0; x < xmax; x++) |                     for (x = 0; x < xmax; x++) { | ||||||
|                         ss += IMAGING_PIXEL_I(imIn, x + xmin, yy + offset) * k[x]; |                         ss += IMAGING_PIXEL_I(imIn, x + xmin, yy + offset) * k[x]; | ||||||
|  |                     } | ||||||
|                     IMAGING_PIXEL_I(imOut, xx, yy) = ROUND_UP(ss); |                     IMAGING_PIXEL_I(imOut, xx, yy) = ROUND_UP(ss); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -474,8 +491,9 @@ ImagingResampleHorizontal_32bpc(Imaging imOut, Imaging imIn, int offset, | ||||||
|                     xmax = bounds[xx * 2 + 1]; |                     xmax = bounds[xx * 2 + 1]; | ||||||
|                     k = &kk[xx * ksize]; |                     k = &kk[xx * ksize]; | ||||||
|                     ss = 0.0; |                     ss = 0.0; | ||||||
|                     for (x = 0; x < xmax; x++) |                     for (x = 0; x < xmax; x++) { | ||||||
|                         ss += IMAGING_PIXEL_F(imIn, x + xmin, yy + offset) * k[x]; |                         ss += IMAGING_PIXEL_F(imIn, x + xmin, yy + offset) * k[x]; | ||||||
|  |                     } | ||||||
|                     IMAGING_PIXEL_F(imOut, xx, yy) = ss; |                     IMAGING_PIXEL_F(imOut, xx, yy) = ss; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -503,8 +521,9 @@ ImagingResampleVertical_32bpc(Imaging imOut, Imaging imIn, int offset, | ||||||
|                 k = &kk[yy * ksize]; |                 k = &kk[yy * ksize]; | ||||||
|                 for (xx = 0; xx < imOut->xsize; xx++) { |                 for (xx = 0; xx < imOut->xsize; xx++) { | ||||||
|                     ss = 0.0; |                     ss = 0.0; | ||||||
|                     for (y = 0; y < ymax; y++) |                     for (y = 0; y < ymax; y++) { | ||||||
|                         ss += IMAGING_PIXEL_I(imIn, xx, y + ymin) * k[y]; |                         ss += IMAGING_PIXEL_I(imIn, xx, y + ymin) * k[y]; | ||||||
|  |                     } | ||||||
|                     IMAGING_PIXEL_I(imOut, xx, yy) = ROUND_UP(ss); |                     IMAGING_PIXEL_I(imOut, xx, yy) = ROUND_UP(ss); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -517,8 +536,9 @@ ImagingResampleVertical_32bpc(Imaging imOut, Imaging imIn, int offset, | ||||||
|                 k = &kk[yy * ksize]; |                 k = &kk[yy * ksize]; | ||||||
|                 for (xx = 0; xx < imOut->xsize; xx++) { |                 for (xx = 0; xx < imOut->xsize; xx++) { | ||||||
|                     ss = 0.0; |                     ss = 0.0; | ||||||
|                     for (y = 0; y < ymax; y++) |                     for (y = 0; y < ymax; y++) { | ||||||
|                         ss += IMAGING_PIXEL_F(imIn, xx, y + ymin) * k[y]; |                         ss += IMAGING_PIXEL_F(imIn, xx, y + ymin) * k[y]; | ||||||
|  |                     } | ||||||
|                     IMAGING_PIXEL_F(imOut, xx, yy) = ss; |                     IMAGING_PIXEL_F(imOut, xx, yy) = ss; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -546,8 +566,9 @@ ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4]) | ||||||
|     ResampleFunction ResampleHorizontal; |     ResampleFunction ResampleHorizontal; | ||||||
|     ResampleFunction ResampleVertical; |     ResampleFunction ResampleVertical; | ||||||
| 
 | 
 | ||||||
|     if (strcmp(imIn->mode, "P") == 0 || strcmp(imIn->mode, "1") == 0) |     if (strcmp(imIn->mode, "P") == 0 || strcmp(imIn->mode, "1") == 0) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (imIn->type == IMAGING_TYPE_SPECIAL) { |     if (imIn->type == IMAGING_TYPE_SPECIAL) { | ||||||
|         return (Imaging) ImagingError_ModeError(); |         return (Imaging) ImagingError_ModeError(); | ||||||
|  |  | ||||||
|  | @ -33,11 +33,13 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) | ||||||
|     for (;n > 0; n--) |     for (;n > 0; n--) | ||||||
|     { |     { | ||||||
|         pixel = *src++; |         pixel = *src++; | ||||||
|         if (n == 1 && pixel != 0) |         if (n == 1 && pixel != 0) { | ||||||
|             return n; |             return n; | ||||||
|  |         } | ||||||
|         count = pixel & RLE_MAX_RUN; |         count = pixel & RLE_MAX_RUN; | ||||||
|         if (!count) |         if (!count) { | ||||||
|             return count; |             return count; | ||||||
|  |         } | ||||||
|         if (x + count > xsize) { |         if (x + count > xsize) { | ||||||
|             return -1; |             return -1; | ||||||
|         } |         } | ||||||
|  | @ -71,11 +73,13 @@ static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize) | ||||||
|     { |     { | ||||||
|         pixel = src[1]; |         pixel = src[1]; | ||||||
|         src+=2; |         src+=2; | ||||||
|         if (n == 1 && pixel != 0) |         if (n == 1 && pixel != 0) { | ||||||
|             return n; |             return n; | ||||||
|  |         } | ||||||
|         count = pixel & RLE_MAX_RUN; |         count = pixel & RLE_MAX_RUN; | ||||||
|         if (!count) |         if (!count) { | ||||||
|             return count; |             return count; | ||||||
|  |         } | ||||||
|         if (x + count > xsize) { |         if (x + count > xsize) { | ||||||
|             return -1; |             return -1; | ||||||
|         } |         } | ||||||
|  | @ -151,11 +155,13 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, | ||||||
|         goto sgi_finish_decode; |         goto sgi_finish_decode; | ||||||
|     } |     } | ||||||
|     /* populate offsets table */ |     /* populate offsets table */ | ||||||
|     for (c->tabindex = 0, c->bufindex = 0; c->tabindex < c->tablen; c->tabindex++, c->bufindex+=4) |     for (c->tabindex = 0, c->bufindex = 0; c->tabindex < c->tablen; c->tabindex++, c->bufindex+=4) { | ||||||
|         read4B(&c->starttab[c->tabindex], &ptr[c->bufindex]); |         read4B(&c->starttab[c->tabindex], &ptr[c->bufindex]); | ||||||
|  |     } | ||||||
|     /* populate lengths table */ |     /* populate lengths table */ | ||||||
|     for (c->tabindex = 0, c->bufindex = c->tablen * sizeof(UINT32); c->tabindex < c->tablen; c->tabindex++, c->bufindex+=4) |     for (c->tabindex = 0, c->bufindex = c->tablen * sizeof(UINT32); c->tabindex < c->tablen; c->tabindex++, c->bufindex+=4) { | ||||||
|         read4B(&c->lengthtab[c->tabindex], &ptr[c->bufindex]); |         read4B(&c->lengthtab[c->tabindex], &ptr[c->bufindex]); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     state->count += c->tablen * sizeof(UINT32) * 2; |     state->count += c->tablen * sizeof(UINT32) * 2; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -244,17 +244,21 @@ ImagingNewPrologue(const char *mode, int xsize, int ysize) | ||||||
| void | void | ||||||
| ImagingDelete(Imaging im) | ImagingDelete(Imaging im) | ||||||
| { | { | ||||||
|     if (!im) |     if (!im) { | ||||||
|         return; |         return; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (im->palette) |     if (im->palette) { | ||||||
|         ImagingPaletteDelete(im->palette); |         ImagingPaletteDelete(im->palette); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (im->destroy) |     if (im->destroy) { | ||||||
|         im->destroy(im); |         im->destroy(im); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (im->image) |     if (im->image) { | ||||||
|         free(im->image); |         free(im->image); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     free(im); |     free(im); | ||||||
| } | } | ||||||
|  | @ -399,8 +403,9 @@ ImagingAllocateArray(Imaging im, int dirty, int block_size) | ||||||
| 
 | 
 | ||||||
|     aligned_linesize = (im->linesize + arena->alignment - 1) & -arena->alignment; |     aligned_linesize = (im->linesize + arena->alignment - 1) & -arena->alignment; | ||||||
|     lines_per_block = (block_size - (arena->alignment - 1)) / aligned_linesize; |     lines_per_block = (block_size - (arena->alignment - 1)) / aligned_linesize; | ||||||
|     if (lines_per_block == 0) |     if (lines_per_block == 0) { | ||||||
|         lines_per_block = 1; |         lines_per_block = 1; | ||||||
|  |     } | ||||||
|     blocks_count = (im->ysize + lines_per_block - 1) / lines_per_block; |     blocks_count = (im->ysize + lines_per_block - 1) / lines_per_block; | ||||||
|     // printf("NEW size: %dx%d, ls: %d, lpb: %d, blocks: %d\n",
 |     // printf("NEW size: %dx%d, ls: %d, lpb: %d, blocks: %d\n",
 | ||||||
|     //        im->xsize, im->ysize, aligned_linesize, lines_per_block, blocks_count);
 |     //        im->xsize, im->ysize, aligned_linesize, lines_per_block, blocks_count);
 | ||||||
|  | @ -457,8 +462,9 @@ ImagingAllocateArray(Imaging im, int dirty, int block_size) | ||||||
| static void | static void | ||||||
| ImagingDestroyBlock(Imaging im) | ImagingDestroyBlock(Imaging im) | ||||||
| { | { | ||||||
|     if (im->block) |     if (im->block) { | ||||||
|         free(im->block); |         free(im->block); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Imaging | Imaging | ||||||
|  | @ -510,8 +516,9 @@ ImagingNewInternal(const char* mode, int xsize, int ysize, int dirty) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     im = ImagingNewPrologue(mode, xsize, ysize); |     im = ImagingNewPrologue(mode, xsize, ysize); | ||||||
|     if ( ! im) |     if ( ! im) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (ImagingAllocateArray(im, dirty, ImagingDefaultArena.block_size)) { |     if (ImagingAllocateArray(im, dirty, ImagingDefaultArena.block_size)) { | ||||||
|         return im; |         return im; | ||||||
|  | @ -550,8 +557,9 @@ ImagingNewBlock(const char* mode, int xsize, int ysize) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     im = ImagingNewPrologue(mode, xsize, ysize); |     im = ImagingNewPrologue(mode, xsize, ysize); | ||||||
|     if ( ! im) |     if ( ! im) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (ImagingAllocateBlock(im)) { |     if (ImagingAllocateBlock(im)) { | ||||||
|         return im; |         return im; | ||||||
|  | @ -576,8 +584,9 @@ ImagingNew2Dirty(const char* mode, Imaging imOut, Imaging imIn) | ||||||
|     } else { |     } else { | ||||||
|         /* create new image */ |         /* create new image */ | ||||||
|         imOut = ImagingNewDirty(mode, imIn->xsize, imIn->ysize); |         imOut = ImagingNewDirty(mode, imIn->xsize, imIn->ysize); | ||||||
|         if (!imOut) |         if (!imOut) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return imOut; |     return imOut; | ||||||
|  | @ -587,8 +596,9 @@ void | ||||||
| ImagingCopyPalette(Imaging destination, Imaging source) | ImagingCopyPalette(Imaging destination, Imaging source) | ||||||
| { | { | ||||||
|     if (source->palette) { |     if (source->palette) { | ||||||
|         if (destination->palette) |         if (destination->palette) { | ||||||
|             ImagingPaletteDelete(destination->palette); |             ImagingPaletteDelete(destination->palette); | ||||||
|  |         } | ||||||
|         destination->palette = ImagingPaletteDuplicate(source->palette); |         destination->palette = ImagingPaletteDuplicate(source->palette); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -31,13 +31,15 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t | ||||||
| 
 | 
 | ||||||
|     for (;;) { |     for (;;) { | ||||||
| 
 | 
 | ||||||
|         if (bytes < 1) |         if (bytes < 1) { | ||||||
|             return ptr - buf; |             return ptr - buf; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (ptr[0] == 0x80) { |         if (ptr[0] == 0x80) { | ||||||
| 
 | 
 | ||||||
|             if (bytes < 2) |             if (bytes < 2) { | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             n = ptr[1]; |             n = ptr[1]; | ||||||
| 
 | 
 | ||||||
|  | @ -55,8 +57,9 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t | ||||||
|             } else { |             } else { | ||||||
| 
 | 
 | ||||||
|                 /* Run (3 bytes) */ |                 /* Run (3 bytes) */ | ||||||
|                 if (bytes < 3) |                 if (bytes < 3) { | ||||||
|                     break; |                     break; | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|                 /* from (https://www.fileformat.info/format/sunraster/egff.htm)
 |                 /* from (https://www.fileformat.info/format/sunraster/egff.htm)
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,8 +33,9 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state, | ||||||
|         if (state->ystep < 0) { |         if (state->ystep < 0) { | ||||||
|             state->y = state->ysize-1; |             state->y = state->ysize-1; | ||||||
|             state->ystep = -1; |             state->ystep = -1; | ||||||
|         } else |         } else { | ||||||
|             state->ystep = 1; |             state->ystep = 1; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         state->state = 1; |         state->state = 1; | ||||||
| 
 | 
 | ||||||
|  | @ -44,15 +45,17 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state, | ||||||
| 
 | 
 | ||||||
|     for (;;) { |     for (;;) { | ||||||
| 
 | 
 | ||||||
|         if (bytes < 1) |         if (bytes < 1) { | ||||||
|             return ptr - buf; |             return ptr - buf; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (ptr[0] & 0x80) { |         if (ptr[0] & 0x80) { | ||||||
| 
 | 
 | ||||||
|             /* Run (1 + pixelsize bytes) */ |             /* Run (1 + pixelsize bytes) */ | ||||||
| 
 | 
 | ||||||
|             if (bytes < 1 + depth) |             if (bytes < 1 + depth) { | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             n = depth * ((ptr[0] & 0x7f) + 1); |             n = depth * ((ptr[0] & 0x7f) + 1); | ||||||
| 
 | 
 | ||||||
|  | @ -61,12 +64,13 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state, | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (depth == 1) |             if (depth == 1) { | ||||||
|                 memset(state->buffer + state->x, ptr[1], n); |                 memset(state->buffer + state->x, ptr[1], n); | ||||||
|             else { |             } else { | ||||||
|                 int i; |                 int i; | ||||||
|                 for (i = 0; i < n; i += depth) |                 for (i = 0; i < n; i += depth) { | ||||||
|                     memcpy(state->buffer + state->x + i, ptr+1, depth); |                     memcpy(state->buffer + state->x + i, ptr+1, depth); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             ptr += 1 + depth; |             ptr += 1 + depth; | ||||||
|  | @ -77,8 +81,9 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state, | ||||||
|             /* Literal (1+n+1 bytes block) */ |             /* Literal (1+n+1 bytes block) */ | ||||||
|             n = depth * (ptr[0] + 1); |             n = depth * (ptr[0] + 1); | ||||||
| 
 | 
 | ||||||
|             if (bytes < 1 + n) |             if (bytes < 1 + n) { | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             if (state->x + n > state->bytes) { |             if (state->x + n > state->bytes) { | ||||||
|                 state->errcode = IMAGING_CODEC_OVERRUN; |                 state->errcode = IMAGING_CODEC_OVERRUN; | ||||||
|  |  | ||||||
|  | @ -22,8 +22,9 @@ ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|         if (state->ystep < 0) { |         if (state->ystep < 0) { | ||||||
|             state->ystep = -1; |             state->ystep = -1; | ||||||
|             state->y = state->ysize - 1; |             state->y = state->ysize - 1; | ||||||
|         } else |         } else { | ||||||
|             state->ystep = 1; |             state->ystep = 1; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         state->state = 1; |         state->state = 1; | ||||||
|     } |     } | ||||||
|  | @ -46,8 +47,9 @@ ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|             assert(state->x <= state->xsize); |             assert(state->x <= state->xsize); | ||||||
| 
 | 
 | ||||||
|             /* Make sure we have space for the descriptor. */ |             /* Make sure we have space for the descriptor. */ | ||||||
|             if (bytes < 1) |             if (bytes < 1) { | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             if (state->x == state->xsize) { |             if (state->x == state->xsize) { | ||||||
|                 state->x = 0; |                 state->x = 0; | ||||||
|  | @ -59,12 +61,13 @@ ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (state->x == 0) |             if (state->x == 0) { | ||||||
|                 state->shuffle( |                 state->shuffle( | ||||||
|                     state->buffer, |                     state->buffer, | ||||||
|                     (UINT8*)im->image[state->y + state->yoff] |                     (UINT8*)im->image[state->y + state->yoff] | ||||||
|                         + state->xoff * im->pixelsize, |                         + state->xoff * im->pixelsize, | ||||||
|                     state->xsize); |                     state->xsize); | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             row = state->buffer; |             row = state->buffer; | ||||||
| 
 | 
 | ||||||
|  | @ -87,28 +90,32 @@ ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|                  */ |                  */ | ||||||
|                 maxLookup = state->x + 126; |                 maxLookup = state->x + 126; | ||||||
|                 /* A packet must not span multiple rows. */ |                 /* A packet must not span multiple rows. */ | ||||||
|                 if (maxLookup > state->xsize - 1) |                 if (maxLookup > state->xsize - 1) { | ||||||
|                     maxLookup = state->xsize - 1; |                     maxLookup = state->xsize - 1; | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|                 if (isRaw) { |                 if (isRaw) { | ||||||
|                     while (state->x < maxLookup) |                     while (state->x < maxLookup) { | ||||||
|                         if (!comparePixels(row, state->x, bytesPerPixel)) |                         if (!comparePixels(row, state->x, bytesPerPixel)) { | ||||||
|                             ++state->x; |                             ++state->x; | ||||||
|                         else { |                         } else { | ||||||
|                             /* Two identical pixels will go to RLE packet. */ |                             /* Two identical pixels will go to RLE packet. */ | ||||||
|                             --state->x; |                             --state->x; | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|  |                     } | ||||||
| 
 | 
 | ||||||
|                     state->count += (state->x - startX) * bytesPerPixel; |                     state->count += (state->x - startX) * bytesPerPixel; | ||||||
|                 } else { |                 } else { | ||||||
|                     descriptor |= 0x80; |                     descriptor |= 0x80; | ||||||
| 
 | 
 | ||||||
|                     while (state->x < maxLookup) |                     while (state->x < maxLookup) { | ||||||
|                         if (comparePixels(row, state->x, bytesPerPixel)) |                         if (comparePixels(row, state->x, bytesPerPixel)) { | ||||||
|                             ++state->x; |                             ++state->x; | ||||||
|                         else |                         } else { | ||||||
|                             break; |                             break; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -132,12 +139,14 @@ ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|         assert(state->x > 0); |         assert(state->x > 0); | ||||||
|         assert(state->count <= state->x * bytesPerPixel); |         assert(state->count <= state->x * bytesPerPixel); | ||||||
| 
 | 
 | ||||||
|         if (bytes == 0) |         if (bytes == 0) { | ||||||
|             break; |             break; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         flushCount = state->count; |         flushCount = state->count; | ||||||
|         if (flushCount > bytes) |         if (flushCount > bytes) { | ||||||
|             flushCount = bytes; |             flushCount = bytes; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         memcpy( |         memcpy( | ||||||
|             dst, |             dst, | ||||||
|  |  | ||||||
|  | @ -350,8 +350,9 @@ unpackLI(UINT8* out, const UINT8* in, int pixels) | ||||||
| { | { | ||||||
|     /* negative */ |     /* negative */ | ||||||
|     int i; |     int i; | ||||||
|     for (i = 0; i < pixels; i++) |     for (i = 0; i < pixels; i++) { | ||||||
|         out[i] = ~in[i]; |         out[i] = ~in[i]; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -1115,8 +1116,9 @@ static void NAME(UINT8* out_, const UINT8* in, int pixels)\ | ||||||
| {\ | {\ | ||||||
|     int i;\ |     int i;\ | ||||||
|     OUTTYPE* out = (OUTTYPE*) out_;\ |     OUTTYPE* out = (OUTTYPE*) out_;\ | ||||||
|     for (i = 0; i < pixels; i++, in += sizeof(INTYPE))\ |     for (i = 0; i < pixels; i++, in += sizeof(INTYPE)) {\ | ||||||
|         out[i] = (OUTTYPE) ((INTYPE) GET);\ |         out[i] = (OUTTYPE) ((INTYPE) GET);\ | ||||||
|  |     }\ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define UNPACK(NAME, COPY, INTYPE, OUTTYPE)\ | #define UNPACK(NAME, COPY, INTYPE, OUTTYPE)\ | ||||||
|  | @ -1521,13 +1523,15 @@ ImagingFindUnpacker(const char* mode, const char* rawmode, int* bits_out) | ||||||
|     int i; |     int i; | ||||||
| 
 | 
 | ||||||
|     /* find a suitable pixel unpacker */ |     /* find a suitable pixel unpacker */ | ||||||
|     for (i = 0; unpackers[i].rawmode; i++) |     for (i = 0; unpackers[i].rawmode; i++) { | ||||||
|         if (strcmp(unpackers[i].mode, mode) == 0 && |         if (strcmp(unpackers[i].mode, mode) == 0 && | ||||||
|             strcmp(unpackers[i].rawmode, rawmode) == 0) { |             strcmp(unpackers[i].rawmode, rawmode) == 0) { | ||||||
|             if (bits_out) |             if (bits_out) { | ||||||
|                 *bits_out = unpackers[i].bits; |                 *bits_out = unpackers[i].bits; | ||||||
|  |             } | ||||||
|             return unpackers[i].unpack; |             return unpackers[i].unpack; | ||||||
|         } |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* FIXME: configure a general unpacker based on the type codes... */ |     /* FIXME: configure a general unpacker based on the type codes... */ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,10 +14,12 @@ typedef UINT8 pixel[4]; | ||||||
| 
 | 
 | ||||||
| static inline UINT8 clip8(int in) | static inline UINT8 clip8(int in) | ||||||
| { | { | ||||||
|     if (in >= 255) |     if (in >= 255) { | ||||||
|        return 255; |        return 255; | ||||||
|     if (in <= 0) |     } | ||||||
|  |     if (in <= 0) { | ||||||
|         return 0; |         return 0; | ||||||
|  |     } | ||||||
|     return (UINT8) in; |     return (UINT8) in; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -39,8 +41,9 @@ ImagingUnsharpMask(Imaging imOut, Imaging imIn, float radius, int percent, | ||||||
|     /* First, do a gaussian blur on the image, putting results in imOut
 |     /* First, do a gaussian blur on the image, putting results in imOut
 | ||||||
|        temporarily. All format checks are in gaussian blur. */ |        temporarily. All format checks are in gaussian blur. */ | ||||||
|     result = ImagingGaussianBlur(imOut, imIn, radius, 3); |     result = ImagingGaussianBlur(imOut, imIn, radius, 3); | ||||||
|     if (!result) |     if (!result) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Now, go through each pixel, compare "normal" pixel to blurred
 |     /* Now, go through each pixel, compare "normal" pixel to blurred
 | ||||||
|        pixel. If the difference is more than threshold values, apply |        pixel. If the difference is more than threshold values, apply | ||||||
|  |  | ||||||
|  | @ -27,8 +27,9 @@ ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
| 
 | 
 | ||||||
|     UINT8* ptr; |     UINT8* ptr; | ||||||
| 
 | 
 | ||||||
|     if (!state->state) |     if (!state->state) { | ||||||
|         state->state = SKIP; |         state->state = SKIP; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ptr = buf; |     ptr = buf; | ||||||
| 
 | 
 | ||||||
|  | @ -39,21 +40,24 @@ ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|             /* Skip forward until next 'x' */ |             /* Skip forward until next 'x' */ | ||||||
| 
 | 
 | ||||||
|             while (bytes > 0) { |             while (bytes > 0) { | ||||||
|                 if (*ptr == 'x') |                 if (*ptr == 'x') { | ||||||
|                     break; |                     break; | ||||||
|  |                 } | ||||||
|                 ptr++; |                 ptr++; | ||||||
|                 bytes--; |                 bytes--; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (bytes == 0) |             if (bytes == 0) { | ||||||
|                 return ptr - buf; |                 return ptr - buf; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             state->state = BYTE; |             state->state = BYTE; | ||||||
| 
 | 
 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (bytes < 3) |         if (bytes < 3) { | ||||||
|             return ptr - buf; |             return ptr - buf; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         state->buffer[state->x] = (HEX(ptr[1])<<4) + HEX(ptr[2]); |         state->buffer[state->x] = (HEX(ptr[1])<<4) + HEX(ptr[2]); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -90,8 +90,9 @@ ImagingXbmEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|                     bytes--; |                     bytes--; | ||||||
|                     state->count = 0; |                     state->count = 0; | ||||||
|                     } |                     } | ||||||
|                 } else |                 } else { | ||||||
|                     *ptr++ = '\n'; |                     *ptr++ = '\n'; | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|                 bytes -= 5; |                 bytes -= 5; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -53,8 +53,9 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|     if (!state->state) { |     if (!state->state) { | ||||||
| 
 | 
 | ||||||
|         /* Initialization */ |         /* Initialization */ | ||||||
|         if (context->mode == ZIP_PNG || context->mode == ZIP_PNG_PALETTE) |         if (context->mode == ZIP_PNG || context->mode == ZIP_PNG_PALETTE) { | ||||||
|             context->prefix = 1; /* PNG */ |             context->prefix = 1; /* PNG */ | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         /* overflow check for malloc */ |         /* overflow check for malloc */ | ||||||
|         if (state->bytes > INT_MAX - 1) { |         if (state->bytes > INT_MAX - 1) { | ||||||
|  | @ -121,12 +122,13 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
| 
 | 
 | ||||||
|         if (err < 0) { |         if (err < 0) { | ||||||
|             /* Something went wrong inside the compression library */ |             /* Something went wrong inside the compression library */ | ||||||
|             if (err == Z_DATA_ERROR) |             if (err == Z_DATA_ERROR) { | ||||||
|                 state->errcode = IMAGING_CODEC_BROKEN; |                 state->errcode = IMAGING_CODEC_BROKEN; | ||||||
|             else if (err == Z_MEM_ERROR) |             } else if (err == Z_MEM_ERROR) { | ||||||
|                 state->errcode = IMAGING_CODEC_MEMORY; |                 state->errcode = IMAGING_CODEC_MEMORY; | ||||||
|             else |             } else { | ||||||
|                 state->errcode = IMAGING_CODEC_CONFIG; |                 state->errcode = IMAGING_CODEC_CONFIG; | ||||||
|  |             } | ||||||
|             free(context->previous); |             free(context->previous); | ||||||
|             context->previous = NULL; |             context->previous = NULL; | ||||||
|             inflateEnd(&context->z_stream); |             inflateEnd(&context->z_stream); | ||||||
|  | @ -149,28 +151,33 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|             case 1: |             case 1: | ||||||
|                 /* prior */ |                 /* prior */ | ||||||
|                 bpp = (state->bits + 7) / 8; |                 bpp = (state->bits + 7) / 8; | ||||||
|                 for (i = bpp+1; i <= row_len; i++) |                 for (i = bpp+1; i <= row_len; i++) { | ||||||
|                     state->buffer[i] += state->buffer[i-bpp]; |                     state->buffer[i] += state->buffer[i-bpp]; | ||||||
|  |                 } | ||||||
|                 break; |                 break; | ||||||
|             case 2: |             case 2: | ||||||
|                 /* up */ |                 /* up */ | ||||||
|                 for (i = 1; i <= row_len; i++) |                 for (i = 1; i <= row_len; i++) { | ||||||
|                     state->buffer[i] += context->previous[i]; |                     state->buffer[i] += context->previous[i]; | ||||||
|  |                 } | ||||||
|                 break; |                 break; | ||||||
|             case 3: |             case 3: | ||||||
|                 /* average */ |                 /* average */ | ||||||
|                 bpp = (state->bits + 7) / 8; |                 bpp = (state->bits + 7) / 8; | ||||||
|                 for (i = 1; i <= bpp; i++) |                 for (i = 1; i <= bpp; i++) { | ||||||
|                     state->buffer[i] += context->previous[i]/2; |                     state->buffer[i] += context->previous[i]/2; | ||||||
|                 for (; i <= row_len; i++) |                 } | ||||||
|  |                 for (; i <= row_len; i++) { | ||||||
|                     state->buffer[i] += |                     state->buffer[i] += | ||||||
|                         (state->buffer[i-bpp] + context->previous[i])/2; |                         (state->buffer[i-bpp] + context->previous[i])/2; | ||||||
|  |                 } | ||||||
|                 break; |                 break; | ||||||
|             case 4: |             case 4: | ||||||
|                 /* paeth filtering */ |                 /* paeth filtering */ | ||||||
|                 bpp = (state->bits + 7) / 8; |                 bpp = (state->bits + 7) / 8; | ||||||
|                 for (i = 1; i <= bpp; i++) |                 for (i = 1; i <= bpp; i++) { | ||||||
|                     state->buffer[i] += context->previous[i]; |                     state->buffer[i] += context->previous[i]; | ||||||
|  |                 } | ||||||
|                 for (; i <= row_len; i++) { |                 for (; i <= row_len; i++) { | ||||||
|                     int a, b, c; |                     int a, b, c; | ||||||
|                     int pa, pb, pc; |                     int pa, pb, pc; | ||||||
|  | @ -201,8 +208,9 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt | ||||||
|             break; |             break; | ||||||
|         case ZIP_TIFF_PREDICTOR: |         case ZIP_TIFF_PREDICTOR: | ||||||
|             bpp = (state->bits + 7) / 8; |             bpp = (state->bits + 7) / 8; | ||||||
|             for (i = bpp+1; i <= row_len; i++) |             for (i = bpp+1; i <= row_len; i++) { | ||||||
|                 state->buffer[i] += state->buffer[i-bpp]; |                 state->buffer[i] += state->buffer[i-bpp]; | ||||||
|  |             } | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -128,12 +128,13 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
| 
 | 
 | ||||||
|         if (err < 0) { |         if (err < 0) { | ||||||
|             /* Something went wrong inside the compression library */ |             /* Something went wrong inside the compression library */ | ||||||
|             if (err == Z_DATA_ERROR) |             if (err == Z_DATA_ERROR) { | ||||||
|                 state->errcode = IMAGING_CODEC_BROKEN; |                 state->errcode = IMAGING_CODEC_BROKEN; | ||||||
|             else if (err == Z_MEM_ERROR) |             } else if (err == Z_MEM_ERROR) { | ||||||
|                 state->errcode = IMAGING_CODEC_MEMORY; |                 state->errcode = IMAGING_CODEC_MEMORY; | ||||||
|             else |             } else { | ||||||
|                 state->errcode = IMAGING_CODEC_CONFIG; |                 state->errcode = IMAGING_CODEC_CONFIG; | ||||||
|  |             } | ||||||
|             free(context->paeth); |             free(context->paeth); | ||||||
|             free(context->average); |             free(context->average); | ||||||
|             free(context->up); |             free(context->up); | ||||||
|  | @ -282,12 +283,13 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
| 
 | 
 | ||||||
|                 if (err < 0) { |                 if (err < 0) { | ||||||
|                     /* Something went wrong inside the compression library */ |                     /* Something went wrong inside the compression library */ | ||||||
|                     if (err == Z_DATA_ERROR) |                     if (err == Z_DATA_ERROR) { | ||||||
|                         state->errcode = IMAGING_CODEC_BROKEN; |                         state->errcode = IMAGING_CODEC_BROKEN; | ||||||
|                     else if (err == Z_MEM_ERROR) |                     } else if (err == Z_MEM_ERROR) { | ||||||
|                         state->errcode = IMAGING_CODEC_MEMORY; |                         state->errcode = IMAGING_CODEC_MEMORY; | ||||||
|                     else |                     } else { | ||||||
|                         state->errcode = IMAGING_CODEC_CONFIG; |                         state->errcode = IMAGING_CODEC_CONFIG; | ||||||
|  |                     } | ||||||
|                     free(context->paeth); |                     free(context->paeth); | ||||||
|                     free(context->average); |                     free(context->average); | ||||||
|                     free(context->up); |                     free(context->up); | ||||||
|  | @ -305,8 +307,9 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
| 
 | 
 | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (context->z_stream.avail_out == 0) |             if (context->z_stream.avail_out == 0) { | ||||||
|                 break; /* Buffer full */ |                 break; /* Buffer full */ | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|         case 2: |         case 2: | ||||||
| 
 | 
 | ||||||
|  | @ -331,8 +334,9 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 if (context->z_stream.avail_out == 0) |                 if (context->z_stream.avail_out == 0) { | ||||||
|                     break; /* Buffer full */ |                     break; /* Buffer full */ | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										81
									
								
								src/map.c
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								src/map.c
									
									
									
									
									
								
							|  | @ -47,12 +47,14 @@ PyImaging_MapperNew(const char* filename, int readonly) | ||||||
| { | { | ||||||
|     ImagingMapperObject *mapper; |     ImagingMapperObject *mapper; | ||||||
| 
 | 
 | ||||||
|     if (PyType_Ready(&ImagingMapperType) < 0) |     if (PyType_Ready(&ImagingMapperType) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     mapper = PyObject_New(ImagingMapperObject, &ImagingMapperType); |     mapper = PyObject_New(ImagingMapperObject, &ImagingMapperType); | ||||||
|     if (mapper == NULL) |     if (mapper == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     mapper->base = NULL; |     mapper->base = NULL; | ||||||
|     mapper->size = mapper->offset = 0; |     mapper->size = mapper->offset = 0; | ||||||
|  | @ -101,12 +103,15 @@ static void | ||||||
| mapping_dealloc(ImagingMapperObject* mapper) | mapping_dealloc(ImagingMapperObject* mapper) | ||||||
| { | { | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
|     if (mapper->base != 0) |     if (mapper->base != 0) { | ||||||
|         UnmapViewOfFile(mapper->base); |         UnmapViewOfFile(mapper->base); | ||||||
|     if (mapper->hMap != (HANDLE)-1) |     } | ||||||
|  |     if (mapper->hMap != (HANDLE)-1) { | ||||||
|         CloseHandle(mapper->hMap); |         CloseHandle(mapper->hMap); | ||||||
|     if (mapper->hFile != (HANDLE)-1) |     } | ||||||
|  |     if (mapper->hFile != (HANDLE)-1) { | ||||||
|         CloseHandle(mapper->hFile); |         CloseHandle(mapper->hFile); | ||||||
|  |     } | ||||||
|     mapper->base = 0; |     mapper->base = 0; | ||||||
|     mapper->hMap = mapper->hFile = (HANDLE)-1; |     mapper->hMap = mapper->hFile = (HANDLE)-1; | ||||||
| #endif | #endif | ||||||
|  | @ -122,18 +127,22 @@ mapping_read(ImagingMapperObject* mapper, PyObject* args) | ||||||
|     PyObject* buf; |     PyObject* buf; | ||||||
| 
 | 
 | ||||||
|     int size = -1; |     int size = -1; | ||||||
|     if (!PyArg_ParseTuple(args, "|i", &size)) |     if (!PyArg_ParseTuple(args, "|i", &size)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* check size */ |     /* check size */ | ||||||
|     if (size < 0 || mapper->offset + size > mapper->size) |     if (size < 0 || mapper->offset + size > mapper->size) { | ||||||
|         size = mapper->size - mapper->offset; |         size = mapper->size - mapper->offset; | ||||||
|     if (size < 0) |     } | ||||||
|  |     if (size < 0) { | ||||||
|         size = 0; |         size = 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     buf = PyBytes_FromStringAndSize(NULL, size); |     buf = PyBytes_FromStringAndSize(NULL, size); | ||||||
|     if (!buf) |     if (!buf) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (size > 0) { |     if (size > 0) { | ||||||
|         memcpy(PyBytes_AsString(buf), mapper->base + mapper->offset, size); |         memcpy(PyBytes_AsString(buf), mapper->base + mapper->offset, size); | ||||||
|  | @ -148,8 +157,9 @@ mapping_seek(ImagingMapperObject* mapper, PyObject* args) | ||||||
| { | { | ||||||
|     int offset; |     int offset; | ||||||
|     int whence = 0; |     int whence = 0; | ||||||
|     if (!PyArg_ParseTuple(args, "i|i", &offset, &whence)) |     if (!PyArg_ParseTuple(args, "i|i", &offset, &whence)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     switch (whence) { |     switch (whence) { | ||||||
|         case 0: /* SEEK_SET */ |         case 0: /* SEEK_SET */ | ||||||
|  | @ -193,17 +203,19 @@ mapping_readimage(ImagingMapperObject* mapper, PyObject* args) | ||||||
|     int stride; |     int stride; | ||||||
|     int orientation; |     int orientation; | ||||||
|     if (!PyArg_ParseTuple(args, "s(ii)ii", &mode, &xsize, &ysize, |     if (!PyArg_ParseTuple(args, "s(ii)ii", &mode, &xsize, &ysize, | ||||||
|                           &stride, &orientation)) |                           &stride, &orientation)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (stride <= 0) { |     if (stride <= 0) { | ||||||
|         /* FIXME: maybe we should call ImagingNewPrologue instead */ |         /* FIXME: maybe we should call ImagingNewPrologue instead */ | ||||||
|         if (!strcmp(mode, "L") || !strcmp(mode, "P")) |         if (!strcmp(mode, "L") || !strcmp(mode, "P")) { | ||||||
|             stride = xsize; |             stride = xsize; | ||||||
|         else if (!strcmp(mode, "I;16") || !strcmp(mode, "I;16B")) |         } else if (!strcmp(mode, "I;16") || !strcmp(mode, "I;16B")) { | ||||||
|             stride = xsize * 2; |             stride = xsize * 2; | ||||||
|         else |         } else { | ||||||
|             stride = xsize * 4; |             stride = xsize * 4; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     size = ysize * stride; |     size = ysize * stride; | ||||||
|  | @ -214,16 +226,20 @@ mapping_readimage(ImagingMapperObject* mapper, PyObject* args) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     im = ImagingNewPrologue(mode, xsize, ysize); |     im = ImagingNewPrologue(mode, xsize, ysize); | ||||||
|     if (!im) |     if (!im) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* setup file pointers */ |     /* setup file pointers */ | ||||||
|     if (orientation > 0) |     if (orientation > 0) { | ||||||
|         for (y = 0; y < ysize; y++) |         for (y = 0; y < ysize; y++) { | ||||||
|             im->image[y] = mapper->base + mapper->offset + y * stride; |             im->image[y] = mapper->base + mapper->offset + y * stride; | ||||||
|     else |         } | ||||||
|         for (y = 0; y < ysize; y++) |     } else { | ||||||
|  |         for (y = 0; y < ysize; y++) { | ||||||
|             im->image[ysize-y-1] = mapper->base + mapper->offset + y * stride; |             im->image[ysize-y-1] = mapper->base + mapper->offset + y * stride; | ||||||
|  |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     im->destroy = ImagingDestroyMap; |     im->destroy = ImagingDestroyMap; | ||||||
| 
 | 
 | ||||||
|  | @ -279,8 +295,9 @@ PyObject* | ||||||
| PyImaging_Mapper(PyObject* self, PyObject* args) | PyImaging_Mapper(PyObject* self, PyObject* args) | ||||||
| { | { | ||||||
|     char* filename; |     char* filename; | ||||||
|     if (!PyArg_ParseTuple(args, "s", &filename)) |     if (!PyArg_ParseTuple(args, "s", &filename)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return (PyObject*) PyImaging_MapperNew(filename, 1); |     return (PyObject*) PyImaging_MapperNew(filename, 1); | ||||||
| } | } | ||||||
|  | @ -319,8 +336,9 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args) | ||||||
|     int ystep; |     int ystep; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "O(ii)sn(sii)", &target, &xsize, &ysize, |     if (!PyArg_ParseTuple(args, "O(ii)sn(sii)", &target, &xsize, &ysize, | ||||||
|                           &codec, &offset, &mode, &stride, &ystep)) |                           &codec, &offset, &mode, &stride, &ystep)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!PyImaging_CheckBuffer(target)) { |     if (!PyImaging_CheckBuffer(target)) { | ||||||
|         PyErr_SetString(PyExc_TypeError, "expected string or buffer"); |         PyErr_SetString(PyExc_TypeError, "expected string or buffer"); | ||||||
|  | @ -328,12 +346,13 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (stride <= 0) { |     if (stride <= 0) { | ||||||
|         if (!strcmp(mode, "L") || !strcmp(mode, "P")) |         if (!strcmp(mode, "L") || !strcmp(mode, "P")) { | ||||||
|             stride = xsize; |             stride = xsize; | ||||||
|         else if (!strncmp(mode, "I;16", 4)) |         } else if (!strncmp(mode, "I;16", 4)) { | ||||||
|             stride = xsize * 2; |             stride = xsize * 2; | ||||||
|         else |         } else { | ||||||
|             stride = xsize * 4; |             stride = xsize * 4; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (stride > 0 && ysize > PY_SSIZE_T_MAX / stride) { |     if (stride > 0 && ysize > PY_SSIZE_T_MAX / stride) { | ||||||
|  | @ -349,8 +368,9 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* check buffer size */ |     /* check buffer size */ | ||||||
|     if (PyImaging_GetBuffer(target, &view) < 0) |     if (PyImaging_GetBuffer(target, &view) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (view.len < 0) { |     if (view.len < 0) { | ||||||
|         PyErr_SetString(PyExc_ValueError, "buffer has negative size"); |         PyErr_SetString(PyExc_ValueError, "buffer has negative size"); | ||||||
|  | @ -371,12 +391,15 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* setup file pointers */ |     /* setup file pointers */ | ||||||
|     if (ystep > 0) |     if (ystep > 0) { | ||||||
|         for (y = 0; y < ysize; y++) |         for (y = 0; y < ysize; y++) { | ||||||
|             im->image[y] = (char*)view.buf + offset + y * stride; |             im->image[y] = (char*)view.buf + offset + y * stride; | ||||||
|     else |         } | ||||||
|         for (y = 0; y < ysize; y++) |     } else { | ||||||
|  |         for (y = 0; y < ysize; y++) { | ||||||
|             im->image[ysize-y-1] = (char*)view.buf + offset + y * stride; |             im->image[ysize-y-1] = (char*)view.buf + offset + y * stride; | ||||||
|  |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     im->destroy = mapping_destroy_buffer; |     im->destroy = mapping_destroy_buffer; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -39,12 +39,14 @@ _outline_new(void) | ||||||
| { | { | ||||||
|     OutlineObject *self; |     OutlineObject *self; | ||||||
| 
 | 
 | ||||||
|     if (PyType_Ready(&OutlineType) < 0) |     if (PyType_Ready(&OutlineType) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     self = PyObject_New(OutlineObject, &OutlineType); |     self = PyObject_New(OutlineObject, &OutlineType); | ||||||
|     if (self == NULL) |     if (self == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     self->outline = ImagingOutlineNew(); |     self->outline = ImagingOutlineNew(); | ||||||
| 
 | 
 | ||||||
|  | @ -61,8 +63,9 @@ _outline_dealloc(OutlineObject* self) | ||||||
| ImagingOutline | ImagingOutline | ||||||
| PyOutline_AsOutline(PyObject* outline) | PyOutline_AsOutline(PyObject* outline) | ||||||
| { | { | ||||||
|     if (PyOutline_Check(outline)) |     if (PyOutline_Check(outline)) { | ||||||
|         return ((OutlineObject*) outline)->outline; |         return ((OutlineObject*) outline)->outline; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  | @ -74,8 +77,9 @@ PyOutline_AsOutline(PyObject* outline) | ||||||
| PyObject* | PyObject* | ||||||
| PyOutline_Create(PyObject* self, PyObject* args) | PyOutline_Create(PyObject* self, PyObject* args) | ||||||
| { | { | ||||||
|     if (!PyArg_ParseTuple(args, ":outline")) |     if (!PyArg_ParseTuple(args, ":outline")) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return (PyObject*) _outline_new(); |     return (PyObject*) _outline_new(); | ||||||
| } | } | ||||||
|  | @ -88,8 +92,9 @@ static PyObject* | ||||||
| _outline_move(OutlineObject* self, PyObject* args) | _outline_move(OutlineObject* self, PyObject* args) | ||||||
| { | { | ||||||
|     float x0, y0; |     float x0, y0; | ||||||
|     if (!PyArg_ParseTuple(args, "ff", &x0, &y0)) |     if (!PyArg_ParseTuple(args, "ff", &x0, &y0)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingOutlineMove(self->outline, x0, y0); |     ImagingOutlineMove(self->outline, x0, y0); | ||||||
| 
 | 
 | ||||||
|  | @ -101,8 +106,9 @@ static PyObject* | ||||||
| _outline_line(OutlineObject* self, PyObject* args) | _outline_line(OutlineObject* self, PyObject* args) | ||||||
| { | { | ||||||
|     float x1, y1; |     float x1, y1; | ||||||
|     if (!PyArg_ParseTuple(args, "ff", &x1, &y1)) |     if (!PyArg_ParseTuple(args, "ff", &x1, &y1)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingOutlineLine(self->outline, x1, y1); |     ImagingOutlineLine(self->outline, x1, y1); | ||||||
| 
 | 
 | ||||||
|  | @ -114,8 +120,9 @@ static PyObject* | ||||||
| _outline_curve(OutlineObject* self, PyObject* args) | _outline_curve(OutlineObject* self, PyObject* args) | ||||||
| { | { | ||||||
|     float x1, y1, x2, y2, x3, y3; |     float x1, y1, x2, y2, x3, y3; | ||||||
|     if (!PyArg_ParseTuple(args, "ffffff", &x1, &y1, &x2, &y2, &x3, &y3)) |     if (!PyArg_ParseTuple(args, "ffffff", &x1, &y1, &x2, &y2, &x3, &y3)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingOutlineCurve(self->outline, x1, y1, x2, y2, x3, y3); |     ImagingOutlineCurve(self->outline, x1, y1, x2, y2, x3, y3); | ||||||
| 
 | 
 | ||||||
|  | @ -126,8 +133,9 @@ _outline_curve(OutlineObject* self, PyObject* args) | ||||||
| static PyObject* | static PyObject* | ||||||
| _outline_close(OutlineObject* self, PyObject* args) | _outline_close(OutlineObject* self, PyObject* args) | ||||||
| { | { | ||||||
|     if (!PyArg_ParseTuple(args, ":close")) |     if (!PyArg_ParseTuple(args, ":close")) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingOutlineClose(self->outline); |     ImagingOutlineClose(self->outline); | ||||||
| 
 | 
 | ||||||
|  | @ -139,8 +147,9 @@ static PyObject* | ||||||
| _outline_transform(OutlineObject* self, PyObject* args) | _outline_transform(OutlineObject* self, PyObject* args) | ||||||
| { | { | ||||||
|     double a[6]; |     double a[6]; | ||||||
|     if (!PyArg_ParseTuple(args, "(dddddd)", a+0, a+1, a+2, a+3, a+4, a+5)) |     if (!PyArg_ParseTuple(args, "(dddddd)", a+0, a+1, a+2, a+3, a+4, a+5)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ImagingOutlineTransform(self->outline, a); |     ImagingOutlineTransform(self->outline, a); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										123
									
								
								src/path.c
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								src/path.c
									
									
									
									
									
								
							|  | @ -61,8 +61,9 @@ alloc_array(Py_ssize_t count) | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|     xy = malloc(2 * count * sizeof(double) + 1); |     xy = malloc(2 * count * sizeof(double) + 1); | ||||||
|     if (!xy) |     if (!xy) { | ||||||
|         PyErr_NoMemory(); |         PyErr_NoMemory(); | ||||||
|  |     } | ||||||
|     return xy; |     return xy; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -74,8 +75,9 @@ path_new(Py_ssize_t count, double* xy, int duplicate) | ||||||
|     if (duplicate) { |     if (duplicate) { | ||||||
|         /* duplicate path */ |         /* duplicate path */ | ||||||
|         double* p = alloc_array(count); |         double* p = alloc_array(count); | ||||||
|         if (!p) |         if (!p) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  |         } | ||||||
|         memcpy(p, xy, count * 2 * sizeof(double)); |         memcpy(p, xy, count * 2 * sizeof(double)); | ||||||
|         xy = p; |         xy = p; | ||||||
|     } |     } | ||||||
|  | @ -120,8 +122,9 @@ PyPath_Flatten(PyObject* data, double **pxy) | ||||||
|         /* This was another path object. */ |         /* This was another path object. */ | ||||||
|         PyPathObject *path = (PyPathObject*) data; |         PyPathObject *path = (PyPathObject*) data; | ||||||
|         xy = alloc_array(path->count); |         xy = alloc_array(path->count); | ||||||
|         if (!xy) |         if (!xy) { | ||||||
|             return -1; |             return -1; | ||||||
|  |         } | ||||||
|         memcpy(xy, path->xy, 2 * path->count * sizeof(double)); |         memcpy(xy, path->xy, 2 * path->count * sizeof(double)); | ||||||
|         *pxy = xy; |         *pxy = xy; | ||||||
|         return path->count; |         return path->count; | ||||||
|  | @ -134,10 +137,12 @@ PyPath_Flatten(PyObject* data, double **pxy) | ||||||
|             float *ptr = (float*) buffer.buf; |             float *ptr = (float*) buffer.buf; | ||||||
|             n = buffer.len / (2 * sizeof(float)); |             n = buffer.len / (2 * sizeof(float)); | ||||||
|             xy = alloc_array(n); |             xy = alloc_array(n); | ||||||
|             if (!xy) |             if (!xy) { | ||||||
|                 return -1; |                 return -1; | ||||||
|             for (i = 0; i < n+n; i++) |             } | ||||||
|  |             for (i = 0; i < n+n; i++) { | ||||||
|                 xy[i] = ptr[i]; |                 xy[i] = ptr[i]; | ||||||
|  |             } | ||||||
|             *pxy = xy; |             *pxy = xy; | ||||||
|             PyBuffer_Release(&buffer); |             PyBuffer_Release(&buffer); | ||||||
|             return n; |             return n; | ||||||
|  | @ -153,26 +158,28 @@ PyPath_Flatten(PyObject* data, double **pxy) | ||||||
|     j = 0; |     j = 0; | ||||||
|     n = PyObject_Length(data); |     n = PyObject_Length(data); | ||||||
|     /* Just in case __len__ breaks (or doesn't exist) */ |     /* Just in case __len__ breaks (or doesn't exist) */ | ||||||
|     if (PyErr_Occurred()) |     if (PyErr_Occurred()) { | ||||||
|         return -1; |         return -1; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Allocate for worst case */ |     /* Allocate for worst case */ | ||||||
|     xy = alloc_array(n); |     xy = alloc_array(n); | ||||||
|     if (!xy) |     if (!xy) { | ||||||
|         return -1; |         return -1; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Copy table to path array */ |     /* Copy table to path array */ | ||||||
|     if (PyList_Check(data)) { |     if (PyList_Check(data)) { | ||||||
|         for (i = 0; i < n; i++) { |         for (i = 0; i < n; i++) { | ||||||
|             double x, y; |             double x, y; | ||||||
|             PyObject *op = PyList_GET_ITEM(data, i); |             PyObject *op = PyList_GET_ITEM(data, i); | ||||||
|             if (PyFloat_Check(op)) |             if (PyFloat_Check(op)) { | ||||||
|                 xy[j++] = PyFloat_AS_DOUBLE(op); |                 xy[j++] = PyFloat_AS_DOUBLE(op); | ||||||
|             else if (PyLong_Check(op)) |             } else if (PyLong_Check(op)) { | ||||||
|                 xy[j++] = (float) PyLong_AS_LONG(op); |                 xy[j++] = (float) PyLong_AS_LONG(op); | ||||||
|             else if (PyNumber_Check(op)) |             } else if (PyNumber_Check(op)) { | ||||||
|                 xy[j++] = PyFloat_AsDouble(op); |                 xy[j++] = PyFloat_AsDouble(op); | ||||||
|             else if (PyArg_ParseTuple(op, "dd", &x, &y)) { |             } else if (PyArg_ParseTuple(op, "dd", &x, &y)) { | ||||||
|                 xy[j++] = x; |                 xy[j++] = x; | ||||||
|                 xy[j++] = y; |                 xy[j++] = y; | ||||||
|             } else { |             } else { | ||||||
|  | @ -184,13 +191,13 @@ PyPath_Flatten(PyObject* data, double **pxy) | ||||||
|         for (i = 0; i < n; i++) { |         for (i = 0; i < n; i++) { | ||||||
|             double x, y; |             double x, y; | ||||||
|             PyObject *op = PyTuple_GET_ITEM(data, i); |             PyObject *op = PyTuple_GET_ITEM(data, i); | ||||||
|             if (PyFloat_Check(op)) |             if (PyFloat_Check(op)) { | ||||||
|                 xy[j++] = PyFloat_AS_DOUBLE(op); |                 xy[j++] = PyFloat_AS_DOUBLE(op); | ||||||
|             else if (PyLong_Check(op)) |             } else if (PyLong_Check(op)) { | ||||||
|                 xy[j++] = (float) PyLong_AS_LONG(op); |                 xy[j++] = (float) PyLong_AS_LONG(op); | ||||||
|             else if (PyNumber_Check(op)) |             } else if (PyNumber_Check(op)) { | ||||||
|                 xy[j++] = PyFloat_AsDouble(op); |                 xy[j++] = PyFloat_AsDouble(op); | ||||||
|             else if (PyArg_ParseTuple(op, "dd", &x, &y)) { |             } else if (PyArg_ParseTuple(op, "dd", &x, &y)) { | ||||||
|                 xy[j++] = x; |                 xy[j++] = x; | ||||||
|                 xy[j++] = y; |                 xy[j++] = y; | ||||||
|             } else { |             } else { | ||||||
|  | @ -213,13 +220,13 @@ PyPath_Flatten(PyObject* data, double **pxy) | ||||||
|                     return -1; |                     return -1; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (PyFloat_Check(op)) |             if (PyFloat_Check(op)) { | ||||||
|                 xy[j++] = PyFloat_AS_DOUBLE(op); |                 xy[j++] = PyFloat_AS_DOUBLE(op); | ||||||
|             else if (PyLong_Check(op)) |             } else if (PyLong_Check(op)) { | ||||||
|                 xy[j++] = (float) PyLong_AS_LONG(op); |                 xy[j++] = (float) PyLong_AS_LONG(op); | ||||||
|             else if (PyNumber_Check(op)) |             } else if (PyNumber_Check(op)) { | ||||||
|                 xy[j++] = PyFloat_AsDouble(op); |                 xy[j++] = PyFloat_AsDouble(op); | ||||||
|             else if (PyArg_ParseTuple(op, "dd", &x, &y)) { |             } else if (PyArg_ParseTuple(op, "dd", &x, &y)) { | ||||||
|                 xy[j++] = x; |                 xy[j++] = x; | ||||||
|                 xy[j++] = y; |                 xy[j++] = y; | ||||||
|             } else { |             } else { | ||||||
|  | @ -257,19 +264,22 @@ PyPath_Create(PyObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|         /* number of vertices */ |         /* number of vertices */ | ||||||
|         xy = alloc_array(count); |         xy = alloc_array(count); | ||||||
|         if (!xy) |         if (!xy) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } else { |     } else { | ||||||
| 
 | 
 | ||||||
|         /* sequence or other path */ |         /* sequence or other path */ | ||||||
|         PyErr_Clear(); |         PyErr_Clear(); | ||||||
|         if (!PyArg_ParseTuple(args, "O", &data)) |         if (!PyArg_ParseTuple(args, "O", &data)) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         count = PyPath_Flatten(data, &xy); |         count = PyPath_Flatten(data, &xy); | ||||||
|         if (count < 0) |         if (count < 0) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return (PyObject*) path_new(count, xy, 0); |     return (PyObject*) path_new(count, xy, 0); | ||||||
|  | @ -291,8 +301,9 @@ path_compact(PyPathObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|     double cityblock = 2.0; |     double cityblock = 2.0; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "|d:compact", &cityblock)) |     if (!PyArg_ParseTuple(args, "|d:compact", &cityblock)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     xy = self->xy; |     xy = self->xy; | ||||||
| 
 | 
 | ||||||
|  | @ -323,8 +334,9 @@ path_getbbox(PyPathObject* self, PyObject* args) | ||||||
|     double *xy; |     double *xy; | ||||||
|     double x0, y0, x1, y1; |     double x0, y0, x1, y1; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, ":getbbox")) |     if (!PyArg_ParseTuple(args, ":getbbox")) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     xy = self->xy; |     xy = self->xy; | ||||||
| 
 | 
 | ||||||
|  | @ -332,14 +344,18 @@ path_getbbox(PyPathObject* self, PyObject* args) | ||||||
|     y0 = y1 = xy[1]; |     y0 = y1 = xy[1]; | ||||||
| 
 | 
 | ||||||
|     for (i = 1; i < self->count; i++) { |     for (i = 1; i < self->count; i++) { | ||||||
|         if (xy[i+i] < x0) |         if (xy[i+i] < x0) { | ||||||
|             x0 = xy[i+i]; |             x0 = xy[i+i]; | ||||||
|         if (xy[i+i] > x1) |         } | ||||||
|  |         if (xy[i+i] > x1) { | ||||||
|             x1 = xy[i+i]; |             x1 = xy[i+i]; | ||||||
|         if (xy[i+i+1] < y0) |         } | ||||||
|  |         if (xy[i+i+1] < y0) { | ||||||
|             y0 = xy[i+i+1]; |             y0 = xy[i+i+1]; | ||||||
|         if (xy[i+i+1] > y1) |         } | ||||||
|  |         if (xy[i+i+1] > y1) { | ||||||
|             y1 = xy[i+i+1]; |             y1 = xy[i+i+1]; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return Py_BuildValue("dddd", x0, y0, x1, y1); |     return Py_BuildValue("dddd", x0, y0, x1, y1); | ||||||
|  | @ -348,8 +364,9 @@ path_getbbox(PyPathObject* self, PyObject* args) | ||||||
| static PyObject* | static PyObject* | ||||||
| path_getitem(PyPathObject* self, Py_ssize_t i) | path_getitem(PyPathObject* self, Py_ssize_t i) | ||||||
| { | { | ||||||
|     if (i < 0) |     if (i < 0) { | ||||||
|         i = self->count + i; |         i = self->count + i; | ||||||
|  |     } | ||||||
|     if (i < 0 || i >= self->count) { |     if (i < 0 || i >= self->count) { | ||||||
|         PyErr_SetString(PyExc_IndexError, "path index out of range"); |         PyErr_SetString(PyExc_IndexError, "path index out of range"); | ||||||
|         return NULL; |         return NULL; | ||||||
|  | @ -362,16 +379,19 @@ static PyObject* | ||||||
| path_getslice(PyPathObject* self, Py_ssize_t ilow, Py_ssize_t ihigh) | path_getslice(PyPathObject* self, Py_ssize_t ilow, Py_ssize_t ihigh) | ||||||
| { | { | ||||||
|     /* adjust arguments */ |     /* adjust arguments */ | ||||||
|     if (ilow < 0) |     if (ilow < 0) { | ||||||
|         ilow = 0; |         ilow = 0; | ||||||
|     else if (ilow >= self->count) |     } else if (ilow >= self->count) { | ||||||
|         ilow = self->count; |         ilow = self->count; | ||||||
|     if (ihigh < 0) |     } | ||||||
|  |     if (ihigh < 0) { | ||||||
|         ihigh = 0; |         ihigh = 0; | ||||||
|     if (ihigh < ilow) |     } | ||||||
|  |     if (ihigh < ilow) { | ||||||
|         ihigh = ilow; |         ihigh = ilow; | ||||||
|     else if (ihigh > self->count) |     } else if (ihigh > self->count) { | ||||||
|         ihigh = self->count; |         ihigh = self->count; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return (PyObject*) path_new(ihigh - ilow, self->xy + ilow * 2, 1); |     return (PyObject*) path_new(ihigh - ilow, self->xy + ilow * 2, 1); | ||||||
| } | } | ||||||
|  | @ -390,8 +410,9 @@ path_map(PyPathObject* self, PyObject* args) | ||||||
|     double *xy; |     double *xy; | ||||||
|     PyObject* function; |     PyObject* function; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "O:map", &function)) |     if (!PyArg_ParseTuple(args, "O:map", &function)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     xy = self->xy; |     xy = self->xy; | ||||||
| 
 | 
 | ||||||
|  | @ -432,8 +453,9 @@ path_setitem(PyPathObject* self, Py_ssize_t i, PyObject* op) | ||||||
| 
 | 
 | ||||||
|     xy = &self->xy[i+i]; |     xy = &self->xy[i+i]; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(op, "dd", &xy[0], &xy[1])) |     if (!PyArg_ParseTuple(op, "dd", &xy[0], &xy[1])) { | ||||||
|         return -1; |         return -1; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | @ -445,16 +467,18 @@ path_tolist(PyPathObject* self, PyObject* args) | ||||||
|     Py_ssize_t i; |     Py_ssize_t i; | ||||||
| 
 | 
 | ||||||
|     int flat = 0; |     int flat = 0; | ||||||
|     if (!PyArg_ParseTuple(args, "|i:tolist", &flat)) |     if (!PyArg_ParseTuple(args, "|i:tolist", &flat)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (flat) { |     if (flat) { | ||||||
|         list = PyList_New(self->count*2); |         list = PyList_New(self->count*2); | ||||||
|         for (i = 0; i < self->count*2; i++) { |         for (i = 0; i < self->count*2; i++) { | ||||||
|             PyObject* item; |             PyObject* item; | ||||||
|             item = PyFloat_FromDouble(self->xy[i]); |             item = PyFloat_FromDouble(self->xy[i]); | ||||||
|             if (!item) |             if (!item) { | ||||||
|                 goto error; |                 goto error; | ||||||
|  |             } | ||||||
|             PyList_SetItem(list, i, item); |             PyList_SetItem(list, i, item); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|  | @ -462,8 +486,9 @@ path_tolist(PyPathObject* self, PyObject* args) | ||||||
|         for (i = 0; i < self->count; i++) { |         for (i = 0; i < self->count; i++) { | ||||||
|             PyObject* item; |             PyObject* item; | ||||||
|             item = Py_BuildValue("dd", self->xy[i+i], self->xy[i+i+1]); |             item = Py_BuildValue("dd", self->xy[i+i], self->xy[i+i+1]); | ||||||
|             if (!item) |             if (!item) { | ||||||
|                 goto error; |                 goto error; | ||||||
|  |             } | ||||||
|             PyList_SetItem(list, i, item); |             PyList_SetItem(list, i, item); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -487,19 +512,20 @@ path_transform(PyPathObject* self, PyObject* args) | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "(dddddd)|d:transform", |     if (!PyArg_ParseTuple(args, "(dddddd)|d:transform", | ||||||
|                           &a, &b, &c, &d, &e, &f, |                           &a, &b, &c, &d, &e, &f, | ||||||
|                           &wrap)) |                           &wrap)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     xy = self->xy; |     xy = self->xy; | ||||||
| 
 | 
 | ||||||
|     /* transform the coordinate set */ |     /* transform the coordinate set */ | ||||||
|     if (b == 0.0 && d == 0.0) |     if (b == 0.0 && d == 0.0) { | ||||||
|         /* scaling */ |         /* scaling */ | ||||||
|         for (i = 0; i < self->count; i++) { |         for (i = 0; i < self->count; i++) { | ||||||
|             xy[i+i]   = a*xy[i+i]+c; |             xy[i+i]   = a*xy[i+i]+c; | ||||||
|             xy[i+i+1] = e*xy[i+i+1]+f; |             xy[i+i+1] = e*xy[i+i+1]+f; | ||||||
|         } |         } | ||||||
|     else |     } else { | ||||||
|         /* affine transform */ |         /* affine transform */ | ||||||
|         for (i = 0; i < self->count; i++) { |         for (i = 0; i < self->count; i++) { | ||||||
|             double x = xy[i+i]; |             double x = xy[i+i]; | ||||||
|  | @ -507,11 +533,14 @@ path_transform(PyPathObject* self, PyObject* args) | ||||||
|             xy[i+i]   = a*x+b*y+c; |             xy[i+i]   = a*x+b*y+c; | ||||||
|             xy[i+i+1] = d*x+e*y+f; |             xy[i+i+1] = d*x+e*y+f; | ||||||
|         } |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* special treatment of geographical map data */ |     /* special treatment of geographical map data */ | ||||||
|     if (wrap != 0.0) |     if (wrap != 0.0) { | ||||||
|         for (i = 0; i < self->count; i++) |         for (i = 0; i < self->count; i++) { | ||||||
|             xy[i+i] = fmod(xy[i+i], wrap); |             xy[i+i] = fmod(xy[i+i], wrap); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     Py_INCREF(Py_None); |     Py_INCREF(Py_None); | ||||||
|     return Py_None; |     return Py_None; | ||||||
|  | @ -542,16 +571,18 @@ path_subscript(PyPathObject* self, PyObject* item) { | ||||||
|     if (PyIndex_Check(item)) { |     if (PyIndex_Check(item)) { | ||||||
|         Py_ssize_t i; |         Py_ssize_t i; | ||||||
|         i = PyNumber_AsSsize_t(item, PyExc_IndexError); |         i = PyNumber_AsSsize_t(item, PyExc_IndexError); | ||||||
|         if (i == -1 && PyErr_Occurred()) |         if (i == -1 && PyErr_Occurred()) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  |         } | ||||||
|         return path_getitem(self, i); |         return path_getitem(self, i); | ||||||
|     } |     } | ||||||
|     if (PySlice_Check(item)) { |     if (PySlice_Check(item)) { | ||||||
|         int len = 4; |         int len = 4; | ||||||
|         Py_ssize_t start, stop, step, slicelength; |         Py_ssize_t start, stop, step, slicelength; | ||||||
| 
 | 
 | ||||||
|         if (PySlice_GetIndicesEx(item, len, &start, &stop, &step, &slicelength) < 0) |         if (PySlice_GetIndicesEx(item, len, &start, &stop, &step, &slicelength) < 0) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (slicelength <= 0) { |         if (slicelength <= 0) { | ||||||
|             double *xy = alloc_array(0); |             double *xy = alloc_array(0); | ||||||
|  |  | ||||||
|  | @ -170,9 +170,9 @@ deps = { | ||||||
|         "libs": [r"output\release-static\{architecture}\lib\*.lib"], |         "libs": [r"output\release-static\{architecture}\lib\*.lib"], | ||||||
|     }, |     }, | ||||||
|     "freetype": { |     "freetype": { | ||||||
|         "url": "https://download.savannah.gnu.org/releases/freetype/freetype-2.10.1.tar.gz",  # noqa: E501 |         "url": "https://download.savannah.gnu.org/releases/freetype/freetype-2.10.2.tar.gz",  # noqa: E501 | ||||||
|         "filename": "freetype-2.10.1.tar.gz", |         "filename": "freetype-2.10.2.tar.gz", | ||||||
|         "dir": "freetype-2.10.1", |         "dir": "freetype-2.10.2", | ||||||
|         "patch": { |         "patch": { | ||||||
|             r"builds\windows\vc2010\freetype.vcxproj": { |             r"builds\windows\vc2010\freetype.vcxproj": { | ||||||
|                 # freetype setting is /MD for .dll and /MT for .lib, we need /MD |                 # freetype setting is /MD for .dll and /MT for .lib, we need /MD | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user