I've been attempting to work at this for hours but decided to turn to the experts here on stackoverflow.
I'm trying to download an image from a url:
import urllib
originalphoto = urllib.urlretrieve(bundle.obj.url)
#originalphoto is being saved to the tmp directory in Ubuntu
This works and it saves the image in the tmp directory, but I need to modify this image by resizing it to a 250px by 250px image and then save it to a folder on my Desktop: /home/ubuntu/Desktop/resizedshots
The name of the original image is in bundle.obj.url, for example if bundle.obj.url is:
http://photographs.500px.com/kyle/09-09-201315-47-571378756077.jpg the name of the image is "09-09-201315-47-571378756077.jpg"
After the image is resized, I need to save is to this folder as 09-09-201315-47-571378756077small.jpg
As you can see, I'm adding in the word "small" to the end the file name. Once all of this is done, I would like to delete the temporary image file that was downloaded so that it doesn't take up the disk.
Any ideas on how this can be done?
Thanks
This is the definition:
def urlretrieve(url, filename=None, reporthook=None, data=None):
You can set the second argument to something you know and then do
import os
os.remove(something_you_know)
If you do not set the second argument you do this:
import urllib, os
url = 'http://photographs.500px.com/kyle/09-09-201315-47-571378756077.jpg'
file, headers = urllib.urlretrieve(url)
# do something
os.remove(file)
if os.remove does not work you still have the file open.
Related
import pyautogui
button7location = pyautogui.locateOnScreen('picturee.png')
print("finished")
The picture works perfect in a HTML file i created.
Digging into the source code, we are directed from pyautogui to pyscreeze where we can see the following block of code in the location functions.
if isinstance(needleImage, (str, unicode)):
# 'image' is a filename, load the Image object
needleFileObj = open(needleImage, 'rb')
needleImage = Image.open(needleFileObj)
In short, you need the image to be in the same directory as the one you're launching the script from.
Link to source
Context
I have made a simple web app for uploading content to a blog. The front sends AJAX requests (using FormData) to the backend which is Bottle running on Python 3.7. Text content is saved to a MySQL database and images are saved to a folder on the server. Everything works fine.
Image processing and PIL/Pillow
Now, I want to enable processing of uploaded images to standardise them (I need them all resized and/or cropped to 700x400px).
I was hoping to use Pillow for this. My problem is creating a PIL Image object from the file object in Bottle. I cannot initialise a valid Image object.
Code
# AJAX sends request to this route
#post('/update')
def update():
# Form data
title = request.forms.get("title")
body = request.forms.get("body")
image = request.forms.get("image")
author = request.forms.get("author")
# Image upload
file = request.files.get("file")
if file:
extension = file.filename.split(".")[-1]
if extension not in ('png', 'jpg', 'jpeg'):
return {"result" : 0, "message": "File Format Error"}
save_path = "my/save/path"
file.save(save_path)
The problem
This all works as expected, but I cannot create a valid Image object with pillow for processing. I even tried reloading the saved image using the save path but this did not work either.
Other attempts
The code below did not work. It caused an internal server error, though I am having trouble setting up more detailed Python debugging.
path = save_path + "/" + file.filename
image_data = open(path, "rb")
image = Image.open(image_data)
When logged manually, the path is a valid relative URL ("../domain-folder/images") and I have checked that I am definitely importing PIL (Pillow) correctly using PIL.PILLOW_VERSION.
I tried adapting this answer:
image = Image.frombytes('RGBA', (128,128), image_data, 'raw')
However, I won’t know the size until I have created the Image object. I also tried using io:
image = Image.open(io.BytesIO(image_data))
This did not work either. In each case, it is only the line trying to initialise the Image object that causes problems.
Summary
The Bottle documentation says the uploaded file is a file-like object, but I am not having much success in creating an Image object that I can process.
How should I go about this? I do not have a preference about processing before or after saving. I am comfortable with the processing, it is initialising the Image object that is causing the problem.
Edit - Solution
I got this to work by adapting the answer from eatmeimadanish. I had to use a io.BytesIO object to save the file from Bottle, then load it with Pillow from there. After processing, it could be saved in the usual way.
obj = io.BytesIO()
file.save(obj) # This saves the file retrieved by Bottle to the BytesIO object
path = save_path + "/" + file.filename
# Image processing
im = Image.open(obj) # Reopen the object with PIL
im = im.resize((700,400))
im.save(path, optimize=True)
I found this from the Pillow documentation about a different function that may also be of use.
PIL.Image.frombuffer(mode, size, data, decoder_name='raw', *args)
Note that this function decodes pixel data only, not entire images.
If you have an entire image file in a string, wrap it in a BytesIO object, and use open() to load it.
Use StringIO instead.
From PIL import Image
try:
import cStringIO as StringIO
except ImportError:
import StringIO
s = StringIO.StringIO()
#save your in memory file to this instead of a regular file
file = request.files.get("file")
if file:
extension = file.filename.split(".")[-1]
if extension not in ('png', 'jpg', 'jpeg'):
return {"result" : 0, "message": "File Format Error"}
file.save(s)
im = Image.open(s)
im.resize((700,400))
im.save(s, 'png', optimize=True)
s64 = base64.b64encode(s.getvalue())
From what I understand, you're trying to resize the image after it has been saved locally (note that you could try to do the resize before it is saved). If this is what you want to achieve here, you can open the image directly using Pillow, it does the job for you (you do not have to open(path, "rb"):
image = Image.open(path)
image.resize((700,400)).save(path)
I have this script which download all images from a given web url address:
from selenium import webdriver
import urllib
class ChromefoxTest:
def __init__(self,url):
self.url=url
self.uri = []
def chromeTest(self):
# file_name = "C:\Users\Administrator\Downloads\images"
self.driver=webdriver.Chrome()
self.driver.get(self.url)
self.r=self.driver.find_elements_by_tag_name('img')
# output=open(file_name,'w')
for i, v in enumerate(self.r):
src = v.get_attribute("src")
self.uri.append(src)
pos = len(src) - src[::-1].index('/')
print src[pos:]
self.g=urllib.urlretrieve(src, src[pos:])
# output.write(src)
# output.close()
if __name__=='__main__':
FT=ChromefoxTest("http://imgur.com/")
FT.chromeTest()
my question is: how do i make this script to save all the pics to a specific folder location on my windows machine?
You need to specify the path where you want to save the file. This is explained in the documentation for urllib.urlretrieve:
The method is: urllib.urlretrieve(url[, filename[, reporthook[, data]]]).
And the documentation says:
The second argument, if present, specifies the file location to copy to (if absent, the location will be a tempfile with a generated name).
So...
urllib.urlretrieve(src, 'location/on/my/system/foo.png')
Will save the image to the specified folder.
Also, consider reviewing the documentation for os.path. Those functions will help you manipulate file names and paths.
If you use the requests library you can slurp up really big image files (or small ones) efficiently and arrange to store them in a place of your choice in an obvious way.
Use this code and you'll get a nice picture of a beagle dog!
image_url is the link to the remote image.
file_path is where you want to store the image locally. It can include just a file name or a full path, at your option.
chunk_size is the size of the piece of the file to be downloaded with each slurp from the remote site.
length is the actual size of the piece that is written locally. Since I did this interactively I put this in mainly so that I wouldn't have to look at a long vertical stream of 1024s on my screen.
..
>>> import requests
>>> image_url = 'http://maxpixel.freegreatpicture.com/static/photo/1x/Eyes-Dog-Portrait-Animal-Familiar-Domestic-Beagle-2507963.jpg'
>>> file_path = r'c:\scratch\beagle.jpg'
>>> r = requests.get(image_url, stream=True)
>>> with open(file_path, 'wb') as beagle:
... for chunk in r.iter_content(chunk_size=1024):
... length = beagle.write(chunk)
url="https://images.data.gov.sg/api/traffic-images/2016/02/96128cfd-ab9a-4959-972e-a5e74bb149a9.jpg"
I am trying this:
import urllib
url="https://images.data.gov.sg/api/traffic-images/2016/02/96128cfd-ab9a-4959-972e-a5e74bb149a9.jpg"
IMAGE=url.rsplit("/")[-1]
urllib.urlretrieve(url,IMAGE)
Image is downloaded in the destination folder after the execution, but it is corrupt.
"Could not load image"; error pops up.
It might be because the domain that you are trying to reach has restrictions over download policy. Check this one out, hope it helps! https://stackoverflow.com/a/8389368/2539771
import urllib
URL = "https://images-na.ssl-images-amazon.com/images/I/714tx9QbaKL.SL1500.jpg"
urllib.urlretrieve(URL, "sample.png")
from PIL import Image
img = Image.open('/home/sks/sample.png')
img.show()
I want to build an image gallery using Django. Each image is a post, of course. Now, I don't want to be uploading each image independently. I want to zip them all and upload them in the Django admin page and maybe create some kind of a trigger to:
decompressed the zip
read all the images info
store the info in a database, each image in a row
Is this possible with Django? what would be your best way to accomplish this? I'll appreciate any kind of help, I'm very new to Django (like 5 hours new)
Yes, it's possible. Here is a broad outline inspired entirely by how Mezzanine implements this.
First you define a field for accepting the zip file:
class BaseGallery(models.Model):
zip_import = models.FileField(blank=True, upload_to=upload_to("galleries")
Then you have a separate model that is Foreign keyed to your parent model. In the example here the parent model is BaseGallery and the image model is GalleryImage:
class GalleryImage(Orderable):
gallery = models.ForeignKey(Gallery, related_name="images")
file = models.ImageField(upload_to="galleries")
Then in your model's save method, you can extract this zip file and save the individual images:
from django.core.files import ContentFile
from django.conf import settings
from zipfile import ZipFile
def save(self, delete_zip_import=True, *args, **kwargs):
"""
If a zip file is uploaded, extract any images from it and add
them to the gallery, before removing the zip file.
"""
super(BaseGallery, self).save(*args, **kwargs)
if self.zip_import:
zip_file = ZipFile(self.zip_import)
for name in zip_file.namelist():
data = zip_file.read(name)
try:
from PIL import Image
image = Image.open(BytesIO(data))
image.load()
image = Image.open(BytesIO(data))
image.verify()
except ImportError:
pass
except:
continue
name = os.path.split(name)[1]
# You now have an image which you can save
path = os.path.join(settings.MEDIA_ROOT, "galleries",
native(str(name, errors="ignore")))
saved_path = default_storage.save(path, ContentFile(data))
self.images.create(file=saved_path)
if delete_zip_import:
zip_file.close()
self.zip_import.delete(save=True)
Note, the bit where the image is actually saved has been simplified and if you look at the source I have linked to there is a bit more jiggery-pokery required to handle unicode file names etc.
Also note that Mezzanine uses its own FileField which isn't the same as Django's FileField. I have tried to refactor this in the example above.
Here's code to extract files from an uploaded ZIP file:
source
import zipfile
localFile = 'beer.zip'
with zipfile.ZipFile(localFile, 'r') as myzip:
myzip.extractall()
print 'got:', [info.filename for info in myzip.infolist()]
reference
Python zipfile module