4

I need to make a copy of an image to manipulate it, however saving the original image and opening up the copied one seems to differ in their pixel values:

from PIL import Image

# Open original image
img = Image.open("mountain.jpg")
data = img.load()

# Display individual pixels
print("Pixel 1: {}".format(data[0,0]))
print("Pixel 2: {}".format(data[0,1]))
print("Pixel 3: {}".format(data[0,2]))

# Makes a copy of the input image and loads the copied image's pixel map
copyImage = img.copy()

copyImage.save('copy.jpg')
copyImage.close()

# Opens the copied image that was saved earlier and its pixel map
copy = Image.open("copy.jpg")
copy_data = copy.load()

print()

# Display copied images' individual pixels
print("Pixel 1 (copy): {}".format(copy_data[0,0]))
print("Pixel 2 (copy): {}".format(copy_data[0,1]))
print("Pixel 3 (copy): {}".format(copy_data[0,2]))

copy.close()

This outputs as:

Pixel 1: (72, 102, 112)
Pixel 2: (75, 105, 115)
Pixel 3: (71, 101, 111)

Pixel 1 (copy): (70, 100, 110)
Pixel 2 (copy): (77, 107, 117)
Pixel 3 (copy): (74, 104, 114)

Initially, I thought PIL might be changing all pixel values by 2 values for each of the R, G, and B channels (as can be seen with the first two pixels), however the third pixel has a change of 3 values to each channel.

How can I make a reliable copy of the image, in order to change its pixels, where the starting pixels of the copied image are the same as its original?

NOTE: I have tried other images other than my 'mountain.jpg', but all seem to be causing the same issues.

martineau
  • 119,623
  • 25
  • 170
  • 301
Suraj Kothari
  • 1,642
  • 13
  • 22

2 Answers2

5

*.jpg is a compressed image format. By saving the jpg again you use a different default quality for the jpg writer so the resulting pixel-values differ.

See image file format params for jpg for the quality parameter that you can pass to image.save()

quality
The image quality, on a scale from 1 (worst) to 95 (best). The default is 75. Values above 95 should be avoided; 100 disables portions of the JPEG compression algorithm, and results in large files with hardly any gain in image quality.

Either

Related:

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • The second point, how would that work in theory to avoid compression? – Suraj Kothari Feb 09 '19 at 21:16
  • @Sur You do not avoid compression - if you copy the file using f.e. `shutil.copyfile` you get an exact binary copy of your source - it will have the same characteristics as the original file unless you modify pixels and save them again - then it gets recompressed. You can switch to https://en.wikipedia.org/wiki/Image_file_formats#JPEG_2000 wich is a lossless format and will at least not degrade over time if loaded/modified/saved multiple times – Patrick Artner Feb 09 '19 at 21:19
2

The problem is saving image as JPG. Try to do it with PNG. By saving your image as JPG, you are doing JPG compression. That alters the pixels. Do this

copyImage.save('copy.png')
copyImage.close()

and

copy = Image.open("copy.png")
copy_data = copy.load()

NOTE:

You may want to see difference between JPG and PNG.

JPG is compression with cost of losing data

PNG is compression without loss of data

JPG will result in having very low size image but everytime you save the image, you are basicly compressing it again and again. The quality in general is low

PNG will result in quite big size, but saving and loading image will not result in any pixel change.

Martin
  • 3,333
  • 2
  • 18
  • 39
  • The original image was a JPG. But wouldn't saving as a PNG alter the image? – Suraj Kothari Feb 09 '19 at 21:07
  • @SurajKothari It doesnt matter what was original image's format. Once you load it in your python, then to get exactly the copy, you need to save as PNG and load as PNG – Martin Feb 09 '19 at 21:08
  • @SurajKothari On the contrary. If you load JPG image and save the Image as JPG, you will alter the image. Loading JPG image and saving it as PNG will result in two identical images (however size of both of them is different) – Martin Feb 09 '19 at 21:27
  • Thanks for the info. I didn't really realise the file format mattered until I remebered what they really do. – Suraj Kothari Feb 09 '19 at 21:36