python PIL - Convert [animated] gif frames to JPG but artifacts - python

Edit: The problem with my original search for information was that I did not distinguish between gifs and "animated gifs". Hence there are a lot of resources on SO to deal with this question.
Resources:
Link 3
Evidently PIL itself is poorly equipped to deal with animated gifs.
I'm trying to convert gif frames to jpg. For some gifs (mostly black and white) this works out fine, but for others (mostly color) not so much. I've looked at a few of the posts on SO, and tried them, to no avail. In particular I tried out: Link1 , Link2.
Performance is a mild consideration, but for now I'd just like a working solution. A consistent pattern is that the first image of the gif will always come out perfect. Interestingly enough, I have even tried out Zamzar and it also produces the same noise data. I was doing some research and it seems that this might be an issue with the LZW compression algorithm, though on SO, I've seen posts that suggest PIL takes care of LZW decompression. On the other hand I've heard that LZW decompression is propitiatory.
Note that I've also tried converting to PNG without success there either. Are the white dots layered on top of the image or something?
Here is a sample gif that produces this error.
Edit: I just came across images2gif.py. I will update this post if it works for this problem.
Here is the code I'm using:
from PIL import Image
import sys
import os
def processImage(infile):
try:
im = Image.open(infile)
except IOError:
print "Cant load", infile
sys.exit(1)
i = 0
mypalette = im.getpalette()
try:
while 1:
im.putpalette(mypalette)
new_im = Image.new("RGB", im.size)
#new_im = Image.new("RGB", im.size)
new_im.paste(im)
new_im.save('foo'+str(i)+'.png')
#if(os.stat('foo' + str(i)+'.png')):
# os.remove('foo' + str(i) + '.jpg')
i += 1
mypalette = im.getpalette()
im.seek(im.tell() + 1)
except EOFError:
pass # end of sequence

Related

how do i increase the resolution of my gif file?

As I am trying to create a gif file, the file has been created successfully but it is pixelating. So if anyone can help me out with how to increase resolution.
.Here is the code:-
import PIL
from PIL import Image
import NumPy as np
image_frames = []
days = np.arange(0, 12)
for i in days:
new_frame = PIL.Image.open(
r"C:\Users\Harsh Kotecha\PycharmProjects\pythonProject1\totalprecipplot" + "//" + str(i) + ".jpg"
)
image_frames.append(new_frame)
image_frames[0].save(
"precipitation.gif",
format="GIF",
append_images=image_frames[1:],
save_all="true",
duration=800,
loop=0,
quality=100,
)
Here is the Gif file:-
Here are the original images:-
image1
image2
iamge3
Updated Answer
Now that you have provided some images I had a go at disabling the dithering:
#!/usr/bin/env python3
from PIL import Image
# User editable values
method = Image.FASTOCTREE
colors = 250
# Load images precip-01.jpg through precip-12.jpg, quantize to common palette
imgs = []
for i in range(1,12):
filename = f'precip-{i:02d}.jpg'
print(f'Loading: {filename}')
try:
im = Image.open(filename)
pImage = im.quantize(colors=colors, method=method, dither=0)
imgs.append(pImage)
except:
print(f'ERROR: Unable to open {filename}')
imgs[0].save(
"precipitation.gif",
format="GIF",
append_images=imgs[1:],
save_all="true",
duration=800,
loop=0
)
Original Answer
Your original images are JPEGs which means they likely have many thousands of colours 2. When you make an animated GIF (or even a static GIF) each frame can only have 256 colours in its palette.
This can create several problems:
each frame gets a new, distinct palette stored with it, thereby increasing the size of the GIF (each palette is 0.75kB)
colours get dithered in an attempt to make the image look as close as possible to the original colours
different colours can get chosen for frames that are nearly identical which means colours flicker between distinct shades on successive frames - can cause "twinkling" like stars
If you want to learn about GIFs, you can learn 3,872 times as much as I will ever know by reading Anthony Thyssen's excellent notes here, here and here.
Your image is suffering from the first problem because it has 12 "per frame" local colour tables as well as a global colour table3. It is also suffering from the second problem - dithering.
To avoid the dithering, you probably want to do some of the following:
load all images and append them all together into a 12x1 monster image, and find the best palette for all the colours. As all your images are very similar, I think that you'll get away with generating a palette just from the first image without needing to montage all 12 - that'll be quicker
now palettize each image, with dithering disabled and using the single common palette
save your animated sequence of the palletised images, pushing in the singe common palette from the first step above
2: You can count the number of colours in an image with ImageMagick, using:
magick YOURIMAGE -format %k info:
3: You can see the colour tables in a GIF with gifsicle using:
gifsicle -I YOURIMAGE.GIF

Resizing Image in Python without losing letter quality

I have tried using the following code in order resize my picture, but I lose so much quality that I cannot even read the letters clearly. At first I create it the picture from a string, which has very good quality .
handoverNote = str.encode(handoverNote)
with open("test.png", "wb") as f:
f.write(codecs.decode(handoverNote, "base64"))
image = Image.open("test.png")
image.thumbnail((500, 500), Image.ANTIALIAS)
image.save("test2.png", quality=95)
But after resizing the image looks unreadable or alstmost unrecognizable like in this example:
This is the original image, I get without resizing.
What am I doing wrong here? Is it because I use PNG?

Python PIL | RGB values are wrong

I am making a steganography program. I got it to work without PIL but it only works with bitmaps, so I did some research and I found and learned general PIL. I converted my algorithm to be compatible with PIL and it looks like it works, but when I go to decode it seems like it pulls numbers out of nowhere. After some debugging I believe there to be a pattern of sorts because it is only a few values off.
To further debug I've created a similar program that makes the image completely red, then reopens it and reads its pixel values, however, I seem to be encountering the same error. The weird thing is that my computer science teacher, who uses Python 2, isn't encountering this error. I was wondering if any more experienced PIL users know why this is and any fixes. I am using Python 3 on Windows 10.
Here is my code (This is the program I made for debugging):
from PIL import Image
def redify(file_name): #Function that turns the whole image red
image = Image.open(file_name)
image = image.convert("RGB")
pixels = list(image.getdata())
fileTypeIndex = 0
for i in range(0,len(file_name)):
if file_name[-i] == ".":
fileTypeIndex = i
break
for x in range(0,len(pixels)):
pixels[x] = 255,0,0
final = Image.new(image.mode,image.size)
final.putdata(pixels)
final.save(file_name[:-fileTypeIndex] + "_redified" + file_name[-fileTypeIndex:])
def readImage(file_name): #Fucntion that opens an image and reads its data
image = Image.open(file_name)
image = image.convert("RGB")
rgbList = list(image.getdata())
print(rgbList) # This returns every pixel as (254,0,0)
# When I set each pixel to 0,255,0 it returns (0,255,1)
# When I set each pixel to 0,0,255 it returns (0,0,254)
# All of these shouldn't be occuring
redify("moon.jpg")
readImage("moon_redified.jpg")

How to increase likeliness of image recognition with pytesseract

I'm trying to convert this list of images I have to text. The images are fairly small but VERY readable (15x160, with only grey text and a white background) I can't seem to get pytesseract to read the image properly. I tried to increase the size with .resize() but it didn't seem to do much at all. Here's some of my code. Anything new I can add to increase my chances? Like I said, I'm VERY surprised that pytesseract is failing me here, it's small but super readable compared to some of the things I've seem it catch.
for dImg in range(0, len(imgList)):
url = imgList[dImg]
local = "img" + str(dImg) + ".jpg"
urllib.request.urlretrieve(url, local)
imgOpen = Image.open(local)
imgOpen.resize((500,500))
imgToString = pytesseract.image_to_string(imgOpen)
newEmail.append(imgToString)
Setting the Page Segmentation Mode (psm) can probably help.
To get all the available psm enter tesseract --help-psm in your terminal.
Then identify the psm corresponding to your need. Lets say you want to treat the image as a single text line, in that case your ImgToString becomes:
imgToString = pytesseract.image_to_string(imgOpen, config = '--psm 7')
Hope this will help you.
You can perform several pre-processing steps in your code.
1) Use the from PIL import Image and use your_img.convert('L'). There are several other settings you can check.
2) A bit advanced method: Use a CNN. There are several pre-trained CNNs you can use. Here you can find a little bit more detailed information: https://www.cs.princeton.edu/courses/archive/fall00/cs426/lectures/sampling/sampling.pdf
tifi

Transparent PNG in PIL turns out not to be transparent

I have been hitting my head against the wall for a while with this, so maybe someone out there can help.
I'm using PIL to open a PNG with transparent background and some random black scribbles, and trying to put it on top of another PNG (with no transparency), then save it to a third file.
It comes out all black at the end, which is irritating, because I didn't tell it to be black.
I've tested this with multiple proposed fixes from other posts. The image opens in RGBA format, and it's still messed up.
Also, this program is supposed to deal with all sorts of file formats, which is why I'm using PIL. Ironic that the first format I tried is all screwy.
Any help would be appreciated. Here's the code:
from PIL import Image
img = Image.open(basefile)
layer = Image.open(layerfile) # this file is the transparent one
print layer.mode # RGBA
img.paste(layer, (xoff, yoff)) # xoff and yoff are 0 in my tests
img.save(outfile)
I think what you want to use is the paste mask argument.
see the docs, (scroll down to paste)
from PIL import Image
img = Image.open(basefile)
layer = Image.open(layerfile) # this file is the transparent one
print layer.mode # RGBA
img.paste(layer, (xoff, yoff), mask=layer)
# the transparancy layer will be used as the mask
img.save(outfile)

Categories

Resources