PIL putpixel does nothing
up vote
0
down vote
favorite
At high school, we are beginning with Python and we are asked to program a small image processor using the Pillow module. The goal is to open a file, then choose a filter.
The first filter I tried to program is to change the color temperature.
But there's also a minimalist interface with tkinter that shows some buttons and it works without problems.
Here is the function that opens the file
def Ouvrir():
fichier = askopenfilename(title="Ouvrir une image",filetypes=[('jpg files','.jpg'),('all files','.*')])
global img
img =Image.open(fichier)
l, h = img.size
img.show() #visualisation de l'image
global img2
img2 = img #img2 est une copie de img
It creates a global img image object that is loaded from the file. Then l and h are loaded with the width and height of the image.
Another global object image img2 is created for the output image, and it is a copy of img.
Then here is the function that processes the image
def filtreTC(): #Filtre permettant de changer la température de couleur
coef = sliderTC.get() / 100 #On récupère le coefficient à partir de l'échelle. Le coefficient compris entre -1 et 1: -1 = froid (image bleu-vert), 0 = neutre, 1 = chaud (image orangée)
fenTC.destroy() #On ferme la fenêtre
if(coef <= 0): #Calcul des coefficients rouges, verte et bleus
coefR = 1 + coef
coefV = 1 + (coef / 2)
coefB = 1
else:
coefR = 1
coefV = 1 - (coef / 2)
coefB = 1 - coef
for y in range(0, h, 1):
for x in range(0, l, 1):
r, v, b = img.getpixel((x, y))
r = int(float(r * coefR))
v = int(float(v * coefV))
b = int(float(b * coefB))
img2.putpixel((x, y), (r, v, b))
img2.show()
It's a loop that scans through the whole image and takes a pixel from img, multiply its rgb values by their corresponding coefficients, then puts that pixel in img2
The problem is that it doesn't work. It doesn't give any errors, but when it shows img2 it's the same as img1, like the putpixel function didn't do anything.
I checked a lot of things so I know the problem is neither the rgb values nor the x/y coordinates.
- I tried replacing
img2 = imgbyimg2 = Image.new("RGB", (l, h))and what I get is a black image. - I then tried replacing
img2.putpixel((x, y), (r, v, b))byimg2.putpixel((100, 100), (127, 127, 127))so that way I should get a grey pixel near the top left corner. But I still got a black image.
I then tried to remove
global img2
img2 = img
from the function that opens a file and put
img2 = Image.new("RGB", (l, h))
right after fenTC.destroy() and I got this:
Exception in Tkinter callback
Traceback (most recent call last):
File "e:xxxxprogrammesanacondalibtkinter__init__.py", line 1702, in __call__
return self.func(*args)
File "H:ISNProgrammesTP-imageprojet.py", line 62, in filtreTC
img2.show()
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 2016, in show
_show(self, title=title, command=command)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 2876, in _show
_showxv(image, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 2881, in _showxv
ImageShow.show(image, title, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 51, in show
if viewer.show(image, title=title, **options):
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 75, in show
return self.show_image(image, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 95, in show_image
return self.show_file(self.save_image(image), **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 91, in save_image
return image._dump(format=self.get_format(image), **self.options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 639, in _dump
self.save(filename, format, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 1969, in save
save_handler(self, fp, filename)
File "e:xxxxprogrammesanacondalibsite-packagesPILBmpImagePlugin.py", line 319, in _save
(rawmode, stride, -1))])
File "e:xxxxprogrammesanacondalibsite-packagesPILImageFile.py", line 512, in _save
e.setimage(im.im, b)
SystemError: tile cannot extend outside image
Basically a lot of stuff I've got no idea what it means except:
SystemError: tile cannot extend outside image
I checked the x and y coordinates and they never went beyond the borders, so I don't understand what's this error.
I spent several hours to try figure out what the problem was and tried lots of different things but none of them worked. So I thought it was better to ask for help
python image-processing python-imaging-library
add a comment |
up vote
0
down vote
favorite
At high school, we are beginning with Python and we are asked to program a small image processor using the Pillow module. The goal is to open a file, then choose a filter.
The first filter I tried to program is to change the color temperature.
But there's also a minimalist interface with tkinter that shows some buttons and it works without problems.
Here is the function that opens the file
def Ouvrir():
fichier = askopenfilename(title="Ouvrir une image",filetypes=[('jpg files','.jpg'),('all files','.*')])
global img
img =Image.open(fichier)
l, h = img.size
img.show() #visualisation de l'image
global img2
img2 = img #img2 est une copie de img
It creates a global img image object that is loaded from the file. Then l and h are loaded with the width and height of the image.
Another global object image img2 is created for the output image, and it is a copy of img.
Then here is the function that processes the image
def filtreTC(): #Filtre permettant de changer la température de couleur
coef = sliderTC.get() / 100 #On récupère le coefficient à partir de l'échelle. Le coefficient compris entre -1 et 1: -1 = froid (image bleu-vert), 0 = neutre, 1 = chaud (image orangée)
fenTC.destroy() #On ferme la fenêtre
if(coef <= 0): #Calcul des coefficients rouges, verte et bleus
coefR = 1 + coef
coefV = 1 + (coef / 2)
coefB = 1
else:
coefR = 1
coefV = 1 - (coef / 2)
coefB = 1 - coef
for y in range(0, h, 1):
for x in range(0, l, 1):
r, v, b = img.getpixel((x, y))
r = int(float(r * coefR))
v = int(float(v * coefV))
b = int(float(b * coefB))
img2.putpixel((x, y), (r, v, b))
img2.show()
It's a loop that scans through the whole image and takes a pixel from img, multiply its rgb values by their corresponding coefficients, then puts that pixel in img2
The problem is that it doesn't work. It doesn't give any errors, but when it shows img2 it's the same as img1, like the putpixel function didn't do anything.
I checked a lot of things so I know the problem is neither the rgb values nor the x/y coordinates.
- I tried replacing
img2 = imgbyimg2 = Image.new("RGB", (l, h))and what I get is a black image. - I then tried replacing
img2.putpixel((x, y), (r, v, b))byimg2.putpixel((100, 100), (127, 127, 127))so that way I should get a grey pixel near the top left corner. But I still got a black image.
I then tried to remove
global img2
img2 = img
from the function that opens a file and put
img2 = Image.new("RGB", (l, h))
right after fenTC.destroy() and I got this:
Exception in Tkinter callback
Traceback (most recent call last):
File "e:xxxxprogrammesanacondalibtkinter__init__.py", line 1702, in __call__
return self.func(*args)
File "H:ISNProgrammesTP-imageprojet.py", line 62, in filtreTC
img2.show()
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 2016, in show
_show(self, title=title, command=command)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 2876, in _show
_showxv(image, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 2881, in _showxv
ImageShow.show(image, title, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 51, in show
if viewer.show(image, title=title, **options):
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 75, in show
return self.show_image(image, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 95, in show_image
return self.show_file(self.save_image(image), **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 91, in save_image
return image._dump(format=self.get_format(image), **self.options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 639, in _dump
self.save(filename, format, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 1969, in save
save_handler(self, fp, filename)
File "e:xxxxprogrammesanacondalibsite-packagesPILBmpImagePlugin.py", line 319, in _save
(rawmode, stride, -1))])
File "e:xxxxprogrammesanacondalibsite-packagesPILImageFile.py", line 512, in _save
e.setimage(im.im, b)
SystemError: tile cannot extend outside image
Basically a lot of stuff I've got no idea what it means except:
SystemError: tile cannot extend outside image
I checked the x and y coordinates and they never went beyond the borders, so I don't understand what's this error.
I spent several hours to try figure out what the problem was and tried lots of different things but none of them worked. So I thought it was better to ask for help
python image-processing python-imaging-library
Avoid using global variables in your function. It makes it hard or impossible for us to really know what's going on. Instead include a Minimal, Complete, and Verifiable example. With all the code needed to reproduce your issue. The fact that you get an error saying "tile cannot extend outside image" would indicate that you are making some incorrect assumption about what your image shape is.
– Håken Lid
Nov 11 at 18:07
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
At high school, we are beginning with Python and we are asked to program a small image processor using the Pillow module. The goal is to open a file, then choose a filter.
The first filter I tried to program is to change the color temperature.
But there's also a minimalist interface with tkinter that shows some buttons and it works without problems.
Here is the function that opens the file
def Ouvrir():
fichier = askopenfilename(title="Ouvrir une image",filetypes=[('jpg files','.jpg'),('all files','.*')])
global img
img =Image.open(fichier)
l, h = img.size
img.show() #visualisation de l'image
global img2
img2 = img #img2 est une copie de img
It creates a global img image object that is loaded from the file. Then l and h are loaded with the width and height of the image.
Another global object image img2 is created for the output image, and it is a copy of img.
Then here is the function that processes the image
def filtreTC(): #Filtre permettant de changer la température de couleur
coef = sliderTC.get() / 100 #On récupère le coefficient à partir de l'échelle. Le coefficient compris entre -1 et 1: -1 = froid (image bleu-vert), 0 = neutre, 1 = chaud (image orangée)
fenTC.destroy() #On ferme la fenêtre
if(coef <= 0): #Calcul des coefficients rouges, verte et bleus
coefR = 1 + coef
coefV = 1 + (coef / 2)
coefB = 1
else:
coefR = 1
coefV = 1 - (coef / 2)
coefB = 1 - coef
for y in range(0, h, 1):
for x in range(0, l, 1):
r, v, b = img.getpixel((x, y))
r = int(float(r * coefR))
v = int(float(v * coefV))
b = int(float(b * coefB))
img2.putpixel((x, y), (r, v, b))
img2.show()
It's a loop that scans through the whole image and takes a pixel from img, multiply its rgb values by their corresponding coefficients, then puts that pixel in img2
The problem is that it doesn't work. It doesn't give any errors, but when it shows img2 it's the same as img1, like the putpixel function didn't do anything.
I checked a lot of things so I know the problem is neither the rgb values nor the x/y coordinates.
- I tried replacing
img2 = imgbyimg2 = Image.new("RGB", (l, h))and what I get is a black image. - I then tried replacing
img2.putpixel((x, y), (r, v, b))byimg2.putpixel((100, 100), (127, 127, 127))so that way I should get a grey pixel near the top left corner. But I still got a black image.
I then tried to remove
global img2
img2 = img
from the function that opens a file and put
img2 = Image.new("RGB", (l, h))
right after fenTC.destroy() and I got this:
Exception in Tkinter callback
Traceback (most recent call last):
File "e:xxxxprogrammesanacondalibtkinter__init__.py", line 1702, in __call__
return self.func(*args)
File "H:ISNProgrammesTP-imageprojet.py", line 62, in filtreTC
img2.show()
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 2016, in show
_show(self, title=title, command=command)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 2876, in _show
_showxv(image, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 2881, in _showxv
ImageShow.show(image, title, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 51, in show
if viewer.show(image, title=title, **options):
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 75, in show
return self.show_image(image, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 95, in show_image
return self.show_file(self.save_image(image), **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 91, in save_image
return image._dump(format=self.get_format(image), **self.options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 639, in _dump
self.save(filename, format, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 1969, in save
save_handler(self, fp, filename)
File "e:xxxxprogrammesanacondalibsite-packagesPILBmpImagePlugin.py", line 319, in _save
(rawmode, stride, -1))])
File "e:xxxxprogrammesanacondalibsite-packagesPILImageFile.py", line 512, in _save
e.setimage(im.im, b)
SystemError: tile cannot extend outside image
Basically a lot of stuff I've got no idea what it means except:
SystemError: tile cannot extend outside image
I checked the x and y coordinates and they never went beyond the borders, so I don't understand what's this error.
I spent several hours to try figure out what the problem was and tried lots of different things but none of them worked. So I thought it was better to ask for help
python image-processing python-imaging-library
At high school, we are beginning with Python and we are asked to program a small image processor using the Pillow module. The goal is to open a file, then choose a filter.
The first filter I tried to program is to change the color temperature.
But there's also a minimalist interface with tkinter that shows some buttons and it works without problems.
Here is the function that opens the file
def Ouvrir():
fichier = askopenfilename(title="Ouvrir une image",filetypes=[('jpg files','.jpg'),('all files','.*')])
global img
img =Image.open(fichier)
l, h = img.size
img.show() #visualisation de l'image
global img2
img2 = img #img2 est une copie de img
It creates a global img image object that is loaded from the file. Then l and h are loaded with the width and height of the image.
Another global object image img2 is created for the output image, and it is a copy of img.
Then here is the function that processes the image
def filtreTC(): #Filtre permettant de changer la température de couleur
coef = sliderTC.get() / 100 #On récupère le coefficient à partir de l'échelle. Le coefficient compris entre -1 et 1: -1 = froid (image bleu-vert), 0 = neutre, 1 = chaud (image orangée)
fenTC.destroy() #On ferme la fenêtre
if(coef <= 0): #Calcul des coefficients rouges, verte et bleus
coefR = 1 + coef
coefV = 1 + (coef / 2)
coefB = 1
else:
coefR = 1
coefV = 1 - (coef / 2)
coefB = 1 - coef
for y in range(0, h, 1):
for x in range(0, l, 1):
r, v, b = img.getpixel((x, y))
r = int(float(r * coefR))
v = int(float(v * coefV))
b = int(float(b * coefB))
img2.putpixel((x, y), (r, v, b))
img2.show()
It's a loop that scans through the whole image and takes a pixel from img, multiply its rgb values by their corresponding coefficients, then puts that pixel in img2
The problem is that it doesn't work. It doesn't give any errors, but when it shows img2 it's the same as img1, like the putpixel function didn't do anything.
I checked a lot of things so I know the problem is neither the rgb values nor the x/y coordinates.
- I tried replacing
img2 = imgbyimg2 = Image.new("RGB", (l, h))and what I get is a black image. - I then tried replacing
img2.putpixel((x, y), (r, v, b))byimg2.putpixel((100, 100), (127, 127, 127))so that way I should get a grey pixel near the top left corner. But I still got a black image.
I then tried to remove
global img2
img2 = img
from the function that opens a file and put
img2 = Image.new("RGB", (l, h))
right after fenTC.destroy() and I got this:
Exception in Tkinter callback
Traceback (most recent call last):
File "e:xxxxprogrammesanacondalibtkinter__init__.py", line 1702, in __call__
return self.func(*args)
File "H:ISNProgrammesTP-imageprojet.py", line 62, in filtreTC
img2.show()
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 2016, in show
_show(self, title=title, command=command)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 2876, in _show
_showxv(image, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 2881, in _showxv
ImageShow.show(image, title, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 51, in show
if viewer.show(image, title=title, **options):
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 75, in show
return self.show_image(image, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 95, in show_image
return self.show_file(self.save_image(image), **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImageShow.py", line 91, in save_image
return image._dump(format=self.get_format(image), **self.options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 639, in _dump
self.save(filename, format, **options)
File "e:xxxxprogrammesanacondalibsite-packagesPILImage.py", line 1969, in save
save_handler(self, fp, filename)
File "e:xxxxprogrammesanacondalibsite-packagesPILBmpImagePlugin.py", line 319, in _save
(rawmode, stride, -1))])
File "e:xxxxprogrammesanacondalibsite-packagesPILImageFile.py", line 512, in _save
e.setimage(im.im, b)
SystemError: tile cannot extend outside image
Basically a lot of stuff I've got no idea what it means except:
SystemError: tile cannot extend outside image
I checked the x and y coordinates and they never went beyond the borders, so I don't understand what's this error.
I spent several hours to try figure out what the problem was and tried lots of different things but none of them worked. So I thought it was better to ask for help
python image-processing python-imaging-library
python image-processing python-imaging-library
edited Nov 11 at 17:58
Martijn Pieters♦
695k12924042245
695k12924042245
asked Nov 11 at 17:54
Integrated Electronics
211
211
Avoid using global variables in your function. It makes it hard or impossible for us to really know what's going on. Instead include a Minimal, Complete, and Verifiable example. With all the code needed to reproduce your issue. The fact that you get an error saying "tile cannot extend outside image" would indicate that you are making some incorrect assumption about what your image shape is.
– Håken Lid
Nov 11 at 18:07
add a comment |
Avoid using global variables in your function. It makes it hard or impossible for us to really know what's going on. Instead include a Minimal, Complete, and Verifiable example. With all the code needed to reproduce your issue. The fact that you get an error saying "tile cannot extend outside image" would indicate that you are making some incorrect assumption about what your image shape is.
– Håken Lid
Nov 11 at 18:07
Avoid using global variables in your function. It makes it hard or impossible for us to really know what's going on. Instead include a Minimal, Complete, and Verifiable example. With all the code needed to reproduce your issue. The fact that you get an error saying "tile cannot extend outside image" would indicate that you are making some incorrect assumption about what your image shape is.
– Håken Lid
Nov 11 at 18:07
Avoid using global variables in your function. It makes it hard or impossible for us to really know what's going on. Instead include a Minimal, Complete, and Verifiable example. With all the code needed to reproduce your issue. The fact that you get an error saying "tile cannot extend outside image" would indicate that you are making some incorrect assumption about what your image shape is.
– Håken Lid
Nov 11 at 18:07
add a comment |
1 Answer
1
active
oldest
votes
up vote
2
down vote
Your problem is that you didn't create a copy. img2 = img creates another reference to the same object, not a new, separate image.
To create a actual copy, use the image.copy() method:
img2 = img.copy()
Next, I'd not use a loop and getpixel() / putpixel() combinations. You are doing double work for RGB values that appear more than once. If you use the image.point() method then you get to use your formula on each unique value in each band in the image, and leave the looping over all pixels to the library (much faster). It also makes the image copy for you!
You need to create a table; for values 0 through 255 for the R, G and B values, calculate the possible result, and put those 3 * 256 results in a long list:
coefG = [i * (1 - (coef / 2)) for i in range(256)]
if coef <= 0:
coefR = [i * (1 + coef) for i in range(256)]
coefB = list(range(256))
else:
coefR = list(range(256))
coefB = [i * (1 - coef) for i in range(256)]
img2 = img1.point(coefR + coefG + coefB)
The resulting table is used for each unique color value in the image.
You could also split the RGB image into separate bands, apply your different coefficient formulas to each separate band as a function then re-combine the bands into a new image:
r, g, b = img.split()
g = g.point(lambda i: i * (1 - (coef / 2)))
if coef <= 0:
r = r.point(lambda i: i * (1 + coef))
else:
b = b.point(lambda i: i * (1 - coef))
img = Image.merge('RGB', (r, g, b))
When creating an image filter, you'd really want to pass in the input image as a function argument rather than use globals. Pass in the coefficient as well:
def filtreTC(source_image, coef):
coefG = [i * (1 - (coef / 2)) for i in range(256)]
if coef <= 0:
coefR = [i * (1 + coef) for i in range(256)]
coefB = list(range(256))
else:
coefR = list(range(256))
coefB = [i * (1 - coef) for i in range(256)]
return source_image.point(coefR + coefG + coefB)
You can then store the result of the call in a global if you must, but the function can now stand on its own, and can be re-used anywhere that has a RGB PIL image object. You'd call the function with the slider value:
coef = sliderTC.get() / 100
fenTC.destroy()
img2 = filtreTC(img, coef)
Using the above on your profile image

with a coefficient of 0.75, gives us:

while -0.75 results in:

Thank you. I understand that using getpixel/putpixel is obviously not a proper method. The teacher told us that the PIL library does indeed have methods for image processing. But he told us to use getpixel/putpixel so that we understand how image processing works. If I use yourfiltreTCfunction it works perfectly. I then modified myfiltreTCfunction so that it takes a source image and an argument, time again no error but I get a black image, like if the putpixel function didn't do anything. But surprisingly Image.point works and I don't understand why.
– Integrated Electronics
Nov 12 at 20:59
1
@IntegratedElectronics: your loop code worked fine for me when I tried it withimg2 = img.copy(), for what it is worth. Put the copy at the top of the function, run your loop over theimg.sizedimensions, and return the altered copy.
– Martijn Pieters♦
Nov 12 at 21:37
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
Your problem is that you didn't create a copy. img2 = img creates another reference to the same object, not a new, separate image.
To create a actual copy, use the image.copy() method:
img2 = img.copy()
Next, I'd not use a loop and getpixel() / putpixel() combinations. You are doing double work for RGB values that appear more than once. If you use the image.point() method then you get to use your formula on each unique value in each band in the image, and leave the looping over all pixels to the library (much faster). It also makes the image copy for you!
You need to create a table; for values 0 through 255 for the R, G and B values, calculate the possible result, and put those 3 * 256 results in a long list:
coefG = [i * (1 - (coef / 2)) for i in range(256)]
if coef <= 0:
coefR = [i * (1 + coef) for i in range(256)]
coefB = list(range(256))
else:
coefR = list(range(256))
coefB = [i * (1 - coef) for i in range(256)]
img2 = img1.point(coefR + coefG + coefB)
The resulting table is used for each unique color value in the image.
You could also split the RGB image into separate bands, apply your different coefficient formulas to each separate band as a function then re-combine the bands into a new image:
r, g, b = img.split()
g = g.point(lambda i: i * (1 - (coef / 2)))
if coef <= 0:
r = r.point(lambda i: i * (1 + coef))
else:
b = b.point(lambda i: i * (1 - coef))
img = Image.merge('RGB', (r, g, b))
When creating an image filter, you'd really want to pass in the input image as a function argument rather than use globals. Pass in the coefficient as well:
def filtreTC(source_image, coef):
coefG = [i * (1 - (coef / 2)) for i in range(256)]
if coef <= 0:
coefR = [i * (1 + coef) for i in range(256)]
coefB = list(range(256))
else:
coefR = list(range(256))
coefB = [i * (1 - coef) for i in range(256)]
return source_image.point(coefR + coefG + coefB)
You can then store the result of the call in a global if you must, but the function can now stand on its own, and can be re-used anywhere that has a RGB PIL image object. You'd call the function with the slider value:
coef = sliderTC.get() / 100
fenTC.destroy()
img2 = filtreTC(img, coef)
Using the above on your profile image

with a coefficient of 0.75, gives us:

while -0.75 results in:

Thank you. I understand that using getpixel/putpixel is obviously not a proper method. The teacher told us that the PIL library does indeed have methods for image processing. But he told us to use getpixel/putpixel so that we understand how image processing works. If I use yourfiltreTCfunction it works perfectly. I then modified myfiltreTCfunction so that it takes a source image and an argument, time again no error but I get a black image, like if the putpixel function didn't do anything. But surprisingly Image.point works and I don't understand why.
– Integrated Electronics
Nov 12 at 20:59
1
@IntegratedElectronics: your loop code worked fine for me when I tried it withimg2 = img.copy(), for what it is worth. Put the copy at the top of the function, run your loop over theimg.sizedimensions, and return the altered copy.
– Martijn Pieters♦
Nov 12 at 21:37
add a comment |
up vote
2
down vote
Your problem is that you didn't create a copy. img2 = img creates another reference to the same object, not a new, separate image.
To create a actual copy, use the image.copy() method:
img2 = img.copy()
Next, I'd not use a loop and getpixel() / putpixel() combinations. You are doing double work for RGB values that appear more than once. If you use the image.point() method then you get to use your formula on each unique value in each band in the image, and leave the looping over all pixels to the library (much faster). It also makes the image copy for you!
You need to create a table; for values 0 through 255 for the R, G and B values, calculate the possible result, and put those 3 * 256 results in a long list:
coefG = [i * (1 - (coef / 2)) for i in range(256)]
if coef <= 0:
coefR = [i * (1 + coef) for i in range(256)]
coefB = list(range(256))
else:
coefR = list(range(256))
coefB = [i * (1 - coef) for i in range(256)]
img2 = img1.point(coefR + coefG + coefB)
The resulting table is used for each unique color value in the image.
You could also split the RGB image into separate bands, apply your different coefficient formulas to each separate band as a function then re-combine the bands into a new image:
r, g, b = img.split()
g = g.point(lambda i: i * (1 - (coef / 2)))
if coef <= 0:
r = r.point(lambda i: i * (1 + coef))
else:
b = b.point(lambda i: i * (1 - coef))
img = Image.merge('RGB', (r, g, b))
When creating an image filter, you'd really want to pass in the input image as a function argument rather than use globals. Pass in the coefficient as well:
def filtreTC(source_image, coef):
coefG = [i * (1 - (coef / 2)) for i in range(256)]
if coef <= 0:
coefR = [i * (1 + coef) for i in range(256)]
coefB = list(range(256))
else:
coefR = list(range(256))
coefB = [i * (1 - coef) for i in range(256)]
return source_image.point(coefR + coefG + coefB)
You can then store the result of the call in a global if you must, but the function can now stand on its own, and can be re-used anywhere that has a RGB PIL image object. You'd call the function with the slider value:
coef = sliderTC.get() / 100
fenTC.destroy()
img2 = filtreTC(img, coef)
Using the above on your profile image

with a coefficient of 0.75, gives us:

while -0.75 results in:

Thank you. I understand that using getpixel/putpixel is obviously not a proper method. The teacher told us that the PIL library does indeed have methods for image processing. But he told us to use getpixel/putpixel so that we understand how image processing works. If I use yourfiltreTCfunction it works perfectly. I then modified myfiltreTCfunction so that it takes a source image and an argument, time again no error but I get a black image, like if the putpixel function didn't do anything. But surprisingly Image.point works and I don't understand why.
– Integrated Electronics
Nov 12 at 20:59
1
@IntegratedElectronics: your loop code worked fine for me when I tried it withimg2 = img.copy(), for what it is worth. Put the copy at the top of the function, run your loop over theimg.sizedimensions, and return the altered copy.
– Martijn Pieters♦
Nov 12 at 21:37
add a comment |
up vote
2
down vote
up vote
2
down vote
Your problem is that you didn't create a copy. img2 = img creates another reference to the same object, not a new, separate image.
To create a actual copy, use the image.copy() method:
img2 = img.copy()
Next, I'd not use a loop and getpixel() / putpixel() combinations. You are doing double work for RGB values that appear more than once. If you use the image.point() method then you get to use your formula on each unique value in each band in the image, and leave the looping over all pixels to the library (much faster). It also makes the image copy for you!
You need to create a table; for values 0 through 255 for the R, G and B values, calculate the possible result, and put those 3 * 256 results in a long list:
coefG = [i * (1 - (coef / 2)) for i in range(256)]
if coef <= 0:
coefR = [i * (1 + coef) for i in range(256)]
coefB = list(range(256))
else:
coefR = list(range(256))
coefB = [i * (1 - coef) for i in range(256)]
img2 = img1.point(coefR + coefG + coefB)
The resulting table is used for each unique color value in the image.
You could also split the RGB image into separate bands, apply your different coefficient formulas to each separate band as a function then re-combine the bands into a new image:
r, g, b = img.split()
g = g.point(lambda i: i * (1 - (coef / 2)))
if coef <= 0:
r = r.point(lambda i: i * (1 + coef))
else:
b = b.point(lambda i: i * (1 - coef))
img = Image.merge('RGB', (r, g, b))
When creating an image filter, you'd really want to pass in the input image as a function argument rather than use globals. Pass in the coefficient as well:
def filtreTC(source_image, coef):
coefG = [i * (1 - (coef / 2)) for i in range(256)]
if coef <= 0:
coefR = [i * (1 + coef) for i in range(256)]
coefB = list(range(256))
else:
coefR = list(range(256))
coefB = [i * (1 - coef) for i in range(256)]
return source_image.point(coefR + coefG + coefB)
You can then store the result of the call in a global if you must, but the function can now stand on its own, and can be re-used anywhere that has a RGB PIL image object. You'd call the function with the slider value:
coef = sliderTC.get() / 100
fenTC.destroy()
img2 = filtreTC(img, coef)
Using the above on your profile image

with a coefficient of 0.75, gives us:

while -0.75 results in:

Your problem is that you didn't create a copy. img2 = img creates another reference to the same object, not a new, separate image.
To create a actual copy, use the image.copy() method:
img2 = img.copy()
Next, I'd not use a loop and getpixel() / putpixel() combinations. You are doing double work for RGB values that appear more than once. If you use the image.point() method then you get to use your formula on each unique value in each band in the image, and leave the looping over all pixels to the library (much faster). It also makes the image copy for you!
You need to create a table; for values 0 through 255 for the R, G and B values, calculate the possible result, and put those 3 * 256 results in a long list:
coefG = [i * (1 - (coef / 2)) for i in range(256)]
if coef <= 0:
coefR = [i * (1 + coef) for i in range(256)]
coefB = list(range(256))
else:
coefR = list(range(256))
coefB = [i * (1 - coef) for i in range(256)]
img2 = img1.point(coefR + coefG + coefB)
The resulting table is used for each unique color value in the image.
You could also split the RGB image into separate bands, apply your different coefficient formulas to each separate band as a function then re-combine the bands into a new image:
r, g, b = img.split()
g = g.point(lambda i: i * (1 - (coef / 2)))
if coef <= 0:
r = r.point(lambda i: i * (1 + coef))
else:
b = b.point(lambda i: i * (1 - coef))
img = Image.merge('RGB', (r, g, b))
When creating an image filter, you'd really want to pass in the input image as a function argument rather than use globals. Pass in the coefficient as well:
def filtreTC(source_image, coef):
coefG = [i * (1 - (coef / 2)) for i in range(256)]
if coef <= 0:
coefR = [i * (1 + coef) for i in range(256)]
coefB = list(range(256))
else:
coefR = list(range(256))
coefB = [i * (1 - coef) for i in range(256)]
return source_image.point(coefR + coefG + coefB)
You can then store the result of the call in a global if you must, but the function can now stand on its own, and can be re-used anywhere that has a RGB PIL image object. You'd call the function with the slider value:
coef = sliderTC.get() / 100
fenTC.destroy()
img2 = filtreTC(img, coef)
Using the above on your profile image

with a coefficient of 0.75, gives us:

while -0.75 results in:

edited Nov 11 at 23:04
answered Nov 11 at 18:07
Martijn Pieters♦
695k12924042245
695k12924042245
Thank you. I understand that using getpixel/putpixel is obviously not a proper method. The teacher told us that the PIL library does indeed have methods for image processing. But he told us to use getpixel/putpixel so that we understand how image processing works. If I use yourfiltreTCfunction it works perfectly. I then modified myfiltreTCfunction so that it takes a source image and an argument, time again no error but I get a black image, like if the putpixel function didn't do anything. But surprisingly Image.point works and I don't understand why.
– Integrated Electronics
Nov 12 at 20:59
1
@IntegratedElectronics: your loop code worked fine for me when I tried it withimg2 = img.copy(), for what it is worth. Put the copy at the top of the function, run your loop over theimg.sizedimensions, and return the altered copy.
– Martijn Pieters♦
Nov 12 at 21:37
add a comment |
Thank you. I understand that using getpixel/putpixel is obviously not a proper method. The teacher told us that the PIL library does indeed have methods for image processing. But he told us to use getpixel/putpixel so that we understand how image processing works. If I use yourfiltreTCfunction it works perfectly. I then modified myfiltreTCfunction so that it takes a source image and an argument, time again no error but I get a black image, like if the putpixel function didn't do anything. But surprisingly Image.point works and I don't understand why.
– Integrated Electronics
Nov 12 at 20:59
1
@IntegratedElectronics: your loop code worked fine for me when I tried it withimg2 = img.copy(), for what it is worth. Put the copy at the top of the function, run your loop over theimg.sizedimensions, and return the altered copy.
– Martijn Pieters♦
Nov 12 at 21:37
Thank you. I understand that using getpixel/putpixel is obviously not a proper method. The teacher told us that the PIL library does indeed have methods for image processing. But he told us to use getpixel/putpixel so that we understand how image processing works. If I use your
filtreTC function it works perfectly. I then modified my filtreTC function so that it takes a source image and an argument, time again no error but I get a black image, like if the putpixel function didn't do anything. But surprisingly Image.point works and I don't understand why.– Integrated Electronics
Nov 12 at 20:59
Thank you. I understand that using getpixel/putpixel is obviously not a proper method. The teacher told us that the PIL library does indeed have methods for image processing. But he told us to use getpixel/putpixel so that we understand how image processing works. If I use your
filtreTC function it works perfectly. I then modified my filtreTC function so that it takes a source image and an argument, time again no error but I get a black image, like if the putpixel function didn't do anything. But surprisingly Image.point works and I don't understand why.– Integrated Electronics
Nov 12 at 20:59
1
1
@IntegratedElectronics: your loop code worked fine for me when I tried it with
img2 = img.copy(), for what it is worth. Put the copy at the top of the function, run your loop over the img.size dimensions, and return the altered copy.– Martijn Pieters♦
Nov 12 at 21:37
@IntegratedElectronics: your loop code worked fine for me when I tried it with
img2 = img.copy(), for what it is worth. Put the copy at the top of the function, run your loop over the img.size dimensions, and return the altered copy.– Martijn Pieters♦
Nov 12 at 21:37
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53251541%2fpil-putpixel-does-nothing%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Avoid using global variables in your function. It makes it hard or impossible for us to really know what's going on. Instead include a Minimal, Complete, and Verifiable example. With all the code needed to reproduce your issue. The fact that you get an error saying "tile cannot extend outside image" would indicate that you are making some incorrect assumption about what your image shape is.
– Håken Lid
Nov 11 at 18:07