Δημιουργία ImageSurface στο pycairo με χρηση της PIL.

Πρόσφατα δοκίμαζα το cairo (με την χρήση των python bindings, pycairo). Μια 2D vector graphics βιβλιοθήκη γραμμένη σε C με bindings για πολλές γλώσσες.

Ήθελα να μπορώ να φορτώνω εικόνες απο αρχεία με διάφορα format και να τα βάζω στο canvas μου.

Η PIL (Python Imaging Library) είναι μια πολύ καλή βιβλιοθήκη που μας επιτρέπει να διαβάζουμε και να επεξεργαζόμαστε πολλά αρχεία είκόνας.

Η PIL μας δίνει την δυνατότητα να πάρουμε τα “raw” δεδομένα μιας εικόνας, το cairo μας επιτρέπει να φτιάξουμε ένα ImageSurface απο τα “raw” δεδομένα μιας εικόνας αρα το πρόβλημα θα έπρεπε να είναι απλό. Μετατρέπουμε μια εικόνα σε RGBA format (γιατί μπορεί πχ να είναι pallete ) , παίρνουμε τα raw δεδομένα και τα δίνουμε στο cairo. Δεν είναι ακριβώς έτσι όμως. Η PIL χρησιμοποιεί RGBA format στα raw δεδομένα ενώ η cairo ARGB. (δηλαδή πρώτα το alpha channel αντί για τελευταίο όπως στο RGBA). Το αποτέλεσμα είναι οτι αντιστρέφονται τα χρώματα στο B και R color bands.

Για να το λύσουμε αυτό πρέπει να αντιστρέψουμε τα B και R color bands (blue και Red δηλαδή). Το οτι χρειάζεται να γίνει αυτό, όπως και το πώς γίνεται το βρήκα με αρκετό ψάξιμο ψάξιμο στα intertubes και για αυτό το καταγράφω εδώ. Υπάρχει στο cookbook του cairo σχετικό θέμα αλλα δεν λύνει την μετατροπή RGBA->ARGB και αυτό που αναφέρει σαν λύση (οτι το PIL μπορεί να μετατρέψει ARGB) δεν δουλεύει.

Ορίστε λοιπόν:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import Image
import cairo
import numpy

img = Image.open('our_file.jpg')
img = img.convert("RGBA")
r , g , b, a  = img.split()
img = Image.merge("RGBA"  ( b, g, r ,a ) )
buff = numpy.asarray(img)
buff.flags.writeable = True

width,height = img.size
stride = cairo.ImageSurface.format_stride_for_width(
                  cairo.FORMAT_ARGB32,width)

surface = cairo.ImageSurface.create_for_data(buff,
                    cairo.FORMAT_ARGB32, width,height,stride)

Εδώ χρησιμοποιώ την numpy για writeable buffer που χρειάζεται η μέθοδος create_for_data() αλλα γίνεται το ίδιο απλά και με το array module.

Comments !

blogroll

social