Python PIL thumbnail with Image.ANTIALIAS. How to preserve quality - python

I'm trying to resize images while keeping aspect ratio. I use PIL's thumbnail method for this. I use Image.ANTIALIAS filter.
You can check my code here:
image = Image.open(design.design.path)
format = image.format
image = ImageOps.mirror(image)
new_size = (241, 241)
image.thumbnail(new_size, Image.ANTIALIAS)
image.save(response, format)
This code works perfectly however quality is lost after thumbnail. I can see it by zooming in on the saved image. I can see pixels at the corners of the image while I don't on the original image. This is seen even better when I print out resized image.
You can check out sample images here: http://imgur.com/a/ifZoU
Please tell me if you need anything else

Image.save has options for you:
img.save(fpath, 'image/png', quality=100, optimize=True)

If you are making thumbnails of a pixel-based image, of course you will loose quality. Re-sizing this kind of image (as opposed to vector images) simply throw information away - there is no way to recover it.
IF you need to view the image in full size, you have to preserve the original image, and keep the scaled-down version to be shown only where it is needed - use the original for everything else.
https://en.wikipedia.org/wiki/Raster_graphics

Related

PIL shows black image when attempting to view image

The current goal of what I am writing is to download an image from S3, open it using Pillow, and show the image. I am able to download the image fine; it can be viewed properly from my photos. However, when I try to use the image with PIL, all of the pixel values are black. It does however, retain the shape of the image, which leads me to know that the image is at least being read. the code is shown below:
s3.Bucket(bucket).download_file(key, key) # downloaded perfectly fine
img = Image.open(key)
img.show() # shows all black with the Images's dimensions
I know I can read from bytes, but that will give me a 1d array of all the bytes instead of the dimensions needed for an image.

Python Wand Scaling Issue

I'm using Python Wand module(version 0.4.3.) to convert an image stored in pdf to PNG. Final PNG quality is great when I saved the final image in its orignal image width and height. But, when I try to save it to smaller image final PNG gets blurry and quality is not that great.
The difference between two images is shown here. Top image is converted to original size (10800x7200px). The second one is scale to 1250x833px.
Is there any way I can improve the second image? I played with different filter and blur setting.But, could not get the image quality I want. Any help is greatly appreciated.
Code I used to convert PDF to png in its original size:
def pdf_to_png(pdf_name, res):
with Image(filename=pdf_name, resolution=res) as img:
with Image(width=img.width,height=img.height, background=Color("white")) as bg:
bg.composite(img,0,0)`
bg.save(filename="Drawing_improved_wand.png")`
pdf_to_png('Drawing_1.pdf', 300)
Code for resized png:
with Image(filename="Drawing_1.pdf", resolution=(300,300)) as img:
with Image(width=1250, height=833, background=Color("white")) as bg:
img.resize(1250, 833,filter='undefined', blur=1)
img.format = 'png'
bg.composite(img,0,0)
bg.save(filename='Drawing_improved_wand1250x833.png')
This is likely due to an inefficiency with how ImageMagick handles rasterization form PDF text + vectors, and not because of anything you're doing wrong. The large PNG likely has the same problems as the small one, but since the resolution is almost an order of magnitude higher, the effects become imperceptible.
If when exporting to the large PNG the file looks good, I would use this for further processing (like scaling down) and not the PDF.
have you try to set blur < 1?
for example:
img.resize(1250, 833,filter='undefined', blur=0.1)

Image resized with Python PIL are darker

I'm fairly new to PIL and having issue with some image processing. I'm just trying to resize an image to a different resolution using PIL:
resized_hd = image.resize((hd_width, hd_height), Image.ANTIALIAS)
However, the resized picture does not look as good/bright as the original one.
Original (5184*3456) -> http://d31d9cjolqcwln.cloudfront.net/San+Francisco/sutro+baths.jpg
Resized (2048*1366) -> http://d31d9cjolqcwln.cloudfront.net/San+Francisco/HD-sutro+baths.jpg
Any guess ?
I think it's because one of the two images (the original one) has an embedded color profile, which the other one (the resized one) doesn't have. I discovered this by trying to open the original image in gimp. The color profile will cause advanced viewers to make corrections, in theory to fix differences like the ones between paper and screen. When I view the two images in a simple viewer that doesn't know about color profiles, they are really the same brightness. It looks like the PIL library ignores the color profile and doesn't carry it onto the resized image.
I can't help you more precisely than that, though, as I don't know much about color profiles. There might be tools to copy the profile over.
Kuddo to Armin for his suggestion.
Pil allow you to attach an ICC profile to a resized image using the following code:
icc_profile = im1.info.get('icc_profile')
im6 = im1.resize((hd_width, hd_height), Image.ANTIALIAS)
## this one will preserve the colours
im6.save("colorok-"+image,icc_profile=icc_profile)
## this one don't
im6.save("nop-"+image)

Remove alpha compositing knowing the watermark (revert/compensate)

I have watermarked a bunch of images image with PIL (PILLOW in fact).
I have the original watermark and I know exactly how it has been resized and pasted on the image (0.75 opacity). The watermark is essentially black, white and red.
I want to restore images as close as possible as they were originally.
Is there any chance I could do that automatically?
What about quality? Is it worth it? Do you have examples of the result of such a process?
If so, how would I manage to do this?
Here is the code I used to watermark the image:
logo = Image.open(path)
red, green, blue, alpha = logo.split()
alpha = ImageEnhance.Brightness(alpha).enhance(0.75)
logo.putalpha(alpha)
img = Image.open('...')
img = Image.composite(logo, img, logo)
I've made a mask with of my logo and use GIMP's G'MIC plugin : http://blog.patdavid.net/2014/02/getting-around-in-gimp-gmic-inpainting.html
Here is as far as I can get, which is not really good enough:
This has been made with inpainting technic, but I am sure I could somehow exploit the fact that my watermark is somewhat transparent.
I've also tried to unblend the picture, given the watermark and watermarked pictures as input.
Unforunately, the watermarked picture being compressed in jpeg, I couldn't get any better than this :

How do you scale an animated GIF image in PIL and preserve the animation

I'm wondering if it's possible to scale an animated GIF image using PIL. In particular Plone’s archetypes ImageField currently loses the animation from images scaled using its scale method:
def scale(self, data, w, h, default_format = 'PNG'):
""" scale image (with material from ImageTag_Hotfix)"""
#make sure we have valid int's
size = int(w), int(h)
original_file=StringIO(data)
image = PIL.Image.open(original_file)
# consider image mode when scaling
# source images can be mode '1','L,','P','RGB(A)'
# convert to greyscale or RGBA before scaling
# preserve palletted mode (but not pallette)
# for palletted-only image formats, e.g. GIF
# PNG compression is OK for RGBA thumbnails
original_mode = image.mode
img_format = image.format and image.format or default_format
if original_mode == '1':
image = image.convert('L')
elif original_mode == 'P':
image = image.convert('RGBA')
image.thumbnail(size, self.pil_resize_algo)
# decided to only preserve palletted mode
# for GIF, could also use image.format in ('GIF','PNG')
if original_mode == 'P' and img_format == 'GIF':
image = image.convert('P')
thumbnail_file = StringIO()
# quality parameter doesn't affect lossless formats
image.save(thumbnail_file, img_format, quality=self.pil_quality)
thumbnail_file.seek(0)
return thumbnail_file, img_format.lower()
I know how to identify a animated GIF: The following evaluates to True image.format == 'GIF' and image.seek(image.tell()+1). I’ve tried not converting to RGBA mode but that doesn't work.
Background: On our Plone instance we've modified the default image type to set the original_size attribute of its image field to force all images to scaled with an appropriate quality setting. This works great for jpegs but means we currently can't upload animated GIFs
You can use images2gif.py to read gifs and than scale each frame independently. images2gif will allow you to write an animated gif with a sequence of Images.
The images2gif.py I found on the internet didn't handle transparency, so i fixed that. You can find that here:
https://bitbucket.org/bench/images2gif.py
PIL has got some limited support for animated GIF's but it is, as said, limited, and you have to work in very low level to deal with it.
While it is possible to manipulate and scale GIFs in PIL (Pillow) at the current version (9.2), its rather obscure, and only offer the "rendered" version of each frame: that is, if you have a GIF with custom palettes or shapes per frame, you can only get access to the flattened frames as they are presented in an image viewing program.
I'd advise trying some other method for scaling images than PIL if you want to deal with animated gif's. Possibly, the most straightforward way is to use an off-process ImageMagick, with subprocess.Popen - (and even then, at this time, I am only guessing ImageMagick "does the right thing" with animated GIF's) -
An option is to have an "image processing server", with another Python script, apart from your zope install that will receive requests to scale the images - possibly with a xmlrpc call - you could build this as a GIMP plug-in and use GIMP for scaling the GIF's.
Another option is to leave things as they are, and use "stills" for animated GIF's where they need to appear in another dimension than the original, and display the original image where the animation is appropriate. (Or maybe simply require that animated gif's be submitted already on the proper size)
Pillow (PIL's fork) supports animated GIF since version 3.0.0 when PR #1384 was merged.

Categories