pythonpython-2.7picklegdkpixbufbytesio

Re-Construct a png image from a GDK Pixbuf


I want to send an image Pixbuf over a socket but the received image is only in black and white and distorted. Here are the steps I'm using:

1) get pixels array of that Pixbuf

2) serialize the pixels array

3) Convert the serialized string to a BytesIO

4) Send over the socket

MyShot = ScreenShot2()
frame = MyShot.GetScreenShot() #this function returns the Pixbuf
a = frame.get_pixels_array()
Sframe = pickle.dumps( a, 1)
b = BytesIO()
b.write(Sframe)
b.seek(0)

after this I have to rebuild the image by:

1) Deserialize the received string in its original pixels array

2) Build the Pixbuf from the pixels array

3) Save the image

res = gtk.gdk.pixbuf_new_from_data(pickle.loads(b.getvalue()), frame.get_colorspace(), False, frame.get_bits_per_sample(), frame.get_width(), frame.get_height(), frame.get_rowstride()) #also tried this res = gtk.gdk.pixbuf_new_from_array(pickle.loads(b.read()),gtk.gdk.COLORSPACE_RGB,8)
res.save("result.png","png")

Solution

  • If you want to send a Pixbuf over a socket you have to send all data, not just the pixels. The BytesIO object is not necessary as Numpy arrays have a tostring() method.

    It would be easier/make more sense to send a PNG instead of sending raw data and encode it at the receiving end to a PNG image. Here a BytesIO object actually is necessary to avoid a temporary file. Sending side:

    screen = ScreenShot()
    image = screen.get_screenshot()
    png_file = BytesIO()
    image.save_to_callback(png_file.write)
    data = png_file.getvalue()
    

    Then send data over the socket and on the receiving side simply save it:

    with open('result.png', 'wb') as png_file:
        png_file.write(data)