I am trying to edit this image:
However, when I run
im = Image.open(filename)
im.show()
it outputs a completely plain white image of the same size. Why is Image.open() not working? How can I fix this? Is there another library I can use to get non-255 pixel values (the correct pixel array)?
Thanks,
Vinny
Image.open actually seems to work fine, as does getpixel, putpixel and save, so you can still load, edit and save the image.
The problem seems to be that the temp file the image is saved in for show is just plain white, so the image viewer shows just a white image. Your original image is 16 bit grayscale, but the temp image is saved as an 8 bit grayscale.
My current theory is that there might actually be a bug in show where a 16 bit grayscale image is just "converted" to 8 bit grayscale by capping all pixel values to 255, resulting in an all-white temp image since all the pixels values in the original are above 30,000.
If you set a pixel to a value below 255 before calling show, that pixel shows correctly. Thus, assuming you want to enhance the contrast in the picture, you can open the picture, map the values to a range from 0 to 255 (e.g. using numpy), and then use show.
from PIL import Image
import numpy as np
arr = np.array(Image.open("Rt5Ov.png"))
arr = (arr - arr.min()) * 255 // (arr.max() - arr.min())
img = Image.fromarray(arr.astype("uint8"))
img.show()
But as said before, since save seems to work as it should, you could also keep the 16 bit grayscale depth and just save the edited image instead of using show.
you can use openCV library for loading images.
import cv2
img = cv2.imread('image file')
plt.show(img)
Related
I want to convert a 24-bit PNG image to 32-bit so that it can be displayed on the LED matrix. Here is the code which I have used, but it converted 24-bit to 48-bit
import cv2
import numpy as np
i = cv2.imread("bbb.png")
img = np.array(i, dtype = np.uint16)
img *= 256
cv2.imwrite('test.png', img)
I looked at the christmas.png image in the code you linked to, and it appears to be a 624x8 pixel image with a palette and an 8-bit alpha channel.
Assuming the sample image works, you can make one with the same characteristics by taking a PNG image and adding a fully opaque alpha channel like this:
#!/usr/local/bin/python3
from PIL import Image
# Load the image and convert to 32-bit RGBA
im = Image.open("image.png").convert('RGBA')
# Save result
im.save("result.png")
I generated a gradient image and applied that processing and got this, so maybe you can try that:
I think you have confused the color bit-depth with the size of the input image/array. From the links posted in the comments, there is no mention of 32 as a bit depth. The script at that tutorial link uses an image with 3-channel, 8-bit color (red, green, and blue code values each represented as numbers from 0-255). The input image must have the same height as the array, but can be a different width to allow scrolling.
For more on bit-depth: https://en.wikipedia.org/wiki/Color_depth
I am reading an RGB image and converting it into HSV mode using PIL. Now I am trying to save this HSV image but I am getting an error.
filename = r'\trial_images\cat.jpg'
img = Image.open(filename)
img = img.convert('HSV')
destination = r'\demo\temp.jpg'
img.save(destination)
I am getting the following error:
OSError: cannot write mode HSV as JPEG
How can I save my transformed image? Please help
Easy one...save as a numpy array. This works fine, but the file might be pretty big (for me it go about 7 times bigger than the jpeg image). You can numpy's savez_compressed
function to cut that in half to about 3-4 times the size of the original image. Not fantastic, but when you are doing image processing you are probably fine.
I would like to convert a PNG32 image (with transparency) to PNG8 with Python Image Library.
So far I have succeeded converting to PNG8 with a solid background.
Below is what I am doing:
from PIL import Image
im = Image.open("logo_256.png")
im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)
im.save("logo_py.png", colors=255)
After much searching on the net, here is the code to accomplish what I asked for:
from PIL import Image
im = Image.open("logo_256.png")
# PIL complains if you don't load explicitly
im.load()
# Get the alpha band
alpha = im.split()[-1]
im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)
# Set all pixel values below 128 to 255,
# and the rest to 0
mask = Image.eval(alpha, lambda a: 255 if a <=128 else 0)
# Paste the color of index 255 and use alpha as a mask
im.paste(255, mask)
# The transparency index is 255
im.save("logo_py.png", transparency=255)
Source: http://nadiana.com/pil-tips-converting-png-gif
Although the code there does not call im.load(), and thus crashes on my version of os/python/pil. (It looks like that is the bug in PIL).
As mentioned by Mark Ransom, your paletized image will only have one transparency level.
When saving your paletized image, you'll have to specify which color index you want to be the transparent color like this :
im.save("logo_py.png", transparency=0)
to save the image as a paletized colors and using the first color as a transparent color.
This is an old question so perhaps older answers are tuned to older version of PIL?
But for anyone coming to this with Pillow>=6.0.0 then the following answer is many magnitudes faster and simpler.
im = Image.open('png32_or_png64_with_alpha.png')
im = im.quantize()
im.save('png8_with_alpha_channel_preserved.png')
Don't use PIL to generate the palette, as it can't handle RGBA properly and has quite limited quantization algorithm.
Use pngquant instead.
I've been having trouble trying to get PIL to nicely downsample images. The goal, in this case, is for my website to automagically downsample->cache the original image file whenever a different size is required, thus removing the pain of maintaining multiple versions of the same image. However, I have not had any luck. I've tried:
image.thumbnail((width, height), Image.ANTIALIAS)
image.save(newSource)
and
image.resize((width, height), Image.ANTIALIAS).save(newSource)
and
ImageOps.fit(image, (width, height), Image.ANTIALIAS, (0, 0)).save(newSource)
and all of them seem to perform a nearest-neighbout downsample, rather than averaging over the pixels as it should Hence it turns images like
http://www.techcreation.sg/media/projects//software/Java%20Games/images/Tanks3D%20Full.png
to
http://www.techcreation.sg/media/temp/0x5780b20fe2fd0ed/Tanks3D.png
which isn't very nice. Has anyone else bumped into this issue?
That image is an indexed-color (palette or P mode) image. There are a very limited number of colors to work with and there's not much chance that a pixel from the resized image will be in the palette, since it will need a lot of in-between colors. So it always uses nearest-neighbor mode when resizing; it's really the only way to keep the same palette.
This behavior is the same as in Adobe Photoshop.
You want to convert to RGB mode first and resize it, then go back to palette mode before saving, if desired. (Actually I would just save it in RGB mode, and then turn PNGCrush loose on the folder of resized images.)
This is over a year old, but in case anyone is still looking:
Here is a sample of code that will see if an image is in a palette mode, and make adjustments
import Image # or from PIL import Image
img = Image.open(sourceFile)
if 'P' in img.mode: # check if image is a palette type
img = img.convert("RGB") # convert it to RGB
img = img.resize((w,h),Image.ANTIALIAS) # resize it
img = img.convert("P",dither=Image.NONE, palette=Image.ADAPTIVE)
#convert back to palette
else:
img = img.resize((w,h),Image.ANTIALIAS) # regular resize
img.save(newSourceFile) # save the image to the new source
#img.save(newSourceFile, quality = 95, dpi=(72,72), optimize = True)
# set quality, dpi , and shrink size
By converting the paletted version to RGB, we can resize it with the anti alias. If you want to reconvert it back, then you have to set dithering to NONE, and use an ADAPTIVE palette. If there options aren't included your result (if reconverted to palette) will be grainy. Also you can use the quality option, in the save function, on some image formats to improve the quality even more.
I want to take a BMP or JPG and duplicate it so the new image will darker (or brighrt) what function can I use?
Ariel
You can use ImageEnhance module of PIL:
import Image
import ImageEnhance
image = Image.open(r'c:\temp\20090809210.jpg')
enhancer = ImageEnhance.Brightness(image)
brighter_image = enhancer.enhance(2)
darker_image = enhancer.enhance(0.5)
Look at PIL and ImageEnhance documentation for more details.
Note: I think ImageEnhancer documentation is a bit too terse, and you may need some experimenting within the interactive prompt to get it right.
If you want to do it the hard way i.e. code up a pixel by pixel intensity change. Here is how:
1) Convert from RGB to HSI
2) Increase or decrease the Intensity component
3) Conver back from HSI to RGB
True fade out i.e. alpha channel is not present in the JPG or BMP formats [ RGBA format image in PIL] . You get black to white using the the intensity technique. If you want to use alpha use png or tiff instead.