# Basic Image Manipulation

[CG]Maxime
105.6K views

## Luminosity

Changing the luminosity of a picture in a RGB mode can be done by adding a constant to each color component. However, this is a very simplified algorithm: the perceived luminosity has not an easy definition and there are several ways to estimate the luminosity of a pixel. Note that it is also possible to change from RGB to HSL to modify the luminosity easily.

from PIL import Image, ImageDraw
# Change this:
luminosity = 80
input_image = Image.open("input.png")
# Create output image
output_image = Image.new("RGB", input_image.size)
draw = ImageDraw.Draw(output_image)
# Generate image
for x in range(output_image.width):
for y in range(output_image.height):
r, g, b = input_pixels[x, y]
r = int(r + luminosity)
g = int(g + luminosity)
b = int(b + luminosity)
draw.point((x, y), (r, g, b))
output_image.save("output.png")
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

## Contrast

The contrast is the difference in brightness (or color) that makes the objects in a picture distinguishable. The intensity histogram of an image is the distribution of pixel luminance for an image. In order to improve the contrast, we can use a linear normalization of the intensity histogram:

${I}_{N}=\left(I-\text{Imin}\right)\frac{255}{\text{Imax}-\text{Imin}}$, where ${I}_{N}$ is the normalized pixel intensity, $\text{Imin}$ and $\text{Imax}$ are the minimum and maximum intensity (before normalization).

from PIL import Image, ImageDraw
input_image = Image.open("input.png")
# Create output image
output_image = Image.new("RGB", input_image.size)
draw = ImageDraw.Draw(output_image)
# Find minimum and maximum luminosity
imin = 255
imax = 0
for x in range(input_image.width):
for y in range(input_image.height):
r, g, b = input_pixels[x, y]
i = (r + g + b) / 3
imin = min(imin, i)
imax = max(imax, i)
# Generate image
for x in range(output_image.width):
for y in range(output_image.height):
r, g, b = input_pixels[x, y]
# Current luminosity
i = (r + g + b) / 3
# New luminosity
ip = 255 * (i - imin) / (imax - imin)
r = int(r * ip / i)
g = int(g * ip / i)
b = int(b * ip / i)
draw.point((x, y), (r, g, b))
output_image.save("output.png")
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

## Colorize

In the previous example, we saw how to adjust the color of the pixels. This can be used to change the color balance for instance. In the next example, we detect the pixels whose color is close to blue (0, 0, 255) by computing a distance, and we reduce the value of the red and blue components and increase the green component.

from PIL import Image, ImageDraw
# Square distance between 2 colors
def distance2(color1, color2):
r1, g1, b1 = color1
r2, g2, b2 = color2
return (r1 - r2) ** 2 + (g1 - g2) ** 2 + (b1 - b2) ** 2
color_to_change = (0, 0, 255)
threshold = 220
input_image = Image.open("input.png")
# Create output image
output_image = Image.new("RGB", input_image.size)
draw = ImageDraw.Draw(output_image)
# Generate image
for x in range(output_image.width):
for y in range(output_image.height):
r, g, b = input_pixels[x, y]
if distance2(color_to_change, input_pixels[x, y]) < threshold ** 2:
r = int(r * .5)
g = int(g * 1.25)
b = int(b * .5)
draw.point((x, y), (r, g, b))
output_image.save("output.png")
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX   