

Image moduleImageChops (“channel operations”) moduleImageCms moduleImageColor moduleImageDraw moduleImageEnhance moduleImageFile moduleImageFilter moduleImageFont moduleImageGrab moduleImageMath moduleImageMorph moduleImageOps moduleImagePalette moduleImagePath moduleImageQt moduleImageSequence moduleImageShow moduleImageStat moduleImageText moduleImageTk moduleImageTransform moduleImageWin module (Windows-only)ExifTags moduleTiffTags moduleJpegPresets modulePSDraw modulePixelAccess classfeatures moduleThe most important class in the Python Imaging Library is theImage class, defined in the module with the same name.You can create instances of this class in several ways; either by loadingimages from files, processing other images, or creating images from scratch.
To load an image from a file, use theopen() functionin theImage module:
>>>fromPILimportImage>>>im=Image.open("hopper.ppm")
If successful, this function returns anImage object.You can now use instance attributes to examine the file contents:
>>>print(im.format,im.size,im.mode)PPM (512, 512) RGB
Theformat attribute identifies the source of animage. If the image was not read from a file, it is set to None. The sizeattribute is a 2-tuple containing width and height (in pixels). Themode attribute defines the number and names of thebands in the image, and also the pixel type and depth. Common modes are “L”(luminance) for grayscale images, “RGB” for true color images, and “CMYK” forpre-press images.
If the file cannot be opened, anOSError exception is raised.
Once you have an instance of theImage class, you can usethe methods defined by this class to process and manipulate the image. Forexample, let’s display the image we just loaded:
>>>im.show()

Note
The standard version ofshow() is not veryefficient, since it saves the image to a temporary file and calls a utilityto display the image. If you don’t have an appropriate utility installed,it won’t even work. When it does work though, it is very handy fordebugging and tests.
The following sections provide an overview of the different functions provided in this library.
The Python Imaging Library supports a wide variety of image file formats. Toread files from disk, use theopen() function in theImage module. You don’t have to know the file format to open afile. The library automatically determines the format based on the contents ofthe file.
To save a file, use thesave() method of theImage class. When saving files, the name becomesimportant. Unless you specify the format, the library uses the filenameextension to discover which file storage format to use.
importos,sysfromPILimportImageforinfileinsys.argv[1:]:f,e=os.path.splitext(infile)outfile=f+".jpg"ifinfile!=outfile:try:withImage.open(infile)asim:im.save(outfile)exceptOSError:print("cannot convert",infile)

A second argument can be supplied to thesave()method which explicitly specifies a file format. If you use a non-standardextension, you must always specify the format this way:
importos,sysfromPILimportImagesize=(128,128)forinfileinsys.argv[1:]:outfile=os.path.splitext(infile)[0]+".thumbnail"ifinfile!=outfile:try:withImage.open(infile)asim:im.thumbnail(size)im.save(outfile,"JPEG")exceptOSError:print("cannot create thumbnail for",infile)
It is important to note that the library doesn’t decode or load the raster dataunless it really has to. When you open a file, the file header is read todetermine the file format and extract things like mode, size, and otherproperties required to decode the file, but the rest of the file is notprocessed until later.
This means that opening an image file is a fast operation, which is independentof the file size and compression type. Here’s a simple script to quicklyidentify a set of image files:
importsysfromPILimportImageforinfileinsys.argv[1:]:try:withImage.open(infile)asim:print(infile,im.format,f"{im.size}x{im.mode}")exceptOSError:pass
TheImage class contains methods allowing you tomanipulate regions within an image. To extract a sub-rectangle from an image,use thecrop() method.
box=(0,0,64,64)region=im.crop(box)
The region is defined by a 4-tuple, where coordinates are (left, upper, right,lower). The Python Imaging Library uses a coordinate system with (0, 0) in theupper left corner. Also note that coordinates refer to positions between thepixels, so the region in the above example is exactly 64x64 pixels.
The region could now be processed in a certain manner and pasted back.

region=region.transpose(Image.Transpose.ROTATE_180)im.paste(region,box)
When pasting regions back, the size of the region must match the given regionexactly. In addition, the region cannot extend outside the image. However, themodes 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 onColor transforms below for details).

Here’s an additional example:
defroll(im:Image.Image,delta:int)->Image.Image:"""Roll an image sideways."""xsize,ysize=im.sizedelta=delta%xsizeifdelta==0:returnimpart1=im.crop((0,0,delta,ysize))part2=im.crop((delta,0,xsize,ysize))im.paste(part1,(xsize-delta,0,xsize,ysize))im.paste(part2,(0,0,xsize-delta,ysize))returnim

Or if you would like to merge two images into a wider image:
defmerge(im1:Image.Image,im2:Image.Image)->Image.Image:w=im1.size[0]+im2.size[0]h=max(im1.size[1],im2.size[1])im=Image.new("RGBA",(w,h))im.paste(im1)im.paste(im2,(im1.size[0],0))returnim

For more advanced tricks, the paste method can also take a transparency mask asan optional argument. In this mask, the value 255 indicates that the pastedimage is opaque in that position (that is, the pasted image should be used asis). The value 0 means that the pasted image is completely transparent. Valuesin-between indicate different levels of transparency. For example, pasting anRGBA image and also using it as the mask would paste the opaque portionof the image but not its transparent background.
The Python Imaging Library also allows you to work with the individual bands ofan multi-band image, such as an RGB image. The split method creates a set ofnew images, each containing one band from the original multi-band image. Themerge function takes a mode and a tuple of images, and combines them into a newimage. The following sample swaps the three bands of an RGB image:
r,g,b=im.split()im=Image.merge("RGB",(b,g,r))
Note that for a single-band image,split() returnsthe image itself. To work with individual color bands, you may want to convertthe image to “RGB” first.

ThePIL.Image.Image class contains methods toresize() androtate() animage. The former takes a tuple giving the new size, the latter the angle indegrees counter-clockwise.
out=im.resize((128,128))out=im.rotate(45)# degrees counter-clockwise

To rotate the image in 90 degree steps, you can either use therotate() method or thetranspose() method. The latter can also be used toflip an image around its horizontal or vertical axis.
out=im.transpose(Image.Transpose.FLIP_LEFT_RIGHT)

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

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

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

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

transpose(ROTATE) operations can also be performed identically withrotate() operations, provided theexpand flag istrue, to provide for the same changes to the image’s size.
A more general form of image transformations can be carried out via thetransform() method.
Instead of calculating the size of the new image when resizing, you can alsochoose to resize relative to a given size.
fromPILimportImage,ImageOpssize=(100,150)withImage.open("hopper.webp")asim:ImageOps.contain(im,size).save("imageops_contain.webp")ImageOps.cover(im,size).save("imageops_cover.webp")ImageOps.fit(im,size).save("imageops_fit.webp")ImageOps.pad(im,size,color="#f00").save("imageops_pad.webp")# thumbnail() can also be used,# but will modify the image object in placeim.thumbnail(size)im.save("image_thumbnail.webp")
Given size |
|
|
|
|
|
Resulting image | ![]() | ![]() | ![]() | ![]() | |
Resulting size |
|
|
|
|
|
The Python Imaging Library allows you to convert images between different pixelrepresentations using theconvert() method.
fromPILimportImagewithImage.open("hopper.ppm")asim:im=im.convert("L")
The library supports transformations between each supported mode and the “L”and “RGB” modes. To convert between other modes, you may have to use anintermediate image (typically an “RGB” image).
The Python Imaging Library provides a number of methods and modules that can beused to enhance images.
TheImageFilter module contains a number of pre-definedenhancement filters that can be used with thefilter() method.
fromPILimportImageFilterout=im.filter(ImageFilter.DETAIL)

Thepoint() method can be used to translate the pixelvalues of an image (e.g. image contrast manipulation). In most cases, afunction object expecting one argument can be passed to this method. Eachpixel is processed according to that function:
# multiply each pixel by 20out=im.point(lambdai:i*20)

Using the above technique, you can quickly apply any simple expression to animage. You can also combine thepoint() andpaste() methods to selectively modify an image:
# split the image into individual bandssource=im.split()R,G,B=0,1,2# select regions where red is less than 100mask=source[R].point(lambdai:i<100and255)# process the green bandout=source[G].point(lambdai:i*0.7)# paste the processed band back, but only where red was < 100source[G].paste(out,None,mask)# build a new multiband imageim=Image.merge(im.mode,source)
Note the syntax used to create the mask:
imout=im.point(lambdai:expressionand255)

Python only evaluates the portion of a logical expression as is necessary todetermine the outcome, and returns the last value examined as the result of theexpression. So if the expression above is false (0), Python does not look atthe second operand, and thus returns 0. Otherwise, it returns 255.
For more advanced image enhancement, you can use the classes in theImageEnhance module. Once created from an image, an enhancementobject can be used to quickly try out different settings.
You can adjust contrast, brightness, color balance and sharpness in this way.
fromPILimportImageEnhanceenh=ImageEnhance.Contrast(im)enh.enhance(1.3).show("30% more contrast")

The Python Imaging Library contains some basic support for image sequences(also called animation formats). Supported sequence formats include FLI/FLC,GIF, and a few experimental formats. TIFF files can also contain more than oneframe.
When you open a sequence file, PIL automatically loads the first frame in thesequence. You can use the seek and tell methods to move between differentframes:
fromPILimportImagewithImage.open("animation.gif")asim:im.seek(1)# skip to the second frametry:while1:im.seek(im.tell()+1)# do something to imexceptEOFError:pass# end of sequence
As seen in this example, you’ll get anEOFError exception when thesequence ends.
You can create animated GIFs with Pillow, e.g.
fromPILimportImage# List of image filenamesimage_filenames=["hopper.jpg","rotated_hopper_270.jpg","rotated_hopper_180.jpg","rotated_hopper_90.jpg",]# Open images and create a listimages=[Image.open(filename)forfilenameinimage_filenames]# Save the images as an animated GIFimages[0].save("animated_hopper.gif",append_images=images[1:],duration=500,# duration of each frame in millisecondsloop=0,# loop forever)

The following class lets you use the for-statement to loop over the sequence:
Iterator class¶fromPILimportImageSequenceforframeinImageSequence.Iterator(im):# ...do something to frame...
The Python Imaging Library includes functions to print images, text andgraphics on PostScript printers. Here’s a simple example:
fromPILimportImage,PSDrawimportos# Define the PostScript fileps_file=open("hopper.ps","wb")# Create a PSDraw objectps=PSDraw.PSDraw(ps_file)# Start the documentps.begin_document()# Set the text to be drawntext="Hopper"# Define the PostScript fontfont_name="Helvetica-Narrow-Bold"font_size=36# Calculate text size (approximation as PSDraw doesn't provide direct method)# Assuming average character width as 0.6 of the font sizetext_width=len(text)*font_size*0.6text_height=font_size# Set the position (top-center)page_width,page_height=595,842# A4 size in pointstext_x=(page_width-text_width)//2text_y=page_height-text_height-50# Distance from the top of the page# Load the imageimage_path="hopper.ppm"# Update this with your image pathwithImage.open(image_path)asim:# Resize the image if it's too largeim.thumbnail((page_width-100,page_height//2))# Define the box where the image will be placedimg_x=(page_width-im.width)//2img_y=text_y+text_height-200# 200 points below the text# Draw the image (75 dpi)ps.image((img_x,img_y,img_x+im.width,img_y+im.height),im,75)# Draw the textps.setfont(font_name,font_size)ps.text((text_x,text_y),text)# End the documentps.end_document()ps_file.close()

Note
PostScript converted to PDF for display purposes
As described earlier, theopen() function of theImage module is used to open an image file. In most cases, yousimply pass it the filename as an argument.Image.open() can be used as acontext manager:
fromPILimportImagewithImage.open("hopper.ppm")asim:...
If everything goes well, the result is anPIL.Image.Image object.Otherwise, anOSError exception is raised.
You can use a file-like object instead of the filename. The object mustimplementfile.read,file.seek andfile.tell methods,and be opened in binary mode.
fromPILimportImagewithopen("hopper.ppm","rb")asfp:im=Image.open(fp)
To read an image from binary data, use theBytesIOclass:
fromPILimportImageimportioim=Image.open(io.BytesIO(buffer))
Note that the library rewinds the file (usingseek(0)) before reading theimage header. In addition, seek will also be used when the image data is read(by the load method). If the image file is embedded in a larger file, such as atar file, you can use theContainerIO orTarIO modules to access it.
fromPILimportImagefromurllib.requestimporturlopenurl="https://python-pillow.github.io/assets/images/pillow-logo.png"img=Image.open(urlopen(url))
fromPILimportImage,TarIOfp=TarIO.TarIO("hopper.tar","hopper.jpg")im=Image.open(fp)
Operations can be applied to multiple image files. For example, all PNG imagesin the current directory can be saved as JPEGs at reduced quality.
importglobfromPILimportImagedefcompress_image(source_path:str,dest_path:str)->None:withImage.open(source_path)asimg:ifimg.mode!="RGB":img=img.convert("RGB")img.save(dest_path,"JPEG",optimize=True,quality=80)paths=glob.glob("*.png")forpathinpaths:compress_image(path,path[:-4]+".jpg")
Since images can also be opened from aPath from thepathlib module,the example could be modified to usepathlib instead of theglobmodule.
frompathlibimportPathpaths=Path(".").glob("*.png")forpathinpaths:compress_image(path,path.stem+".jpg")
Some decoders allow you to manipulate the image while reading it from a file.This can often be used to speed up decoding when creating thumbnails (whenspeed is usually more important than quality) and printing to a monochromelaser printer (when only a grayscale version of the image is needed).
Thedraft() method manipulates an opened but not yetloaded image so it as closely as possible matches the given mode and size. Thisis done by reconfiguring the image decoder.
This is only available for JPEG and MPO files.
fromPILimportImagewithImage.open(file)asim:print("original =",im.mode,im.size)im.draft("L",(100,100))print("draft =",im.mode,im.size)
This prints something like:
original=RGB(512,512)draft=L(128,128)
Note that the resulting image may not exactly match the requested mode andsize. To make sure that the image is not larger than the given size, use thethumbnail method instead.