Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to iterate pixels with python API?
#1
Hi,

[GIMP 3.2 python API]

I'm trying to iterate over all the coordinates of an image, and create some calculated pixel values on a new layer.

I'm currently using the Gimp.Drawable.set_pixel() method, but its very slow (and supposed to be).

I'm struggling to find the right way to do this. I think there was a concept called "regions" in GIMP 2.xx. I understand I have to use a Gegl.Buffer. But from there I'm stuck
I can't find any definition, or just circular definitions, of what a Gegl buffer is, or any other concept. That's what makes things really difficult. 

Does a "buffer" represent the whole drawable? And if it is, how do I extract just a tile and iterate over the pixels?

What is a "shadow buffer"?

What is a "handler"?

What is "the abyss"?

Thanks!
Reply
#2
I was finally able to crack this problem. Here is some sample code:


Code:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# your standard imports, don't forget Gegl
import gi
gi.require_version('Gimp', '3.0')
from gi.repository import Gimp
gi.require_version('GimpUi', '3.0')
from gi.repository import GimpUi
gi.require_version('Gegl', '0.4')
from gi.repository import Gegl # << Gegl needed

# [...] other imports [...]

# needed for this example
import random

#
# [...] some code [...]
#

def randomColors(layer) :
    # example on how to iterate over pixels with Gegl and apply these in batches
    # this is much faster than drawing one by one with Gimp.Drawable.set_pixel()
    # important : the changed pixels can't be undone, it's better to draw them on a new layer
    
    thisBuffer = layer.get_buffer()
    startx = 100
    starty = 100
    sizex =   80 # region size, preferably not too big, iterate if necessary
    sizey =   80
    
    rectangleRegion = Gegl.Rectangle.new(startx, starty, sizex, sizey)
    
    bufferSize = sizex * sizey
    bufferData = []
    i = 0
    
    while i < bufferSize :
        
        # attribute some random values to rgb
        r = random.randint(0,255)
        g = random.randint(0,255)
        b =  random.randint(0,255)
        
        bufferData.extend([r, g, b])
        
        i += 1
        
    thisBuffer.set(rectangleRegion, "RGB u8", bufferData) # << this is where we write pixels!
    layer.update(startx, starty, sizex, sizey) # << necessary refresh
    
Reply
#3
Just a little Post-Scriptum about the Babl pixel format in the .set_rectangle method.
Here are the formats that I could gather from the internet, notably from here:
  • u... are for integer
  • RGB are for linear values
  • R'G'B' are for non-linear values (ie, with a perceptual color profile)
  • A is always linear 

The formats:
  • RGB u8
  • RGBA u8
  • RGBA float
  • R'G'B' u8
  • R'G'B'A u8
  • R'G'B'A float

The formats I presume should logically exist (correct me if wrong):
  • RGB u16
  • RGBA u16
  • R'G'B' u16
  • R'G'B'A u16
  • RGB u32
  • RGBA u32
  • R'G'B' u32
  • R'G'B'A u32
  • RGB float
  • R'G'B' float
Reply
#4
Scallact: For reference, all babl formats can be found here: https://gegl.org/babl/Reference.html
Reply
#5
(07-09-2026, 07:44 PM)CmykStudent_ Wrote: Scallact: For reference, all babl formats can be found here: https://gegl.org/babl/Reference.html

Oh wow, there a lot!!! That's crazy!

Thanks a lot, I should have found that myself! But Gogl doesn't seem to like Gegl! ;-) (Just joking)
Reply


Forum Jump: