Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added docs/handbook/animated_hopper.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/contrasted_hopper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/cropped_hopper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/enhanced_hopper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/flip_left_right_hopper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/flip_top_bottom_hopper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/masked_hopper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/merged_hopper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/pasted_hopper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/rebanded_hopper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/rolled_hopper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/rotated_hopper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/rotated_hopper_180.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/rotated_hopper_270.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/rotated_hopper_90.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/show_hopper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/thumbnail_hopper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/handbook/transformed_hopper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
104 changes: 102 additions & 2 deletions docs/handbook/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ example, let’s display the image we just loaded::

>>> im.show()

.. image:: show_hopper.png
:align: center

.. note::

The standard version of :py:meth:`~PIL.Image.Image.show` is not very
Expand Down Expand Up @@ -79,6 +82,9 @@ Convert files to JPEG
except OSError:
print("cannot convert", infile)

.. image:: ../../Tests/images/hopper.jpg
:align: center

A second argument can be supplied to the :py:meth:`~PIL.Image.Image.save`
method which explicitly specifies a file format. If you use a non-standard
extension, you must always specify the format this way:
Expand All @@ -103,6 +109,9 @@ Create JPEG thumbnails
except OSError:
print("cannot create thumbnail for", infile)

.. image:: thumbnail_hopper.jpg
:align: center

It is important to note that the library doesn’t decode or load the raster data
unless it really has to. When you open a file, the file header is read to
determine the file format and extract things like mode, size, and other
Expand Down Expand Up @@ -150,6 +159,9 @@ pixels, so the region in the above example is exactly 300x300 pixels.

The region could now be processed in a certain manner and pasted back.

.. image:: cropped_hopper.jpg
:align: center

Processing a subrectangle, and pasting it back
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand All @@ -164,6 +176,9 @@ modes of the original image and the region do not need to match. If they don’t
the region is automatically converted before being pasted (see the section on
:ref:`color-transforms` below for details).

.. image:: pasted_hopper.jpg
:align: center

Here’s an additional example:

Rolling an image
Expand All @@ -186,6 +201,9 @@ Rolling an image

return im

.. image:: rolled_hopper.jpg
:align: center

Or if you would like to merge two images into a wider image:

Merging images
Expand All @@ -203,6 +221,9 @@ Merging images

return im

.. image:: merged_hopper.png
:align: center

For more advanced tricks, the paste method can also take a transparency mask as
an optional argument. In this mask, the value 255 indicates that the pasted
image is opaque in that position (that is, the pasted image should be used as
Expand All @@ -229,6 +250,9 @@ Note that for a single-band image, :py:meth:`~PIL.Image.Image.split` returns
the image itself. To work with individual color bands, you may want to convert
the image to “RGB” first.

.. image:: rebanded_hopper.jpg
:align: center

Geometrical transforms
----------------------

Expand All @@ -245,6 +269,9 @@ Simple geometry transforms
out = im.resize((128, 128))
out = im.rotate(45) # degrees counter-clockwise

.. image:: rotated_hopper_90.jpg
:align: center

To rotate the image in 90 degree steps, you can either use the
:py:meth:`~PIL.Image.Image.rotate` method or the
:py:meth:`~PIL.Image.Image.transpose` method. The latter can also be used to
Expand All @@ -256,11 +283,38 @@ Transposing an image
::

out = im.transpose(Image.Transpose.FLIP_LEFT_RIGHT)

.. image:: flip_left_right_hopper.jpg
:align: center

::

out = im.transpose(Image.Transpose.FLIP_TOP_BOTTOM)

.. image:: flip_top_bottom_hopper.jpg
:align: center

::

out = im.transpose(Image.Transpose.ROTATE_90)

.. image:: rotated_hopper_90.jpg
:align: center

::

out = im.transpose(Image.Transpose.ROTATE_180)

.. image:: rotated_hopper_180.jpg
:align: center

::

out = im.transpose(Image.Transpose.ROTATE_270)

.. image:: rotated_hopper_270.jpg
:align: center

``transpose(ROTATE)`` operations can also be performed identically with
:py:meth:`~PIL.Image.Image.rotate` operations, provided the ``expand`` flag is
true, to provide for the same changes to the image's size.
Expand Down Expand Up @@ -342,6 +396,9 @@ Applying filters
from PIL import ImageFilter
out = im.filter(ImageFilter.DETAIL)

.. image:: enhanced_hopper.jpg
:align: center

Point Operations
^^^^^^^^^^^^^^^^

Expand All @@ -358,6 +415,9 @@ Applying point transforms
# multiply each pixel by 1.2
out = im.point(lambda i: i * 1.2)

.. image:: transformed_hopper.jpg
:align: center
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from PIL import Image
im = Image.open("Tests/images/hopper.png")
out = im.point(lambda i: i * 1.2)
out.save("transformed_hopper.jpg")

gives me

transformed_hopper

Yours looks different?
transformed_hopper_pr

Copy link
Member

@hugovk hugovk Jul 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aclark4life I get the same as @radarhere, does this need fixing?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, fixed in 96fa1f5!


Using the above technique, you can quickly apply any simple expression to an
image. You can also combine the :py:meth:`~PIL.Image.Image.point` and
:py:meth:`~PIL.Image.Image.paste` methods to selectively modify an image:
Expand Down Expand Up @@ -388,6 +448,9 @@ Note the syntax used to create the mask::

imout = im.point(lambda i: expression and 255)

.. image:: masked_hopper.jpg
:align: center

Python only evaluates the portion of a logical expression as is necessary to
determine the outcome, and returns the last value examined as the result of the
expression. So if the expression above is false (0), Python does not look at
Expand All @@ -412,6 +475,10 @@ Enhancing images
enh = ImageEnhance.Contrast(im)
enh.enhance(1.3).show("30% more contrast")


.. image:: contrasted_hopper.jpg
:align: center

Image sequences
---------------

Expand Down Expand Up @@ -444,10 +511,43 @@ Reading sequences
As seen in this example, you’ll get an :py:exc:`EOFError` exception when the
sequence ends.

Writing sequences
^^^^^^^^^^^^^^^^^

You can create animated GIFs with Pillow, e.g.

::

from PIL import Image

# List of image filenames
image_filenames = [
"hopper.jpg",
"rotated_hopper_270.jpg",
"rotated_hopper_180.jpg",
"rotated_hopper_90.jpg",
]

# Open images and append them to a list
images = [Image.open(filename) for filename in image_filenames]

# Save the images as an animated GIF
images[0].save(
"animated_hopper.gif",
save_all=True,
append_images=images[1:],
duration=500, # duration of each frame in milliseconds
loop=0, # loop forever
)


.. image:: animated_hopper.gif
:align: center

The following class lets you use the for-statement to loop over the sequence:

Using the ImageSequence Iterator class
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Using the :py:class:`~PIL.ImageSequence.Iterator` class
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

::

Expand Down