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
Forum Archive
From ui.Image to PIL
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()
Sorry. The variables are wrongly named. "pilimg" should be "img" and "img" should be "pilimg". The program works fine.
@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()
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()
@Phuket2 You can access named images with Image.open