Tkinter: saving image results in quality lost - python

I read a picture and display it in a Canvas:
im=the_canvas.create_image(0,0,anchor="nw",image=img)
After that, I save it:
returned_value=the_canvas.postscript(file="saved.ps", height=image_h, width=image_w, colormode="color")
r=Image.open("saved.ps")
r.save("saved.png")
How can I save the image in png or jpg formats without loosing its quality ?
Thank you in advance.

You can use this code:
from PIL import Image,ImageTK
save_name=filedialog.asksaveasfilename()
canvas.postscript(file=save_name+".eps") # save canvas as encapsulated postscript
img = Image.open(save_name+".eps")
img.save(save_name+".png", "png",quality=99)
This will save the image as a png.

Related

how to save or convert holoviews object to image or video

I am trying to detect an image through a detector and want to save it to video or image, but I could not find anything with holoviews DynamicMap to save to image or to video. Please help
fname=r'D:\tiff_data\output_0302.tif'
#fname=r'D:\cite-on-main\poly_wet (1209).tif'
save='outputs/demo'
os.makedirs(save,exist_ok=True)
im=Image.open(fname)
import cv2
img = cv2.imread(fname)
median=np.median(img,axis=2)
upscaling=0.9
detector=Detector('./weights/', gpu='0', init_shape=img.shape[:2], init_upscaling=upscaling)
def explore(Score, Upscaling):
width = median.shape[1]
height = median.shape[0]
detections=detector.detect(median,Score,Upscaling)
aaa = hv.Image((np.arange(width),np.arange(height),median)).opts(title='',invert_yaxis=True, cmap='gray',width=median.shape[1]*scale, height=median.shape[0]*scale,)*hv.Path([hv.Bounds(tuple(r)) for r in detections[:,:4]]).opts(color='lime')
return aaa
dmap=hv.DynamicMap(explore, kdims=['Upscaling','Score'])
dmap.redim.values( Score=np.arange(0.1,1,0.05), Upscaling=np.arange(1,3,0.1))
for reference i have added an image
You can convert a DynamicMap to a HoloMap (http://holoviews.org/user_guide/Live_Data.html#converting-from-dynamicmap-to-holomap) and export a HoloMap to a png or gif or mp4 (https://holoviews.org/user_guide/Exporting_and_Archiving.html). You may need to install some extra dependencies depending on your backend, but the error messages should guide you to what you need. Exporting Matplotlib output is generally easier and faster than Bokeh output, but both should work.

Pysimplegui resizing images

I'm trying to resize images in pysimplegui however it crops the images instead of resizing.
My image element is written as:
ui.Image('{filename}'), size=(50,50)))
Which results to something like:
While the original looks like:
I've seen somewhere else that suggests PIL (link). However, this looks a lot longer than i liked and was wondering if there is an easier way to do this.
Peace
hi
to resize an image you need to take advantage of the pillow library, but you need to import other libraries too in order to convert it into bytes if needed, here is an example:
import PIL.Image
import io
import base64
def resize_image(image_path, resize=None): #image_path: "C:User/Image/img.jpg"
if isinstance(image_path, str):
img = PIL.Image.open(image_path)
else:
try:
img = PIL.Image.open(io.BytesIO(base64.b64decode(image_path)))
except Exception as e:
data_bytes_io = io.BytesIO(image_path)
img = PIL.Image.open(data_bytes_io)
cur_width, cur_height = img.size
if resize:
new_width, new_height = resize
scale = min(new_height/cur_height, new_width/cur_width)
img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.ANTIALIAS)
bio = io.BytesIO()
img.save(bio, format="PNG")
del img
return bio.getvalue()
ui.Image(key="-PHOTO-",size=(50,50) #after some change
elif event == "-IMG-": # the"-IMG-" key is in [ui.I(key="IMG",enable_events=True), ui.FileBrowse()]
window['-PHOTO-'].update(data=resize_image(value["-IMG-"],resize=(50,50)))
I hope this helps
Helloooo, heres my workaround to resize images in pysimplegui:
read the image stored in the path 'old_path'.
resize this image to my desired dimensions.
store the resized image in a folder as a 'png' file.
finally display the resized image.
old_path = os.path.join(
values["-FOLDER-"], values["-FILE LIST-"][0]
)
# read image using old_path
im = cv2.imread(old_path)
# resize image to desired dimensions
im = cv2.resize(im,[700,500])
# save image to temporary folder (new_path) as png
new_path ='temp_storage/image_to_show.png'
cv2.imwrite(new_path,im)
# update window with new resized image
window["-IMAGE-"].update(new_path)
if you need the full code let me know. The image storing folder only stores the image to be shown, it will override every time you choose a new image so no worries about images pilling up.
cv2 needed for reading, resizing and writing. (or PIL)
Goodluck!

Python reportlab generates large files when I add jpeg

I try to generate pdf filled up with jpeg images, but even when I add only one 176 kB (1142 × 1713) image, I get 2.5 mB pdf. When I open this pdf in Photoshop, I see that this is the same jpeg on a canvas, with the same size. Looks like reportlab doesn't do any compression for jpeg or something. There's no any information about it in the documentation.
Here's my code:
...
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
from reportlab.lib.units import mm
from PIL import Image
img = Image.open('/Users/dimabogdan/Downloads/3edbc3086ccadcae8c59a702a4e03020.jpg')
# <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1142x1713 at 0x10A74BE48>
img = ImageReader(img)
c = canvas.Canvas('pdf.pdf', pagesize=(320*mm, 470*mm))
c.drawImage(img, x=0, y=0, height=152*mm, width=102*mm)
c.save()
...
How can I solve this issue?
I just came across this same issue, and for anyone still having this problem the code:
img = ImageReader(img)
c.drawImage(img, x=0, y=0, height=152*mm, width=102*mm)
creates a PDF with uncompressed image data, however you can compress the image with jpeg into a temporary buffer and feed it to reportlab and it will save it compressed, like so:
with BytesIO() as img_jpg: # we create a new BytesIO object, don't forget 'from io import BytesIO'
img.save(img_jpg, format='jpeg') # img is the image from Image.open, we save it to the buffer
img_jpg.seek(0) # reset the buffer position
img_ = ImageReader(img_jpg) # create ImageReader from buffer
c.drawImage(img, x=0, y=0, height=152*mm, width=102*mm) # draw compressed jpeg to PDF
Your sample code should work fine, since you are feeding a jpeg image too, but it doesn't...

Can you display an image inside of a python program (without using pygame)?

I want to do something like:
import image
image.display_image('http://upload.wikimedia.org/wikipedia/commons/8/84/Example.svg')
And it would come out as an image.
P.S. I want PNG or JPEG, not GIFs.
This question is somewhat old, but as info on how to do this easily isn't easy to find online, I'm posting this answer in hope it can be useful to others in the future.
To raster a SVG and put it into a ImageTk.PhotoImage object you can do this inside a class used for a tkinter gui:
def svgPhotoImage(self,file_path_name):
import Image,ImageTk,rsvg,cairo
"Returns a ImageTk.PhotoImage object represeting the svg file"
# Based on pygame.org/wiki/CairoPygame and http://bit.ly/1hnpYZY
svg = rsvg.Handle(file=file_path_name)
width, height = svg.get_dimension_data()[:2]
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
context = cairo.Context(surface)
#context.set_antialias(cairo.ANTIALIAS_SUBPIXEL)
svg.render_cairo(context)
tk_image=ImageTk.PhotoImage('RGBA')
image=Image.frombuffer('RGBA',(width,height),surface.get_data(),'raw','BGRA',0,1)
tk_image.paste(image)
return(tk_image)
Then display the image on a Frame widget (e.g. mainFrame) this way:
tk_image=self.svgPhotoImage(filename)
mainFrame.configure(image=tk_image)
If you want to save the picture you can return image instead of tk_image and save it this way:
image.save(filename) # Image format is autodected via filename extension

How to convert a Pyglet image to a PIL image?

i want to convert a Pyglet.AbstractImage object to an PIL image for further manipulation
here are my codes
from pyglet import image
from PIL import Image
pic = image.load('pic.jpg')
data = pic.get_data('RGB', pic.pitch)
im = Image.fromstring('RGB', (pic.width, pic.height), data)
im.show()
but the image shown went wrong.
so how to convert an image from pyglet to PIL properly?
I think I find the solution
the pitch in Pyglet.AbstractImage instance is not compatible with PIL
I found in pyglet 1.1 there is a codec function to encode the Pyglet image to PIL
here is the link to the source
so the code above should be modified to this
from pyglet import image
from PIL import Image
pic = image.load('pic.jpg')
pitch = -(pic.width * len('RGB'))
data = pic.get_data('RGB', pitch) # using the new pitch
im = Image.fromstring('RGB', (pic.width, pic.height), data)
im.show()
I'm using a 461x288 image in this case and find that pic.pitch is -1384
but the new pitch is -1383
This is an open wishlist item:
AbstractImage to/from PIL image.

Categories