PIL: saving file in python - python-2.7

from PIL import Image
in_put = raw_input("provide the image path: ")
pic_im = image.open(in_put)
pic_im.rotate(45).show()
pic_im.save("outputfile.jpg")
I use the above code to open and rotate the user input image.
but every time i have to manually change the name of "outputfile.jpg" while saving the image.
Please guide to save the modified image: for example.
if my original file path is E:\Picture\Nature.jpg
then it should save the modified file in save location with name E:\Picture\Nature_modified.jpg

Perhaps something like this?
output_filename = in_put[0:len(in_put)-4] + "_modified.jpg"
pic_im.save(output_filename)

Related

Can't Upload Image to ImageField through csv file

My Django application:
In my model, I use ImageField to allow the upload of images.
In my csv file I have an image path for an image like this:
C:/Users/blah/DjangoProject/abc/abc/csvs/photos/product_1/product-1_1.jpg
In my csv's view I got:
Product.objects.create(product_name=row[0],
slug=row[0].lower().replace(' ', '-'),
product_description=row[1],
price=row[7],
image_1=ImageFile(open(row[8], 'rb')))
The row[8] contains the image's path.
When I'm going to my csv.html using Django's FileField to upload csv file which contain the image's path and product's info, after uploading the product should be created in my database which image should also be uploaded to a filesystem - not storing in database. Instead, I got this error:
OSError at /csvs/
[WinError 123] The filename, directory name, or volume label syntax is incorrect: 'C:\Users\blah\DjangoProject\abc\abc\media\photos\products\C:'
When I removed the image_1 row in Product.objects.create(), the product was uploaded and added to the database successfully. If I restore the image_1 row in the object creation, I got the same error again.
Does anyone know why?
Try this:
Product.objects.create(product_name=row[0],
slug=row[0].lower().replace(' ', '-'),
product_description=row[1],
price=row[7],
image_1=row[8])
Or
from django.core.files import File;
Product.objects.create(.....,image_1=File(file=open((row[8], 'rb')))
I think you just have to provide the path of the image to be uploaded.
And in your model you have the ImagePath with and upload_to like this:
image_1 = models.ImageField(upload_to="media/styles/")

Programmatically saving image to Django ImageField returning 404 in production

I have a Django app where users can upload images and can have a processed version of the images if they want. and the processing function returns the path, so my approach was
model2.processed_image = processingfunction( model1.uploaded_image.path)
and as the processing function returns path here's how it looks in my admin view
not like the normally uploaded images
In my machine it worked correctly and I always get a 404 error for the processed ones while the normally uploaded is shown correctly when I try to change the url of the processed from
myurl.com/media/home/ubuntu/Eyelizer/media/path/to/the/image
to
myurl.com/media/path/to/the/image
so how can I fix this ? is there a better approach to saving the images manually to the database ?
I have the same function but returns a Pil.image.image object and I've tried many methods to save it in a model but I didn't know how so I've made the function return a file path.
I think the problem is from nginx where I define the media path.
should/can I override the url attribute of the processedimage?
making something like
model.processed_image.url = media/somefolder/filename
Instead of using the PIL Image directly, create a django.core.files.File.
Example:
from io import BytesIO
from django.core.files import File
img_io = BytesIO() # create a BytesIO object to temporarily save the file in memory
img = processingfunction( model1.uploaded_image.path)
img.save(img_io, 'PNG') # save the PIL image to the BytesIO object
img_file = File(thumb_io, name='some-name.png') # create the File object
# you can use the `name` from `model1.uploaded_image` and use
# that above
# finally, pass the image file to your model field
model2.processed_image = img_file
To avoid repetition of this code, it would be a good idea to keep this code in processingfunction and return the File object directly from there.
My approach is a bit different from #Xyres's, I thought xyres's would make a duplicate of the existing image and create a new one and when I tried overriding the URL attribute it returned an error of
can't set the attribute
but when I saw this question and this ticket I tried making this and it worked
model2.processed_image = processingfunction(model1.uploaded_image.path)
full_path = model2.processed_image.path
model2.processed_image.name = full_path.split('media')[1]
so that explicitly making the URL media/path/to/image and cut out all of the unneeded parts like home/ubuntu and stuff

specify directory where to store uploaded image

I have a script to save images from request.FILES but I don't know how to specify the directory I want to store it.
photos = request.FILES.getlist('file')
for p in photos:
img = Image.open(p)
img.save(p)
In this case how can I specify the folder I want to store the files? like C:\\upload\\photos\\
EDIT: Alrady try to concatenate the directory path like this:
photos = request.FILES.getlist('file')
for p in photos:
img = Image.open(p)
img.save('C:\\upload\\photos\\'+p)
And gives me this error:
cannot concatenate 'str' and 'TemporaryUploadedFile' objects
I am assuming you use the Pillow module.
If so, construct a full path (path prefix + filename) and pass it to the save function.
Documentation

How to process an uploaded KML file in GeoDjango

I wrote a cmd line routine to import a kml file into a geoDjango application, which works fine when you feed it a locally saved KML file path (using the datasource object).
Now I am writing a web file upload dialog, to achieve the same thing. This is the beginning of the code that I have, problem is, that the GDAL DataSource object does not seem to understand Djangos UploadedFile format. It is held in memory and not a file path as expected.
What would be the best strategy to convert the UploadedFile to a normal file, and access this through a path? I dont want to keep the file after processing.
def createFeatureSet(request):
if request.method == 'POST':
inMemoryFile = request.FILES['myfile']
name = inMemoryFile.name
POSTGIS_SRID = 900913
ds = DataSource(inMemoryFile) #This line doesnt work!!!
for layer in ds:
if layer.geom_type in (OGRGeomType('Point'), OGRGeomType('Point25D'), OGRGeomType('MultiPoint'), OGRGeomType('MultiPoint25D')):
layerGeomType = OGRGeomType('MultiPoint').django
elif layer.geom_type in (OGRGeomType('LineString'),OGRGeomType('LineString25D'), OGRGeomType('MultiLineString'), OGRGeomType('MultiLineString25D')):
layerGeomType = OGRGeomType('MultiLineString').django
elif layer.geom_type in (OGRGeomType('Polygon'), OGRGeomType('Polygon25D'), OGRGeomType('MultiPolygon'), OGRGeomType('MultiPolygon25D')):
layerGeomType = OGRGeomType('MultiPolygon').django
DataSource is a wrapper around GDAL's C API and needs an actual file. You'll need to write your upload somewhere on the disk, for insance using a tempfile. Then you can pass the file to DataSource.
Here is a suggested solution using a tempfile. I put the processing code in its own function which is now called.
f = request.FILES['myfile']
temp = tempfile.NamedTemporaryFile(delete=False)
temp.write(f.read())
temp.close()
createFeatureSet(temp.name, source_SRID= 900913)

Saving animated GIFs using PIL (image saved does not animate)

I have Apache2 + PIL + Django + X-sendfile. My problem is that when I save an animated GIF, it won't "animate" when I output through the browser.
Here is my code to display the image located outside the public accessible directory.
def raw(request,uuid):
target = str(uuid).split('.')[:-1][0]
image = Uploads.objects.get(uuid=target)
path = image.path
filepath = os.path.join(path,"%s.%s" % (image.uuid,image.ext))
response = HttpResponse(mimetype=mimetypes.guess_type(filepath))
response['Content-Disposition']='filename="%s"'\
%smart_str(image.filename)
response["X-Sendfile"] = filepath
response['Content-length'] = os.stat(filepath).st_size
return response
UPDATE
It turns out that it works. My problem is when I try to upload an image via URL. It probably doesn't save the entire GIF?
def handle_url_file(request):
"""
Open a file from a URL.
Split the file to get the filename and extension.
Generate a random uuid using rand1()
Then save the file.
Return the UUID when successful.
"""
try:
file = urllib.urlopen(request.POST['url'])
randname = rand1(settings.RANDOM_ID_LENGTH)
newfilename = request.POST['url'].split('/')[-1]
ext = str(newfilename.split('.')[-1]).lower()
im = cStringIO.StringIO(file.read()) # constructs a StringIO holding the image
img = Image.open(im)
filehash = checkhash(im)
image = Uploads.objects.get(filehash=filehash)
uuid = image.uuid
return "%s" % (uuid)
except Uploads.DoesNotExist:
img.save(os.path.join(settings.UPLOAD_DIRECTORY,(("%s.%s")%(randname,ext))))
del img
filesize = os.stat(os.path.join(settings.UPLOAD_DIRECTORY,(("%s.%s")%(randname,ext)))).st_size
upload = Uploads(
ip = request.META['REMOTE_ADDR'],
filename = newfilename,
uuid = randname,
ext = ext,
path = settings.UPLOAD_DIRECTORY,
views = 1,
bandwidth = filesize,
source = request.POST['url'],
size = filesize,
filehash = filehash,
)
upload.save()
#return uuid
return "%s" % (upload.uuid)
except IOError, e:
raise e
Any ideas?
Thanks!
Wenbert
Where does that Image class come from and what does Image.open do?
My guess is that it does some sanitizing of the image data (which is a good thing), but does only save the first frame of the Gif.
Edit:
I'm convinced this is an issue with PIL. The PIL documentation on GIF says:
PIL reads GIF87a and GIF89a versions of the GIF file format. The library writes run-length encoded GIF87a files.
To verify, you can write the contents of im directly to disk and compare with the source image.
The problem is saving a PIL-opened version of the image. When you save it out via PIL, it will only save the first frame.
However, there's an easy workaround: Make a temp copy of the file, open that with PIL, and then if you detect that it's an animated GIF, then just save the original file, not the PIL-opened version.
If you save the original animated GIF file and then stream it back into your HTTP response, it will come through animated to the browser.
Example code to detect if your PIL object is an animated GIF:
def image_is_animated_gif(image):
# verify image format
if image.format.lower() != 'gif':
return False
# verify GIF is animated by attempting to seek beyond the initial frame
try:
image.seek(1)
except EOFError:
return False
else:
return True