Are Image Operations just Slow?

I’m trying to implement image convolution in a blender script (for say, edge detection).

Firstly I’m trying to separate a single colour channel of a loaded image into an array 1/4 of the size to use in the convolution, however it seems painfully slow to do this:

import bpy
import math

D = bpy.data
image = D.images.load('C:/Blender Files/textures/peppers.jpg', check_existing=True)

def channel(img, c):
    buff = img.pixels
    chan = []
    chan = [0 for i in range(0, int(len(img.pixels)/4))]
    
    for i in range(0, int(len(img.pixels)/4)):
        if (i%1000 == 0):
            print(i)
        chan[i] = buff[4*i+c]
        
    print(chan)
    return chan

red = channel(image, 0)

It prints out 1000 every couple of seconds meaning it takes approximately 2ms to copy over a pixel value, is this just due to the nature of python scripts in blender or is there a faster way to do this?

Secondly, if it is this slow to just extract the red channel of the image array, is there any hope in writing a image convolution function that iterates over the image with much more calculation at each pixel?

Update:

So I read that accessing individual pixels of a loaded image can be slow, hence why I’d tried copying the array into a new buffer, buff. However buff = img.pixels just sets the buff to point to the original image object, buff = img.pixels[:] makes a duplicate.

This solved the problem quick time.

I guess my new question is now aimed at the devs;
if it takes 2ms to change or read a specific pixel object but almost instant to copy the whole array into a new buffer, why is there not an intermediate buffer used in the implementation of how image objects are accessed? and why is the nature of them so slow?

You can get the pixels of the image even faster by using foreach_get and foreach_set. Have a look here
https://developer.blender.org/rB9075ec8269e7cb029f4fab6c1289eb2f1ae2858a

Interesting, thank you!

related: Fill large image via Python