diff --git a/.ci/install.sh b/.ci/install.sh index 36bce295c..3c75526fe 100755 --- a/.ci/install.sh +++ b/.ci/install.sh @@ -30,7 +30,11 @@ pip install -U pytest-cov pip install pyroma pip install test-image-results pip install numpy -if [ "$TRAVIS_PYTHON_VERSION" == "3.9-dev" ]; then pip install setuptools==47.3.1 ; fi + +# TODO Remove when 3.9-dev includes setuptools 49.3.2+: +if [ "$TRAVIS_PYTHON_VERSION" == "3.9-dev" ]; then pip install -U "setuptools>=49.3.2" ; fi +if [ "$GHA_PYTHON_VERSION" == "3.9-dev" ]; then pip install -U "setuptools>=49.3.2" ; fi + if [[ $TRAVIS_PYTHON_VERSION == 3.* ]]; then # arm64, ppc64le, s390x CPUs: # "ERROR: Could not find a version that satisfies the requirement pyqt5" diff --git a/.github/workflows/macos-install.sh b/.github/workflows/macos-install.sh index 76a3ef2b7..a0418c3ba 100755 --- a/.github/workflows/macos-install.sh +++ b/.github/workflows/macos-install.sh @@ -15,5 +15,8 @@ pip install test-image-results echo -e "[openblas]\nlibraries = openblas\nlibrary_dirs = /usr/local/opt/openblas/lib" >> ~/.numpy-site.cfg pip install numpy +# TODO Remove when 3.9-dev includes setuptools 49.3.2+: +if [ "$GHA_PYTHON_VERSION" == "3.9-dev" ]; then pip install -U "setuptools>=49.3.2" ; fi + # extra test images pushd depends && ./install_extra_test_images.sh && popd diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 9b04b2bd7..6b8b10445 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -63,6 +63,11 @@ jobs: - name: pip install wheel pytest pytest-cov run: python -m pip install wheel pytest pytest-cov + # TODO Remove when 3.9-dev includes setuptools 49.3.2+: + - name: Upgrade setuptools + if: "contains(matrix.python-version, '3.9-dev')" + run: python -m pip install -U "setuptools>=49.3.2" + - name: Prepare dependencies run: | 7z x winbuild\depends\nasm-2.14.02-win64.zip "-o$env:RUNNER_WORKSPACE\" @@ -163,25 +168,15 @@ jobs: msys: runs-on: windows-2019 - strategy: - fail-fast: false - matrix: - mingw: ["MINGW32", "MINGW64"] - include: - - mingw: "MINGW32" - package: "mingw-w64-i686" - - mingw: "MINGW64" - package: "mingw-w64-x86_64" - defaults: run: shell: bash.exe --login -eo pipefail "{0}" env: - MSYSTEM: ${{ matrix.mingw }} + MSYSTEM: MINGW64 CHERE_INVOKING: 1 timeout-minutes: 30 - name: MSYS2 ${{ matrix.mingw }} + name: MSYS2 MinGW 64-bit steps: - uses: actions/checkout@v2 @@ -193,23 +188,23 @@ jobs: - name: Install Dependencies run: | pacman -S --noconfirm \ - ${{ matrix.package }}-python3-pip \ - ${{ matrix.package }}-python3-setuptools \ - ${{ matrix.package }}-python3-pytest \ - ${{ matrix.package }}-python3-pytest-cov \ - ${{ matrix.package }}-python3-cffi \ - ${{ matrix.package }}-python3-olefile \ - ${{ matrix.package }}-python3-numpy \ - ${{ matrix.package }}-python3-pyqt5 \ - ${{ matrix.package }}-python3-numpy \ - ${{ matrix.package }}-freetype \ - ${{ matrix.package }}-lcms2 \ - ${{ matrix.package }}-libwebp \ - ${{ matrix.package }}-libjpeg-turbo \ - ${{ matrix.package }}-openjpeg2 \ - ${{ matrix.package }}-libimagequant \ - ${{ matrix.package }}-libraqm \ - ${{ matrix.package }}-ghostscript \ + mingw-w64-x86_64-python3-pip \ + mingw-w64-x86_64-python3-setuptools \ + mingw-w64-x86_64-python3-pytest \ + mingw-w64-x86_64-python3-pytest-cov \ + mingw-w64-x86_64-python3-cffi \ + mingw-w64-x86_64-python3-olefile \ + mingw-w64-x86_64-python3-numpy \ + mingw-w64-x86_64-python3-pyqt5 \ + mingw-w64-x86_64-python3-numpy \ + mingw-w64-x86_64-freetype \ + mingw-w64-x86_64-lcms2 \ + mingw-w64-x86_64-libwebp \ + mingw-w64-x86_64-libjpeg-turbo \ + mingw-w64-x86_64-openjpeg2 \ + mingw-w64-x86_64-libimagequant \ + mingw-w64-x86_64-libraqm \ + mingw-w64-x86_64-ghostscript \ subversion python3 -m pip install pyroma @@ -231,4 +226,4 @@ jobs: python3 -m pip install codecov bash <(curl -s https://codecov.io/bash) -F GHA_Windows env: - CODECOV_NAME: MSYS2 ${{ matrix.mingw }} + CODECOV_NAME: MSYS2 MinGW 64-bit diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 65673b0a2..dbe0eb822 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -62,11 +62,15 @@ jobs: if: startsWith(matrix.os, 'ubuntu') run: | .ci/install.sh + env: + GHA_PYTHON_VERSION: ${{ matrix.python-version }} - name: Install macOS dependencies if: startsWith(matrix.os, 'macOS') run: | .github/workflows/macos-install.sh + env: + GHA_PYTHON_VERSION: ${{ matrix.python-version }} - name: Build run: | diff --git a/CHANGES.rst b/CHANGES.rst index 6083cc7f3..c9389ddb1 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Changelog (Pillow) 8.0.0 (unreleased) ------------------ +- Read EXIF data tEXt chunk into info as bytes instead of string #4828 + [radarhere] + - Remove long-deprecated Image.py functions #4798 [hugovk, nulano, radarhere] diff --git a/Tests/images/exif_text.png b/Tests/images/exif_text.png new file mode 100644 index 000000000..e2d8dc0ff Binary files /dev/null and b/Tests/images/exif_text.png differ diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index f59936741..f580f4ae7 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -607,6 +607,11 @@ class TestFilePng: exif = im.copy().getexif() assert exif[274] == 1 + # With a tEXt chunk + with Image.open("Tests/images/exif_text.png") as im: + exif = im._getexif() + assert exif[274] == 1 + # With XMP tags with Image.open("Tests/images/xmp_tags_orientation.png") as im: exif = im.getexif() diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst index 89e3dfd4a..f54b7acf7 100644 --- a/docs/handbook/image-file-formats.rst +++ b/docs/handbook/image-file-formats.rst @@ -257,6 +257,9 @@ Using the :py:meth:`~PIL.Image.Image.draft` method, you can speed things up by converting ``RGB`` images to ``L``, and resize images to 1/2, 1/4 or 1/8 of their original size while loading them. +By default Pillow doesn't allow loading of truncated JPEG files, set +:data:`.ImageFile.LOAD_TRUNCATED_IMAGES` to override this. + The :py:meth:`~PIL.Image.open` method may set the following :py:attr:`~PIL.Image.Image.info` properties if available: @@ -473,6 +476,9 @@ image formats, EXIF data is not guaranteed to be present in :py:attr:`~PIL.Image.Image.info` until :py:meth:`~PIL.Image.Image.load` has been called. +By default Pillow doesn't allow loading of truncated PNG files, set +:data:`.ImageFile.LOAD_TRUNCATED_IMAGES` to override this. + The :py:func:`~PIL.Image.open` function sets the following :py:attr:`~PIL.Image.Image.info` properties, when appropriate: diff --git a/docs/handbook/writing-your-own-file-decoder.rst b/docs/handbook/writing-your-own-file-decoder.rst index 471ae3377..97cb5abe1 100644 --- a/docs/handbook/writing-your-own-file-decoder.rst +++ b/docs/handbook/writing-your-own-file-decoder.rst @@ -87,8 +87,10 @@ true color. Image.register_open(SpamImageFile.format, SpamImageFile, _accept) - Image.register_extension(SpamImageFile.format, ".spam") - Image.register_extension(SpamImageFile.format, ".spa") # DOS version + Image.register_extensions(SpamImageFile.format, [ + ".spam", + ".spa", # DOS version + ]) The format handler must always set the @@ -103,6 +105,15 @@ Note that the image plugin must be explicitly registered using :py:func:`PIL.Image.register_open`. Although not required, it is also a good idea to register any extensions used by this format. +Once the plugin has been imported, it can be used: + +.. code-block:: python + + from PIL import Image + import SpamImagePlugin + with Image.open("hopper.spam") as im: + pass + The ``tile`` attribute ---------------------- @@ -148,6 +159,8 @@ can be used with most uncompressed file formats, such as PPM, BMP, uncompressed TIFF, and many others. To use the raw decoder with the :py:func:`PIL.Image.frombytes` function, use the following syntax:: +.. code-block:: python + image = Image.frombytes( mode, size, data, "raw", raw mode, stride, orientation @@ -258,6 +271,8 @@ image memory. To use the bit decoder with the :py:func:`PIL.Image.frombytes` function, use the following syntax:: +.. code-block:: python + image = Image.frombytes( mode, size, data, "bit", bits, pad, fill, sign, orientation @@ -350,7 +365,7 @@ interest in this object are: The target image, will be set by Pillow. **state** - An ImagingCodecStateInstance, will be set by Pillow. The **context** + An ImagingCodecStateInstance, will be set by Pillow. The ``context`` member is an opaque struct that can be used by the decoder to store any format specific state or options. @@ -414,4 +429,3 @@ Python-based file decoder: 3. Cleanup: The decoder instance's ``cleanup`` method is called. - diff --git a/docs/reference/ImageChops.rst b/docs/reference/ImageChops.rst index 772d9c983..9519361a7 100644 --- a/docs/reference/ImageChops.rst +++ b/docs/reference/ImageChops.rst @@ -39,12 +39,7 @@ operations in this module). .. autofunction:: PIL.ImageChops.soft_light .. autofunction:: PIL.ImageChops.hard_light .. autofunction:: PIL.ImageChops.overlay -.. py:method:: PIL.ImageChops.offset(image, xoffset, yoffset=None) - - Returns a copy of the image where data has been offset by the given - distances. Data wraps around the edges. If **yoffset** is omitted, it - is assumed to be equal to **xoffset**. - +.. autofunction:: PIL.ImageChops.offset .. autofunction:: PIL.ImageChops.screen .. autofunction:: PIL.ImageChops.subtract .. autofunction:: PIL.ImageChops.subtract_modulo diff --git a/docs/reference/ImageFile.rst b/docs/reference/ImageFile.rst index 333876bc8..e0ce389e8 100644 --- a/docs/reference/ImageFile.rst +++ b/docs/reference/ImageFile.rst @@ -52,3 +52,10 @@ Classes .. autoclass:: PIL.ImageFile.StubImageFile() :members: :show-inheritance: + +Constants +--------- + +.. autodata:: PIL.ImageFile.LOAD_TRUNCATED_IMAGES +.. autodata:: PIL.ImageFile.ERRORS + :annotation: diff --git a/docs/reference/ImageFont.rst b/docs/reference/ImageFont.rst index fc61cac13..ff79bdcd8 100644 --- a/docs/reference/ImageFont.rst +++ b/docs/reference/ImageFont.rst @@ -56,3 +56,19 @@ Methods .. autoclass:: PIL.ImageFont.TransposedFont :members: + +Constants +--------- + +.. data:: PIL.ImageFont.LAYOUT_BASIC + + Use basic text layout for TrueType font. + Advanced features such as text direction are not supported. + +.. data:: PIL.ImageFont.LAYOUT_RAQM + + Use Raqm text layout for TrueType font. + Advanced features are supported. + + Requires Raqm, you can check support using + :py:func:`PIL.features.check_feature` with ``feature="raqm"``. diff --git a/docs/reference/ImagePath.rst b/docs/reference/ImagePath.rst index 21a202b5e..b9bdfc507 100644 --- a/docs/reference/ImagePath.rst +++ b/docs/reference/ImagePath.rst @@ -33,7 +33,7 @@ vector data. Path objects can be passed to the methods on the method modifies the path in place, and returns the number of points left in the path. - **distance** is measured as `Manhattan distance`_ and defaults to two + ``distance`` is measured as `Manhattan distance`_ and defaults to two pixels. .. _Manhattan distance: https://en.wikipedia.org/wiki/Manhattan_distance @@ -55,7 +55,7 @@ vector data. Path objects can be passed to the methods on the :param flat: By default, this function returns a list of 2-tuples [(x, y), ...]. If this argument is ``True``, it returns a flat list [x, y, ...] instead. - :return: A list of coordinates. See **flat**. + :return: A list of coordinates. See ``flat``. .. py:method:: PIL.ImagePath.Path.transform(matrix) diff --git a/src/PIL/Image.py b/src/PIL/Image.py index db639f524..8ab67d55e 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -855,7 +855,7 @@ class Image: and the palette can be represented without a palette. The current version supports all possible conversions between - "L", "RGB" and "CMYK." The **matrix** argument only supports "L" + "L", "RGB" and "CMYK." The ``matrix`` argument only supports "L" and "RGB". When translating a color image to greyscale (mode "L"), @@ -870,9 +870,9 @@ class Image: all other values to 0 (black). To use other thresholds, use the :py:meth:`~PIL.Image.Image.point` method. - When converting from "RGBA" to "P" without a **matrix** argument, + When converting from "RGBA" to "P" without a ``matrix`` argument, this passes the operation to :py:meth:`~PIL.Image.Image.quantize`, - and **dither** and **palette** are ignored. + and ``dither`` and ``palette`` are ignored. :param mode: The requested mode. See: :ref:`concept-modes`. :param matrix: An optional conversion matrix. If given, this @@ -880,7 +880,7 @@ class Image: :param dither: Dithering method, used when converting from mode "RGB" to "P" or from "RGB" or "L" to "1". Available methods are :data:`NONE` or :data:`FLOYDSTEINBERG` (default). - Note that this is not used when **matrix** is supplied. + Note that this is not used when ``matrix`` is supplied. :param palette: Palette to use when converting from mode "RGB" to "P". Available palettes are :data:`WEB` or :data:`ADAPTIVE`. :param colors: Number of colors to use for the :data:`ADAPTIVE` palette. @@ -1205,7 +1205,7 @@ class Image: def getbands(self): """ Returns a tuple containing the name of each band in this image. - For example, **getbands** on an RGB image returns ("R", "G", "B"). + For example, ``getbands`` on an RGB image returns ("R", "G", "B"). :returns: A tuple containing band names. :rtype: tuple @@ -1259,7 +1259,7 @@ class Image: Note that the sequence object returned by this method is an internal PIL data type, which only supports certain sequence operations. To convert it to an ordinary sequence (e.g. for - printing), use **list(im.getdata())**. + printing), use ``list(im.getdata())``. :param band: What band to return. The default is to return all bands. To return a single band, pass in the index @@ -1740,7 +1740,7 @@ class Image: Rewrites the image to reorder the palette. :param dest_map: A list of indexes into the original palette. - e.g. [1,0] would swap a two item palette, and list(range(256)) + e.g. ``[1,0]`` would swap a two item palette, and ``list(range(256))`` is the identity transform. :param source_palette: Bytes or None. :returns: An :py:class:`~PIL.Image.Image` object. @@ -1922,16 +1922,16 @@ class Image: def reduce(self, factor, box=None): """ - Returns a copy of the image reduced by `factor` times. - If the size of the image is not dividable by the `factor`, + Returns a copy of the image reduced ``factor`` times. + If the size of the image is not dividable by ``factor``, the resulting size will be rounded up. :param factor: A greater than 0 integer or tuple of two integers for width and height separately. :param box: An optional 4-tuple of ints providing the source image region to be reduced. - The values must be within (0, 0, width, height) rectangle. - If omitted or None, the entire source is used. + The values must be within ``(0, 0, width, height)`` rectangle. + If omitted or ``None``, the entire source is used. """ if not isinstance(factor, (list, tuple)): factor = (factor, factor) @@ -2354,7 +2354,7 @@ class Image: # Return result It may also be an object with a ``method.getdata`` method - that returns a tuple supplying new **method** and **data** values:: + that returns a tuple supplying new ``method`` and ``data`` values:: class Example: def getdata(self): @@ -2369,7 +2369,7 @@ class Image: interpolation in a 4x4 environment). If omitted, or if the image has mode "1" or "P", it is set to :py:data:`PIL.Image.NEAREST`. See: :ref:`concept-filters`. - :param fill: If **method** is an + :param fill: If ``method`` is an :py:class:`~PIL.Image.ImageTransformHandler` object, this is one of the arguments passed to it. Otherwise, it is unused. :param fillcolor: Optional fill color for the area outside the @@ -2668,7 +2668,7 @@ def frombuffer(mode, size, data, decoder_name="raw", *args): Note that this function decodes pixel data only, not entire images. If you have an entire image file in a string, wrap it in a - **BytesIO** object, and use :py:func:`~PIL.Image.open` to load it. + :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load it. In the current version, the default parameters used for the "raw" decoder differs from that used for :py:func:`~PIL.Image.frombytes`. This is a @@ -2715,7 +2715,7 @@ def fromarray(obj, mode=None): Creates an image memory from an object exporting the array interface (using the buffer protocol). - If **obj** is not contiguous, then the tobytes method is called + If ``obj`` is not contiguous, then the ``tobytes`` method is called and :py:func:`~PIL.Image.frombuffer` is used. If you have an image in NumPy:: diff --git a/src/PIL/ImageChops.py b/src/PIL/ImageChops.py index 9fccedcb2..61d3a295b 100644 --- a/src/PIL/ImageChops.py +++ b/src/PIL/ImageChops.py @@ -313,8 +313,8 @@ def composite(image1, image2, mask): def offset(image, xoffset, yoffset=None): """Returns a copy of the image where data has been offset by the given - distances. Data wraps around the edges. If **yoffset** is omitted, it - is assumed to be equal to **xoffset**. + distances. Data wraps around the edges. If ``yoffset`` is omitted, it + is assumed to be equal to ``xoffset``. :param xoffset: The horizontal distance. :param yoffset: The vertical distance. If omitted, both diff --git a/src/PIL/ImageCms.py b/src/PIL/ImageCms.py index 1c4ce5a08..8155a0b2d 100644 --- a/src/PIL/ImageCms.py +++ b/src/PIL/ImageCms.py @@ -250,7 +250,9 @@ class ImageCmsTransform(Image.ImagePointHandler): def get_display_profile(handle=None): - """ (experimental) Fetches the profile for the current display device. + """ + (experimental) Fetches the profile for the current display device. + :returns: ``None`` if the profile is not known. """ @@ -624,7 +626,7 @@ def applyTransform(im, transform, inPlace=False): :param im: An :py:class:`~PIL.Image.Image` object, and im.mode must be the same as the ``inMode`` supported by the transform. :param transform: A valid CmsTransform class object - :param inPlace: Bool. If ``True``, ``im` is modified in place and ``None`` is + :param inPlace: Bool. If ``True``, ``im`` is modified in place and ``None`` is returned, if ``False``, a new :py:class:`~PIL.Image.Image` object with the transform applied is returned (and ``im`` is not changed). The default is ``False``. diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py index 648101ee3..81ec0c266 100644 --- a/src/PIL/ImageFile.py +++ b/src/PIL/ImageFile.py @@ -40,6 +40,7 @@ MAXBLOCK = 65536 SAFEBLOCK = 1024 * 1024 LOAD_TRUNCATED_IMAGES = False +"""Whether or not to load truncated image files. User code may change this.""" ERRORS = { -1: "image buffer overrun error", @@ -48,6 +49,7 @@ ERRORS = { -8: "bad configuration", -9: "out of memory error", } +"""Dict of known error codes returned from :meth:`.PyDecoder.decode`.""" # @@ -583,7 +585,7 @@ class PyCodecState: class PyDecoder: """ Python implementation of a format decoder. Override this class and - add the decoding logic in the `decode` method. + add the decoding logic in the :meth:`decode` method. See :ref:`Writing Your Own File Decoder in Python` """ @@ -615,9 +617,9 @@ class PyDecoder: Override to perform the decoding process. :param buffer: A bytes object with the data to be decoded. - :returns: A tuple of (bytes consumed, errcode). + :returns: A tuple of ``(bytes consumed, errcode)``. If finished with decoding return <0 for the bytes consumed. - Err codes are from `ERRORS` + Err codes are from :data:`.ImageFile.ERRORS`. """ raise NotImplementedError() diff --git a/src/PIL/ImageFilter.py b/src/PIL/ImageFilter.py index 18c550c84..0e76f85f9 100644 --- a/src/PIL/ImageFilter.py +++ b/src/PIL/ImageFilter.py @@ -69,7 +69,7 @@ class Kernel(BuiltinFilter): class RankFilter(Filter): """ Create a rank filter. The rank filter sorts all pixels in - a window of the given size, and returns the **rank**'th value. + a window of the given size, and returns the ``rank``'th value. :param size: The kernel size, in pixels. :param rank: What pixel value to pick. Use 0 for a min filter, diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 8f792d55b..9a1ede80c 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -638,7 +638,7 @@ def truetype(font=None, size=10, index=0, encoding="", layout_engine=None): This specifies the character set to use. It does not alter the encoding of any text provided in subsequent operations. :param layout_engine: Which layout engine to use, if available: - `ImageFont.LAYOUT_BASIC` or `ImageFont.LAYOUT_RAQM`. + :data:`.ImageFont.LAYOUT_BASIC` or :data:`.ImageFont.LAYOUT_RAQM`. You can check support for Raqm layout using :py:func:`PIL.features.check_feature` with ``feature="raqm"``. diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index 87d459fd1..14602a5c8 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -64,7 +64,7 @@ def _lut(image, lut): def autocontrast(image, cutoff=0, ignore=None, mask=None): """ Maximize (normalize) image contrast. This function calculates a - histogram of the input image (or mask region), removes **cutoff** percent of the + histogram of the input image (or mask region), removes ``cutoff`` percent of the lightest and darkest pixels from the histogram, and remaps the image so that the darkest pixel becomes black (0), and the lightest becomes white (255). @@ -149,14 +149,14 @@ def colorize(image, black, white, mid=None, blackpoint=0, whitepoint=255, midpoi Colorize grayscale image. This function calculates a color wedge which maps all black pixels in the source image to the first color and all white pixels to the - second color. If **mid** is specified, it uses three-color mapping. - The **black** and **white** arguments should be RGB tuples or color names; - optionally you can use three-color mapping by also specifying **mid**. + second color. If ``mid`` is specified, it uses three-color mapping. + The ``black`` and ``white`` arguments should be RGB tuples or color names; + optionally you can use three-color mapping by also specifying ``mid``. Mapping positions for any of the colors can be specified - (e.g. **blackpoint**), where these parameters are the integer + (e.g. ``blackpoint``), where these parameters are the integer value corresponding to where the corresponding color should be mapped. These parameters must have logical order, such that - **blackpoint** <= **midpoint** <= **whitepoint** (if **mid** is specified). + ``blackpoint <= midpoint <= whitepoint`` (if ``mid`` is specified). :param image: The image to colorize. :param black: The color to use for black input pixels. @@ -315,7 +315,7 @@ def deform(image, deformer, resample=Image.BILINEAR): :param image: The image to deform. :param deformer: A deformer object. Any object that implements a - **getmesh** method can be used. + ``getmesh`` method can be used. :param resample: An optional resampling filter. Same values possible as in the PIL.Image.transform function. :return: An image. diff --git a/src/PIL/ImageTk.py b/src/PIL/ImageTk.py index ee707cffb..49b598ad2 100644 --- a/src/PIL/ImageTk.py +++ b/src/PIL/ImageTk.py @@ -69,7 +69,7 @@ class PhotoImage: image, pixels having alpha 0 are treated as transparent. The constructor takes either a PIL image, or a mode and a size. - Alternatively, you can use the **file** or **data** options to initialize + Alternatively, you can use the ``file`` or ``data`` options to initialize the photo image object. :param image: Either a PIL image, or a mode string. If a mode string is @@ -210,7 +210,7 @@ class BitmapImage: The given image must have mode "1". Pixels having value 0 are treated as transparent. Options, if any, are passed on to Tkinter. The most commonly - used option is **foreground**, which is used to specify the color for the + used option is ``foreground``, which is used to specify the color for the non-transparent parts. See the Tkinter documentation for information on how to specify colours. diff --git a/src/PIL/ImageWin.py b/src/PIL/ImageWin.py index 2ca4acdf8..ca9b14c8a 100644 --- a/src/PIL/ImageWin.py +++ b/src/PIL/ImageWin.py @@ -59,7 +59,7 @@ class Dib: with 20 greylevels. To make sure that palettes work properly under Windows, you must call the - **palette** method upon certain events from Windows. + ``palette`` method upon certain events from Windows. :param image: Either a PIL image, or a mode string. If a mode string is used, a size must also be given. The mode can be one of "1", diff --git a/src/PIL/JpegPresets.py b/src/PIL/JpegPresets.py index 09691d79d..79d10ebb2 100644 --- a/src/PIL/JpegPresets.py +++ b/src/PIL/JpegPresets.py @@ -34,7 +34,7 @@ Possible subsampling values are 0, 1 and 2 that correspond to 4:4:4, 4:2:2 and 4:2:0. You can get the subsampling of a JPEG with the -`JpegImagePlugin.get_sampling(im)` function. +:func:`.JpegImagePlugin.get_sampling` function. In JPEG compressed data a JPEG marker is used instead of an EXIF tag. (ref.: https://www.exiv2.org/tags.html) @@ -64,7 +64,7 @@ The tables format between im.quantization and quantization in presets differ in 3. The zigzag order is remove in the preset (needed by libjpeg >= 6a). You can convert the dict format to the preset format with the -`JpegImagePlugin.convert_dict_qtables(dict_qtables)` function. +:func:`.JpegImagePlugin.convert_dict_qtables()` function. Libjpeg ref.: https://web.archive.org/web/20120328125543/http://www.jpegcameras.com/libjpeg/libjpeg-3.html diff --git a/src/PIL/PSDraw.py b/src/PIL/PSDraw.py index 3cfcbaf28..4061e3655 100644 --- a/src/PIL/PSDraw.py +++ b/src/PIL/PSDraw.py @@ -25,7 +25,7 @@ from . import EpsImagePlugin class PSDraw: """ - Sets up printing to the given file. If **fp** is omitted, + Sets up printing to the given file. If ``fp`` is omitted, :py:data:`sys.stdout` is assumed. """ diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index 0c53a031b..192c94c89 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -514,10 +514,11 @@ class PngStream(ChunkStream): v = b"" if k: k = k.decode("latin-1", "strict") - v = v.decode("latin-1", "replace") + v_str = v.decode("latin-1", "replace") - self.im_info[k] = self.im_text[k] = v - self.check_text_memory(len(v)) + self.im_info[k] = v if k == "exif" else v_str + self.im_text[k] = v_str + self.check_text_memory(len(v_str)) return s diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 6a772e48b..018789abf 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -414,7 +414,7 @@ class ImageFileDirectory_v2(MutableMapping): The tiff metadata type of each item is stored in a dictionary of tag types in - `~PIL.TiffImagePlugin.ImageFileDirectory_v2.tagtype`. The types + :attr:`~PIL.TiffImagePlugin.ImageFileDirectory_v2.tagtype`. The types are read from a tiff file, guessed from the type added, or added manually. @@ -885,7 +885,7 @@ class ImageFileDirectory_v1(ImageFileDirectory_v2): ('Some Data',) Also contains a dictionary of tag types as read from the tiff image file, - `~PIL.TiffImagePlugin.ImageFileDirectory_v1.tagtype`. + :attr:`~PIL.TiffImagePlugin.ImageFileDirectory_v1.tagtype`. Values are returned as a tuple. @@ -899,6 +899,10 @@ class ImageFileDirectory_v1(ImageFileDirectory_v2): tags = property(lambda self: self._tags_v1) tagdata = property(lambda self: self._tagdata) + # defined in ImageFileDirectory_v2 + tagtype: dict + """Dictionary of tag types""" + @classmethod def from_v2(cls, original): """ Returns an diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py index 41da45e45..abd56be0c 100644 --- a/winbuild/build_prepare.py +++ b/winbuild/build_prepare.py @@ -205,7 +205,7 @@ deps = { # retarget to default toolset (selected by vcvarsall.bat) "v141": "$(DefaultPlatformToolset)", # noqa: E501 # retarget to latest (selected by vcvarsall.bat) - "8.1": "$(WindowsSDKVersion)", # noqa: E501 + "10.0.17134.0": "$(WindowsSDKVersion)", # noqa: E501 } }, "build": [ @@ -420,7 +420,10 @@ def build_dep(name): with open(patch_file, "r") as f: text = f.read() for patch_from, patch_to in patch_list.items(): - text = text.replace(patch_from.format(**prefs), patch_to.format(**prefs)) + patch_from = patch_from.format(**prefs) + patch_to = patch_to.format(**prefs) + assert patch_from in text + text = text.replace(patch_from, patch_to) with open(patch_file, "w") as f: f.write(text)