Let's take a look at some other functions we might want to use in Pillow to modify
images.
First, let's import all of the library functions we need.
So we'll import PIL like we've been using.
From PIL we'll import Image, and from IPython.display, we'll import Display.
And let's load the image we're working with,
and we can just convert it to rgbn.live.
So that image was in read only slash msirecruitment.gif, and
here we'll just image.open the file, and then that returns an image object which
we call converton, send it the rgb string, and now we've got our image.
And let's just display that image, inline, here.
All right, so that's the image we've been working with.
A task that's fairly common in image and
picture manipulation is to create contact sheets of images.
A contact sheet is one image that actually contains several other different images.
So let's try and make a contact sheet for
the Master of Science in Information advertisement image.
In particular, let's change the brightness of the image in ten different ways.
Then scale the images down to smaller sizes and put them side by side so
that we can get a sense of which brightness we might want to use.
So, first off, let's import the image enhance module,
which has a nice object called brightness.
So from PIL import image enhance.
Checking the online documentation for this function,
it takes a value between 0.0, which is a completely black image, and
1.0 which is the original image, to adjust the brightness.
All of the classes in the image enhance module do this in the same way.
You create an object, in this case brightness,
then you call the enhance function on that object with the appropriate parameter.
Let's write a little loop to generate 10 images of different brightnesses.
First, we need the brightness object with our image.
So we'll create a variable called enhancer, and
we'll set this to ImageEnhance.Brightness, and pass in the image.
Now let's create a new list for our images, and then for each image,
so from 0 to 10, let's do some processing of this.
So divide I here by 10 to get the decimal values we want,
and append it to the images list.
We actually call the brightness routine by calling the enhance function as i said.
So remember that you can dig into the details of this using a Help function if
you want to, or by consulting the web docs.
So, we'll do images.append and we'll do enhance or .enhance, and
we'll just take our counter parameter here I and divide it by 10.
Well, first, we'll get 0 and then 0.1, 0.2 and so forth.
We can see that the result here is going to be a list of 10 PIL image.image
objects.
Jupiter nicely prints out the value of Python objects nested in lists.
So let's just print out the images here.
And there we go.
We can see that we have these PIL.image.imageobjects and PIL actually,
what we call print on them the function has been written.
So we get to see a little bit more information about each of these objects.
We see that the mode is RGB, of course we knew that, so we converted that.
But we also see the size and then they give us a memory location which for
our cases is not particularly interesting, but you could see that that changes for
each of the images.
So we know they're pointing to different images.
Let's take this images now and composite them,
one above another into a contact sheet.
There's several different approaches we can use by all simply using new image
which is like the first image but ten times as high.
Let's check out the pil.image.newfunctionality.
So we can do this using Help, which is a help pil.image.new, and run that cell.
The new function requires that we passed to it a mode.
We are going to use the mode RGB, which stands for Red, Green, Blue,
and it's the mode of our current first image.
There's lots of different image mode formats,
and this one is actually one of the most common.
For the size, we have a tuple, which is the width of the image and the height.
We'll use the width of our current first image, but for
the height we'll multiply this by ten.
This will make a sort of canvas for our contact sheet.
Finally the color is optional and we'll just leave it to black.
So we'll create a new variable here called first image and
we'll use that a lot, and it's just the first image from the list but
we're going to use it as a reference for sizes.
From PIL we want to import image, and then let's create the contact sheet.
And so this is we call pil.image.news, so
we're invoking the image new constructor, or what will be a constructor,
to give us the first image mode so that's RB, that's the first parameter.
And then we give it the width and then ten times the height.
So now, we have a block image that's ten times the size of the other images in
the contact sheet variable.
Now let's just look through the image list and paste the results in.
The Paste function will be called on the contact sheet Object, and
it takes in a new image to paste as well as an x y offset for that image.
In our case the x position is always 0 but the y location will change
by 450 pixels each time that we iterate through the loop.
So let's first create a counter variable for the y location and we'll start at 0.
So we call that counter current location.
And then for each image in our images list,
let's paste the current image into the contact sheet.
So we call contact_sheet.paste, we give it the image and
we give it a 0, which is the x location so to the far left, and
then the current location which is our y location.
And then let's update our current location counters.
So we update this by increasing it by 450 pixels, which is the height of our image.
This contact sheet has gotten big, 4,500 pixels tall.
Let's just resize this sheet for display.
We could do this using the Resize function.
This function takes in a tuple of width and height and
will resize everything down to the size of just two individual images.
So we just call contactsheet.resize and
give it the tuple size that we want it to scale to.
Now let's just display that composite image called display with contact sheet.
You can see here that we have all of these images,
they're stacked upon one another and they're different brightnesses.
They really go from quite dark, maybe even black, to almost our full normal image.
Okay, so that's a nice proof of concept but it's a little tough to see.
Let's instead change this to a 3 by 3 grid values, and
this is something you'll use in your assignment.
So first thing we should do is make our canvas, we'll make it three times
the width of our image and three times the height of the image, a nine-image square.
So we'll call pil.image.new.
Again, we want to pass in the mode of the image we're using, and then the width and
the height each multiplied by nine, and we'll save this as our new contact sheet.
Now we want to iterate over our images and place them into this grid.
Remember that in PIL we manage the location of where we've referred to
an image in the upper right hand corner.
So, this would be 0.0.
Let's use one variable for the x dimension and one for the y dimension.
So x equals 0 and y equals 0.
Now, let's just iterate over our images.
Except we don't want to bother with the first one because it's just solid black.
Instead we just want to deal with the images after the first one, and
that should give us a nine total.
So for image in images, and
we just use slicing here to pull out from the first damage, that is the one
in the one position as opposed to the zero position to the end of the list.
And that gives us a sub list that we're going to iterate over.
Let's paste the current image into the contact sheet.
And so we do this with contact_sheet.paste and we pass in the image,
and the x y position.
Now, we need to update our x position.
If it's going to be the width of the image, then we set it to zero and
we update y as well to the point to the next line of the contact sheet.
So, if x plus first image.width is equal to the contact sheet.width, we'll
set x to 0 and we'll update y, and we'll make Y equal to the first image.height.
So if this isn't true then we'll just update x, and
so x will be equal to x plus the first image.width, and this will move us over
a little bit horizontally but won't change our vertical alignment.
Now let's resize the contact sheet.
We'll make it just half the size by dividing it by two, and
because the Resize function needs to take round numbers, we'll need to convert our
divisions from floating point numbers into integers using the N function.
And so we'll take our contact sheet, we'll resize it,
we want to really pass two parameters.
But we need to wrap those in into calls to make them integers, whole numbers,
because we're doing a division.
And so when you take two integers and divide one by the other integer, you
always get a floating point return, and we want to typecast this into integers.
Now let's display that as a composite image, and so
just like before we display the contact sheet in Jupyter.
We see here we have our 3 by 3 grid.
In the upper left we start with very dark and it gets lighter as we go across,
and then it wraps around.
And it gets lighter and lighter until we get to the lightest image in our
brightness levels at the lower right.
And you could see actually how a photographer who might be looking to
change the brightness of an image.
Let's say they're going to put it in the background of a video or
they want to put it as a background of a page and put text over it.
We might want to see in a bunch of different variations,
a bunch of different brightnesses.
Now, we've written a function which could do that.
So if something like Photoshop was written in Python, you could wire up a button now
with this logic that just shows a bunch of alternative versions of the image.
Well, that's been a tour of our first external API,
the Python Imaging Library, or the Pillow module.
In this series of lectures, you've learn how to read and write images,
manipulate them with Pillow, and explore the functionality of third-party APIs
using features of Python like DER, Help, and getmro.
You've also been introduced to the console and
how Python stores the libraries on the computer.
Well, for this course, all of the libraries are intended for
you to use in the Coursera website in the Jupyter system, and
you won't need to install your own.
It's good to get the idea of how this work is done in case you wanted to
set things up on your own PC.
Finally, while you can explore Pillow from within Python,
most good modules also put their documentation up online.
And you can read more about Pillow here at Read the Docs.
And this will be very useful for your assignment which comes up soon.