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 = img by img2 = Image.new("RGB", (l, h))and what I get is a black image.

  • I then tried replacing img2.putpixel((x, y), (r, v, b)) by img2.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










share|improve this question
























  • 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















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 = img by img2 = Image.new("RGB", (l, h))and what I get is a black image.

  • I then tried replacing img2.putpixel((x, y), (r, v, b)) by img2.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










share|improve this question
























  • 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













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 = img by img2 = Image.new("RGB", (l, h))and what I get is a black image.

  • I then tried replacing img2.putpixel((x, y), (r, v, b)) by img2.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










share|improve this question















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 = img by img2 = Image.new("RGB", (l, h))and what I get is a black image.

  • I then tried replacing img2.putpixel((x, y), (r, v, b)) by img2.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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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


















  • 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












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



question-asker profile image, a chip



with a coefficient of 0.75, gives us:



same profile image, but turned orange



while -0.75 results in:



same profile image, but now blue






share|improve this answer























  • 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




    @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













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















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

























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



question-asker profile image, a chip



with a coefficient of 0.75, gives us:



same profile image, but turned orange



while -0.75 results in:



same profile image, but now blue






share|improve this answer























  • 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




    @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

















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



question-asker profile image, a chip



with a coefficient of 0.75, gives us:



same profile image, but turned orange



while -0.75 results in:



same profile image, but now blue






share|improve this answer























  • 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




    @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















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



question-asker profile image, a chip



with a coefficient of 0.75, gives us:



same profile image, but turned orange



while -0.75 results in:



same profile image, but now blue






share|improve this answer














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



question-asker profile image, a chip



with a coefficient of 0.75, gives us:



same profile image, but turned orange



while -0.75 results in:



same profile image, but now blue







share|improve this answer














share|improve this answer



share|improve this answer








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 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




    @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




















  • 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




    @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


















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




















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

List item for chat from Array inside array React Native

Thiostrepton

Caerphilly