Pillow - GIF File Size - python

The following program uses the Pillow package (3.4.2) to create a very simple GIF file. The file size is 11.2 KB.
from PIL import Image, ImageDraw
img = Image.new('P', (400, 300))
draw = ImageDraw.Draw(img)
draw.rectangle((0, 0, img.width, img.height), fill='black')
draw.line((10, 10, img.width-10, img.height-10), fill='cyan', width=5)
del draw
img.save('Test.gif')
If I open this file in Microsoft Paint and Save As with a different name, the file size becomes 1.90 KB.
Why such a big difference? Can I make Pillow use whatever format the Paint uses to get the same small size?

If your not making a animated GIF you can change img.save('Test.gif') to img.save('Test.png') the file size will then become 1.52KB.

You could use jpeg and optimise parameters as in here
img.save('Test.jpg',optimize=True,quality=95)

Related

Python - Render a Slanted Font

This question is inline with the answer in my previous question in Stackoverflow.
I am creating a program that converts a text to image. I want to render it in using the font OCR A. But since OCR A font, has no corresponding font file for italics, I have to do the slanting of the upright font manually.
Upright Font
Slanted Font
Below is my initial code :
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import numpy as np
#Returns the text size in terms of width and height.
def getSize(txt, font):
testImg = Image.new('RGB', (1, 1))
testDraw = ImageDraw.Draw(testImg)
return testDraw.textsize(txt, font)
text = 'CNN Font Recognition Model'
font_size = 12
font = ImageFont.truetype('ocra.ttf' , font_size)
#ocra.ttf is a font file for OCR A Regular font (I have to render it slanted)
width, height = getSize(text, font)
#Creates an image with white background of constant size.
img = Image.new('RGB',(width, height), 'white')
d = ImageDraw.Draw(img)
d.text((0,0), text, fill='black', font=font)
img.save('slanted_ocr_a.png')
How do I manually slant the upright OCR A font? Thanks.
You can download a sample ocra.ttf file here.
This answer to a similar question is probably the easiest way, although it is not exactly what you want to do. Basically you render the upright font into an image then slant (shear) the entire image using PIL's Image.transform method.
To accomplish exactly what you are asking (slanting the font before imaging it) is possible, but would require a lot of work overriding PIL's truetype scheme to have the underlying font engine (FreeType) perform the slant transformation at the font level. PIL's truetype interface simply doesn't have a way to express a transform, so you'd have to override/patch it to pass that all the way down to FreeType where the font is set up.
Another option might be to skip PIL's truetype scheme and use a Python font-rendering library that allows you to set the font transform directly, then scrape the pixel data from that into your PIL Image. One such library is freetype-py.

Transparet pixels are being pasted as black in PIL

I paste an image with transparent pixels, but they are black in the final image
img = Image.new('RGBA', (100, 100), "white")
arbol16 = Image.open("arbol16.png")
img.paste(arbol16,( 0, 0, 16, 16))
img.show()
arbol16.png image file:
The paste method does not take into account the alpha of the image it's pasting; you need to add a mask parameter to control that. If the image you're pasting is RGBA you can just pass it twice.
arbol16 = arbol16.convert("RGBA")
img.paste(arbol16, (0, 0, 16, 16), arbol16)
I think you're (understandably) being confused by what the img.show() is displaying — which I believe is wrong (and may in fact be a bug). On my Windows system a temporary .BMP image is displayed, and it looks like the transparent pixels are black.
However if you add a line like img.save('arbol16_mod.png') at the end and then view that image file by manually opening it in some image file viewing program, such as Paint, Windows Photo Viewer, or Photoshop, the result is correct.

ImageOps.fit() with transparent parts in ICO images

I have a source file image.ico of any size and want to create a thumbnail. This is the code i am using right now:
converted_file = cStringIO.StringIO()
thumb = ImageOps.fit(image, (width, height), Image.ANTIALIAS)
thumb.save(converted_file, format='png')
I chose png as extension because PIL does not support ico files which could be the culprit. It works beside the fact that transparency is not applied. Parts with alpha=0 are rendered black instead of being transparent. How can i fix this behavior?
/edit
I also tried (see this answer):
converted_file = cStringIO.StringIO()
thumb = ImageOps.fit(image, (width, height), Image.ANTIALIAS)
background = Image.new('RGBA', (width, height), (255, 255, 255, 0))
background.paste(thumb, box = (0, 0, width, height))
background.save(converted_file, format='png')
Same effect.
The Problem is indeed that PIL does not know how to exactly read ICO files. There are two possibilities how to fix this:
Add a plugin to PIL that registers the ICO format
Use Pillow, a fork of PIL that is more frequently updated
I chose to use Pillow which is also Python 3 compatible and has some more goodies.
1. PIL Plugin
Save the Win32IconImagePlugin somewhere in your project. After importing the PIL Image class, import the plugin to register ICO support:
from PIL import Image
import Win32IconImagePlugin
There you go, now you can use the right format:
thumb.save(converted_file, format='ico')
2. Pillow
Pillow has builtin support for ICO images.
Just remove pil and install pillow:
pip uninstall pil
pip install pillow
Be sure to change all global pil imports:
import Image, ImageOps
to
from PIL import Image, ImageOps
There you go, now you can use the right format:
thumb.save(converted_file, format='ico')

python imaging library save function

I have just done some image processing using the python image library (PIL) and I can't get the save function to work. the whole code works fine but it just wont save the resulting image. The code is below:
im=Image.new("rgb",(200,10),"#ddd")
draw=Image.draw.draw(im)
draw.text((10,10),"run away",fill="red")
im.save("g.jpeg")
Saving gives an error as unknown extension and even removing the dot doesn't help.
Use .jpg:
im.save("g.jpg")
The image library determines what encoder to use by the extension, but in certain versions of PIL the JPEG encoder do not register the .jpeg extension, only .jpg.
Another possibility is that your PIL installation doesn't support JPEG at all; try saving the image as a PNG, for example.
Replace
draw=Image.draw.draw(im)
with
draw = ImageDraw.Draw(im)
and make sure the height of the new image is tall enough to accomodate the text.
import Image
import ImageDraw
im = Image.new("RGB", (200, 30), "#ddd")
draw = ImageDraw.Draw(im)
draw.text((10, 10), "run away", fill="red")
im.save("g.jpeg")
yields
please save with .jpg extention eg:
im.save("g.jpg")

python: reportlab, how to remove black borders from image

I am trying to generate a pdf file, using python reportlab, but is seems image is displayed with strange black border in pdf.
Here is the code:
# Standalone script to generate pdf lessons
from reportlab.pdfgen import canvas
def hello(c):
c.drawImage("./media/files/1.png", 0, 600, 350, 350)
c = canvas.Canvas("hello.pdf")
hello(c)
c.showPage()
c.save()
The image I am trying to add is here
Can somebody advice why the black line on the left have appeared, and how to fix it?
The problem isn't with a border, rather your chessboard has transparent pixels on the right and bottom sides, and reportlab isn't recognizing the alpha channel and is painting the transparent section as black:
Using mask='auto' tells drawImage to use the alpha channel in your PNG, so the background shows through:
c.drawImage("./media/files/1.png", 0, 600, 350, 350, mask='auto')

Categories

Resources