Why is accessing image data so slow?
.pixels is a python object and pretty slow, especially if you change pixels. That is 'cause the entire buffer / python object is re-created for every single change (if you do it in a python loop). Not sure why it's that slow on read-only actions though...

You can speed it up tremendously if you cast it to a native python type (tuple) and use that copy instead:

img = bpy.data.images['Untitled']

pixels = img.pixels[:] # create a copy (tuple) for read-only access
# -- OR --
pixels = list(img.pixels) # create an editable copy (list)

# Use the tuple object, which is way faster than direct access to Image.pixels
for i in range(0, len(pixels), 4):
    pixels[i] = 1.0 - pixels[i] # invert red channel

# Write back to image.
# Slice notation here means to replace in-place, not sure if it's faster...
img.pixels[:] = pixels

# Should probably update image
img.update()