Forum Archive

From ui.Image to PIL

Phuket2

I have not tried this before. From a ui.Image to a PIL image. I don't understand the differences about the formats. But I can see the PIL module has a wealth of methods/functions like filters for blur etc. unlike ui.Image. I did a pretty good search on the forum and could only find going from PIL Image to ui.Image, not the reverse. I have a bad feeling I am missing something very basic here.
What I am trying to do is load a Pythonista asset like a icon using img = ui.Image.named(IMG_NAME). Once I have that img, I would like to apply some PIL operations on the image. But from what I can see, I need to convert the img to a PIL Image first. This is what I can not work out how to do .To convert it back to a ui.Image should not be a problem as there are quite a few posts on the forum on how to do that.
Any help appreciated

abcabc
from PIL import Image, ImageOps, ImageFilter
import ui

def sketch(img):
    edge_img = img.filter(ImageFilter.CONTOUR)
    return ImageOps.grayscale(edge_img)

def emboss(img):
    edge_img = img.filter(ImageFilter.EMBOSS)
    return ImageOps.grayscale(edge_img)

import io

def ui2pil(ui_img):
    png_data = ui_img.to_png()
    return Image.open(io.BytesIO(png_data))

def pil2ui(pil_image):
    buffer = io.BytesIO()
    pil_image.save(buffer, format='PNG')
    return ui.Image.from_data(buffer.getvalue())

def main():
    pilimg = ui.Image.named('Dog_Face')
    img = ui2pil(pilimg)
    sketch(img).show()
    img1 = pil2ui(img)
    img2 = ui2pil(img1)
    emboss(img2).show()

if __name__ == '__main__':
    main()
abcabc

Sorry. The variables are wrongly named. "pilimg" should be "img" and "img" should be "pilimg". The program works fine.

Phuket2

@abcabc , thanks. It's nice. Exactly what I was after. I understand, this module is going to take quite a bit of thought to optimize both speed and quality. I just never worked with PIL before. Adds an infinite number of ideas what you can do with the built in icons/assets though. I added rotate to your main to test, the result is not great, but I am sure there are a lot of ways to control the quality. But thanks, this gets me up and running so I can play/test

def main():
    img = ui2pil(ui.Image.named('iow:arrow_left_a_256'))

    sketch(img).show()
    img1 = pil2ui(img)
    img2 = ui2pil(img1)

    emboss(img2).show()

    img3 = img.rotate(45)
    img3.show()
ccc

There was this related thread: https://forum.omz-software.com/topic/1935/how-can-i-convert-a-pil-image-to-a-ui-image

I believe that there was once an issue where repeatedly calling a variant of pil2ui() that did not close buffer resulted in a Pythonista crash. A safer formulation might be:


def pil2ui(pil_img):
    with io.BytesIO() as buffer:
        pil_img.save(buffer, format='PNG')
        return ui.Image.from_data(buffer.getvalue())

# other ideas...  ==========================

import io
import ui
from PIL import Image, ImageOps, ImageFilter

def sketch(pil_img):
    return ImageOps.grayscale(pil_img.filter(ImageFilter.CONTOUR))

def emboss(pil_img):
    return ImageOps.grayscale(pil_img.filter(ImageFilter.EMBOSS))

def ui2pil(ui_img):
    return Image.open(io.BytesIO(ui_img.to_png()))

def pil2ui(pil_img):
    with io.BytesIO() as buffer:
        pil_img.save(buffer, format='PNG')
        return ui.Image.from_data(buffer.getvalue())

def main():
    img = ui2pil(ui.Image.named('Dog_Face'))
    sketch(img).show()
    img1 = pil2ui(img)
    img2 = ui2pil(img1)
    emboss(img2).show()

if __name__ == '__main__':
    main()
Webmaster4o

@Phuket2 You can access named images with Image.open