I am writing a script which will get an image from a link. Then the image will be resized using the PIL module and the uploaded to Imgur using pyimgur. I dont want to save the image on disk, instead manipulate the image in memory and then upload it from memory to Imgur.
The Script:
from pyimgur import Imgur
import cStringIO
import requests
from PIL import Image
LINK = "http://pngimg.com/upload/cat_PNG106.png"
CLIENT_ID = '29619ae5d125ae6'
im = Imgur(CLIENT_ID)
def _upload_image(img, title):
uploaded_image = im.upload_image(img, title=title)
return uploaded_image.link
def _resize_image(width, height, link):
#Retrieve our source image from a URL
fp = requests.get(link)
#Load the URL data into an image
img = cStringIO.StringIO(fp.content)
im = Image.open(img)
#Resize the image
im2 = im.resize((width, height), Image.NEAREST)
#saving the image into a cStringIO object to avoid writing to disk
out_im2 = cStringIO.StringIO()
im2.save(out_im2, 'png')
return out_im2.getvalue()
When I run this script I get this error: TypeError: file() argument 1 must be encoded string without NULL bytes, not str
Anyone has a solution in mind?
It looks like the same problem as this, and the solution is to use StringIO.
A common tip for searching such issues is to search using the generic part of the error message/string.
Related
I want to convert Image file to Bytearray. I extracted image from pdf file with minecart lib, but I cant find a way to convert it to bytearray. This is my code:
import minecart
from PIL import Image
import io
pdffile = open('sample6.pdf', 'rb')
doc = minecart.Document(pdffile)
for page in doc.iter_pages():
print(page)
img = page.images[0].as_pil()
print(img) # <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1641x2320 at 0x7FBDF02E6A00>
print(type(img)) # <class 'PIL.JpegImagePlugin.JpegImageFile'>
I have tried to use bytearray(img) but It does not work.
Do you have solution for this (solution that does not consume to much time)?
Create io.BytesIO buffer and write to it using PIL.Image.save. Set appropriate quality and other parameters as per requirement.
import io
from PIL import Image
def convert_pil_image_to_byte_array(img):
img_byte_array = io.BytesIO()
img.save(img_byte_array, format='JPEG', subsampling=0, quality=100)
img_byte_array = img_byte_array.getvalue()
return img_byte_array
References:
Why is the quality of JPEG images produced by PIL so poor?
All the examples I encounter in the internet is loading the image from url (either locally or in the web). What I want is to draw the image directly to the pdf from raw bytes.
UPDATE:
#georgexsh Here is my code based on my understanding of your comment below:
def PDF_view(request):
response = HttpResponse(content_type='application/pdf')
...
page = canvas.Canvas(response, pagesize=A4)
page.setTitle("Sample PDF")
image = StringIO(raw_image_bytes) # raw_image_bytes is from external source
image.seek(0)
page.drawImage(image, 100, 100 )
filename = 'document.pdf'
page.showPage()
page.save()
return response
from report lab Image object source code, filelike obj is acceptable, so you could wrap image data with StringIO/io.BytesIO, pass it as filename.
updated:
as you're using drawImage method, it needs a ImageReader obj:
from reportlab.lib.utils import ImageReader
import io
image = ImageReader(io.BytesIO(raw_image_bytes))
page.drawImage(image, ...)
When I try to resize (thumbnail) an image using PIL, the exif data is lost.
What do I have to do preserve exif data in the thumbnail image? When I searched for the same, got some links but none seem to be working.
from PIL import Image
import StringIO
file_path = '/home/me/img/a.JPG'
im = Image.open( file_path)
THUMB_SIZES = [(512, 512)]
for thumbnail_size in THUMB_SIZES:
im.thumbnail( thumbnail_size, Image.ANTIALIAS)
thumbnail_buf_string = StringIO.StringIO()
im.save('512_' + "a", "JPEG")
The orginal image has exif data, but image im(512_a.JPEG) doesn't.
I read throught some of the source code and found a way to make sure that the exif data is saved with the thumbnail.
When you open a jpg file in PIL, the Image object has an info attribute which is a dictionary. One of the keys is called exif and it has a value which is a byte string - the raw exif data from the image. You can pass this byte string to the save method and it should write the exif data to the new jpg file:
from PIL import Image
size = (512, 512)
im = Image.open('P4072956.jpg')
im.thumbnail(size, Image.ANTIALIAS)
exif = im.info['exif']
im.save('P4072956_thumb.jpg', exif=exif)
To get a human-readable version of the exif data you can do the following:
from PIL import Image
from PIL.ExifTags import TAGS
im = Image.open('P4072956.jpg')
for k, v in im._getexif().items():
print TAGS.get(k, k), v
In my project, i met the same issue with you. After searching Google, I found piexif library. It help to Pilow save exif data to thumbnails.
You can use the source code below:
from PIL import Image
import piexif
import StringIO
file_path = '/home/me/img/a.JPG'
im = Image.open( file_path)
# load exif data
exif_dict = piexif.load(im.info["exif"])
exif_bytes = piexif.dump(exif_dict)
THUMB_SIZES = [(512, 512)]
for thumbnail_size in THUMB_SIZES:
im.thumbnail( thumbnail_size, Image.ANTIALIAS)
thumbnail_buf_string = StringIO.StringIO()
# save thumbnail with exif data
im.save('512_' + "a", "JPEG", exif=exif_bytes)
Note: I am using python 3.4 and ubuntu 14.04
import pyexiv2
from PIL import Image
file_path = '/home/../img/a.JPG'
metadata = pyexiv2.ImageMetadata(file_path)
metadata.read()
thumb = metadata.exif_thumbnail
thumb.set_from_file(file_path)
thumb.write_to_file('512_' + "a")
thumb.erase()
metadata.write()
Now I open the image using (Patch Image Inspector) , I can see the exif data
Is it possible to generate an in-memory image for testing purposes?
Here is my current code:
def test_issue_add_post(self):
url = reverse('issues_issue_add')
image = 'cover.jpg'
data = {
'title': 'Flying Cars',
'cover': image,
}
response = self.client.post(url, data)
self.assertEqual(response.status_code, 302)
To generate a 200x200 test image of solid red:
import Image
size = (200,200)
color = (255,0,0,0)
img = Image.new("RGBA",size,color)
To convert it to a file-like object, then:
import StringIO
f = StringIO.StringIO(img.tostring())
http://effbot.org/imagingbook/image.htm
Jason's accepted answer is not working for me in Django 1.5
Assuming the generated file is to be saved to a model's ImageField from within a unit test, I needed to take it a step further by creating a ContentFile to get it to work:
from PIL import Image
from StringIO import StringIO
from django.core.files.base import ContentFile
image_file = StringIO()
image = Image.new('RGBA', size=(50,50), color=(256,0,0))
image.save(image_file, 'png')
image_file.seek(0)
django_friendly_file = ContentFile(image_file.read(), 'test.png')
So if client.post is expecting a file like object, you could create an example image (if you want to visually check result after tests) or just make a 1px png and read it out from console
open('1px.png', 'rb').read()
which in my case dumped out
image_data = '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\tpHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdb\x0c\x17\x020;\xd1\xda\xcf\xd2\x00\x00\x00\x0cIDAT\x08\xd7c\xf8\xff\xff?\x00\x05\xfe\x02\xfe\xdc\xccY\xe7\x00\x00\x00\x00IEND\xaeB`\x82'
then you can use StringIO which acts as a file like object, so above, image would be
from StringIO import StringIO
def test_issue_add_post(self):
...
image = StringIO(image_data)
...
and you'll have a file like object with the image data
In Python 3
from io import BytesIO
from PIL import Image
image = Image.new('RGBA', size=(50, 50), color=(155, 0, 0))
file = BytesIO(image.tobytes())
file.name = 'test.png'
file.seek(0)
# + + + django_friendly_file = ContentFile(file.read(), 'test.png') # year 2019, django 2.2.1 -works
Thanks to help from Eduardo, I was able to get a working solution.
from StringIO import StringIO
import Image
file = StringIO()
image = Image.new("RGBA", size=(50,50), color=(256,0,0))
image.save(file, 'png')
file.name = 'test.png'
file.seek(0)
Have you used the PIL module? It lets you manipulate images - and should allow creation as well.
In fact, here's a blog entry with some code that does it
http://bradmontgomery.blogspot.com/2008/07/django-generating-image-with-pil.html
Dont know whether you test machine has an internet connection, but you could also pull down random images from google to vary the test data?
I am writing python code to take an image from the web and calculate the standard deviation, ... and do other image processing with it. I have the following code:
from scipy import ndimage
from urllib2 import urlopen
from urllib import urlretrieve
import urllib2
import Image
import ImageFilter
def imagesd(imagelist):
for imageurl in imagelist:
opener1 = urllib2.build_opener()
page1 = opener1.open(imageurl)
im = page1.read()
#localfile = urlretrieve(
#img = Image.fromstring("RGBA", (1,1), page1.read())
#img = list(im.getdata())
# page1.read()
print img
#standard_deviation(p
Now I keep going back and forth because I am not sure how to take the image directly from the web, without saving it to disk, and passing it to the standard deviation function.
Any hints/help would be greatly appreciated.
Thanks.
PIL (Python Imaging Library) methods "fromstring" and "frombuffer" expect the image data in a raw, uncompacted, format.
When you do page1.read() you get the binary file data. In order to have PIL understanding it, you have to make this data mimick a file, and pass it to the "Image.open" method, which understands the file format as it is read from the web (i.e., the .jpg, gif, or .png data instead of raw pixel values)
Try something like this:
from cStringIO import StringIO
(...)
data = StringIO(page1.read())
img = Image.open(data)