Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I can't seem to understand what Image point does. I want to do some pixel edit which might include checking which color value(r, g or b) is max in every pixel and act accordingly. Lets say that I can't use numpy. I managed to use Image point to add the same value to every pixel in an image. point code

import Image, math
def brightness(i, value):
value = math.floor(255*(float(value)/100))
return i+value
if __name__ == '__main__':
    image = '/home/avlahop/verybig.jpg'
    print image
    img = Image.open(image)
    print img
    out = img.point(lambda i: brightness(i, 50))
    out.show()

numpy code

def brightness(arr, adjust):
    import math
    adjust = math.floor(255*(float(adjust)/100))
    arr[...,0] += adjust
    arr[...,1] += adjust
    arr[...,2] += adjust
    return arr
if __name__ == '__main__':
    image = '/home/avlahop/verybig.jpg'
    img = Image.open(image).convert('RGBA')
    arr = np.array(np.asarray(img).astype('float'))
    new_image = Image.fromarray(brightness(arr, adjust).clip(0,255).astype('uint8'), 'RGBA').show()

I have to say that point code is faster than numpy's. But what if i want to do a more complex operation with point. for example for every pixel check the max(r,g,b) and do something depending on if r=max or g=max or b=max. As you saw i used the point with function as argument. It takes one argument i. what is this i? is it the pixel?(i.e i=(r,g,b)?).I can't seem to understand from the pil documentation

The docs may not have been clear in earlier versions of PIL, but in Pillow it's spelled out pretty well. From Image.point:

lut – A lookup table, containing 256 values per band in the image. A function can be used instead, it should take a single argument. The function is called once for each possible pixel value, and the resulting table is applied to all bands of the image.

In other words, it's not a general-purpose way to map each pixel through a function, it's just a way to dynamically built the lookup table, instead of passing in a pre-built one.

In other words, it's called with the numbers from 0 through 255. (Which you can find out for yourself pretty easily by just writing a function that appends its argument to a global list and then dump out the list at the end…)

If you split your image into separate bands or planes, point each one of them with a different function, and then recombine them, that might be able to accomplish what you're trying to do. But even then, I think eval is what you wanted, not point.

But I think what you really want, which is a pixel-by-pixel all-bands-at-once iterator. And you don't need anything special for that. Just use map or a comprehension over getdata. Isn't that slow? Of course it's slow, because it's calling your function X*Y times; the cost of building the getdata sequence and iterating over it is tiny compared to that cost, so looking for a way for PIL to optimize the already-fast-enough part won't get you very far.

eval is just returning the Image.point() as i can read from source. The gedata is the second method i used combined with map. for an HD image i got 20sec lol for the same job numbpy did 1.3 and points did 0,9s. So I am terrified to try more complex functions. – Apostolos Nov 2, 2013 at 0:23 @Apostolos: Again, the reason point is faster is that it's only calling your function 256 times to build a lookup table, then applying that lookup table to the image; if that's not what you want, it doesn't matter how fast it is. The only possible way to speed up calling a function millions of times is to vectorize that function (e.g., via numpy), parallelize it (e.g., by using a concurrent.futures.ProcessPoolExecutor to do each 1/8th of the image concurrently), or compile it (e.g., write the code in C or Cython, or run it in PyPy instead of CPython). – abarnert Nov 2, 2013 at 0:36

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.