Question

I'm working on class work and am having trouble with the data structure that is generated by using the load() function on an image in Python. What I am doing here is trying to convert an entire image to HSL from RGB. The problem is, when I try to write the new values back to the data structure, they don't get written. I have successfully written to this type of structure in other places in my code, however. If that were not the case, I would have just assumed that the structure is immutable, but it seems like it is not. If anyone can explain to me what is going on, and how this particular data structure works, I would be very grateful. I suspect that I somehow need to create a new structure to write to in the function, but I don't know how to, aside from creating a new image and getting the structure from that.

def toHSL(px):     #reorders values to h, s, l from h, l, s
    for x in xrange(0, dim[0]):
        for y in xrange(0, dim[1]):
            r, g, b = px[x,y][0], px[x,y][1], px[x,y][2]   #I don't really understand how to create this type of data structure, even
            r, g, b = [x/255.0 for x in r, g, b]           #Python uses values from 0 to 1
            h, l, s = colorsys.rgb_to_hls(r, g, b)
            px[x,y] = (int(h*255), int(s*255), int(l*255)) #trying to save back to the original data structure
    return px

img_name = "Mandrill"

try:
    im = Image.open(img_name + ".bmp")
except:
    print "Unable to load image."
    sys.exit()
dim = im.size
pix = im.load()
new = Image.new("RGB", dim)
newpx = new.load()

hsl = toHSL(pix)
print hsl[0,0][0], hsl[0,0][1], hsl[0,0][2]    #<< gives the original values
Was it helpful?

Solution

I stand corrected, apparently it is possible to read and write pixels using that (undocumented) indexing technique, at least with some image formats. Learn something new everyday... ;-)

Anyway what's wrong with your program is the line:

    r, g, b = [x/255.0 for x in r, g, b]

which changes the value ofxwhich is already being used to iterate over the pixel coordinates. Simply changing it to another variable name as shown below will make your code do what you want:

    r, g, b = [c/255.0 for c in r, g, b]

(Note, better yet, change it to the following and remove the line preceding it)

    r, g, b = [c/255.0 for c in px[x,y]]

After doing that, here's the image that will result — displayed as RGB, not HSL, to show that the structure is indeed mutable:

output from correctly working code show image was changed

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top