3

I'm using Python and GDK to load an image:

Pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename)

I then want to edit pixels of this pixbuf and display it on a GTKImage.

Here's what I tried:

pixList = Pixbuf.get_pixels()

then:

Pixbuf = GdkPixbuf.Pixbuf.new_from_data(pixList, Pixbuf.get_colorspace(), Pixbuf.get_has_alpha(), Pixbuf.get_bits_per_sample(), Pixbuf.get_width(), Pixbuf.get_height(), Pixbuf.get_rowstride())

But when I display this Pixbuf in a GTKImage, it displays only black pixels. It works with the first new_from_file() though.

What's wrong with it?

Adrien Neveu
  • 827
  • 1
  • 15
  • 28

1 Answers1

0

Gtk doesn't provide and support for setting pixels in a pixbuf, but you can work around that and create/load and write new files like this:

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Pango
from gi.repository import Gtk as gtk
from gi.repository import Gdk as gdk
from gi.repository import GObject as gobject
from gi.repository import GtkSource as gtksource
from gi.repository.GdkPixbuf import Pixbuf
from gi.repository import GtkSource
from gi.repository import GObject
from gi.repository import Gtk as gtk, GdkPixbuf

width = 800
height = 500

def draw_pixel(pixels, x, y, rgb):
    # make sure pixel data is reasonable
    x = min(x, width)
    y = min(y, height)
    r = min(rgb[0], 255)
    g = min(rgb[1], 255)
    b = min(rgb[2], 255)

    # insert pixel data at right location in bytes array
    i = y*width + x
    pixels[i*3 + 0] = r
    pixels[i*3 + 1] = g
    pixels[i*3 + 2] = b

def init_pixels(width, height, color=[0,0,0]):
    pixels = bytearray(width*height*3)
    for i in range(width):
        for j in range(height):
            draw_pixel(pixels, i,j, color)

    return pixels

def save_file(file_name, pixels):

    with open(file_name, 'wb') as f:
        f.write(header)
        # one-liner to write data
        f.write(bytes(pixels))

def get_pixels(image):
    raw_pixels = image.get_pixbuf().get_pixels()
    return bytearray(raw_pixels)


# header for PNM file
s = 'P6\n\n' + str(width) + " " + str(height) + ' \n255\n'
header = bytes(s, 'ascii')

# OPTIONAL
# create an input file
# l = GdkPixbuf.PixbufLoader.new_with_type('pnm')
# l.write(header)
# # create a blank red file
# l.write(bytes(init_pixels(width, height, [255,0,0])))
# input_image = gtk.Image.new_from_pixbuf(l.get_pixbuf())

# # save to disk        
# save_file("input.pnm", get_pixels(input_image))

# retrieve image from disk
image = gtk.Image.new_from_file("input.pnm")    

pixels = get_pixels(image)

# add a blue square
for i in range(50,100):
    for j in range(50,100):
        draw_pixel(pixels, i,j, [0,0,255])

# process and save to new output file
save_file("output.pnm", pixels)

# retrieve from disk
output_image = gtk.Image.new_from_file("output.pnm")    

w = gtk.Window()
w.add(output_image)
w.show_all()
gtk.main()

Here is a example showing a blue square being added to the input image:

adding blue square

jackw11111
  • 1,457
  • 1
  • 17
  • 34