upload PIL image to azure blob - python

I have a Django app that allows users to upload images that are saved in Azure blob storage. When a user uploads an image, I want to both store the original image and create a thumbnail (100x100).
Currently, the site uploads the original from request.FILES perfectly, but for creating the thumbnail I can't figure out how to upload to Azure without first saving the edited image to a holding folder, reading that saved image, and then deleting it. That doesn't seem like the most efficient way to save a thumbnail.
Here is the current upload script:
# original upload
f = request.FILES['pic']
extension = f.name.split('.')[-1]
new_name, thumb_name = rename_file(extension)
upload(blob_service, 'pic-container', new_name, f)
# create thumbnail
f.seek(0)
im = Image.open(f)
width = im.size[0]
height = im.size[1]
if width > height:
left_crop = (width - height)/2
right_crop = (width + height)/2
cropped = im.crop((left_crop, 0, right_crop, height))
else:
upper_crop = (height - width)/2
lower_crop = (height + width)/2
cropped = im.crop((0, upper_crop, width, lower_crop))
std_size = 100, 100
cropped.thumbnail(std_size, Image.ANTIALIAS)
# save to holder, upload thumbnail, then delete from holder
cropped.save('path/to/holder/' + thumb_name)
upload(blob_service, 'media-pic', thumb_name, open('path/to/holder/' + thumb_name))
os.unlink('path/to/holder/' + thumb_name)
# upload script slightly modified from http://www.windowsazure.com/en-us/documentation/articles/storage-python-how-to-use-blob-storage/#_large-blobs
def upload(blob_service, container_name, blob_name, file_path):
blob_service.put_blob(container_name, blob_name, '', 'BlockBlob')
block_ids = []
index = 0
with file_path as f:
while True:
data = f.read(chunk_size)
if data:
length = len(data)
block_id = base64.b64encode(str(index))
blob_service.put_block(container_name, blob_name, data, block_id)
block_ids.append(block_id)
index += 1
else:
break
blob_service.put_block_list(container_name, blob_name, block_ids)
If I don't save the thumbnail first and just run upload(blob_service, 'pic-container', thumb_name, cropped) I get a pretty uninformative error that just says __exit__ and points to the line with file_path as f in def upload.
Is there any way to upload the file directly from cropped without having to save the file, either by revising the upload function or by changing cropped somehow.

Related

Python Script in Cloud Function downloading files

I have a Python Script in Google Cloud Functions.
One of the parts of the script gets a list of URL's (in String format), which I'm currently storing as it is.
The problem I'm having is that in the local version of that script (the one I run on my computer) I download the files of those URL's into a local folder as I need to store those files in Firebase Storage but with a lower resolution and size.
Here is the code I'm using to download the images:
Here I run the full thing getting the urls, and later changing those URL's into jpg's.
#Images Section
imagesRaw = []
imagesSection = soup.find('div', {'class': 'src__GalleryContainer-sc-bdjcm0-7'})
imagesInfo = imagesSection.find_all('img', {'class': 'gallery-image__StyledImg-sc-jtk816-0'})
image1 = imagesInfo[0].get('src')
for image in imagesInfo:
img = image.get('data-flickity-lazyload-src')
imagesRaw.append(img)
imagesRaw.pop(0)
imagesRaw.insert(0, image1)
images = imagesRaw[:12]
imageFile = []
#Here we will store the images in local file
for image in images:
#First we change the ending from webp to jpg
newURL = image[:-4] + 'jpg'
print(newURL)
name = find_between(newURL, "_img", "/origin.jpg")
if name == "":
name = random_name()
print(name)
#Here the function to download the image
try:
dl_jpg(newURL, 'images/', name)
except:
break
#Here we Optimize the image to size 500 x 394 pixels
# And get the location for the new image
try:
path = optimizeImage(name)
except:
break
# We append the path to the Array of paths
imageFile.append(path)
This is the function I use to download the Image from the URL:
def dl_jpg(url, file_path, file_name):
full_path = file_path + file_name + '.jpg'
path = urllib.request.urlretrieve(url, full_path)
This is the function where I optimize te Image to my needs:
def optimizeImage(name) -> str:
foo = Image.open(os.path.join('images/', name + '.jpg'))
foo = foo.resize((525,394),Image.ANTIALIAS)
foo.save('images/' + name + '.jpg',optimize=True,quality=50)
print('Optimized Image: ' + name)
return 'images/' + name + '.jpg'
And Finally I get the images stored in Firebase Storage like this:
photos = []
for image in listing.photos:
fullpath = image #find_between(image, 'scrapping/', '.jpg') + '.jpg'
filename = fullpath[7:]
path = fullpath[0:6]
imagePath = path + '/' + filename
bucket = storage.bucket()
blob = bucket.blob('ListingImages/' + ref.id + '/' + filename)
blob.upload_from_filename(imagePath)
blob.make_public()
photos.append(blob.public_url)
The problem that I see is that I do have a folder called Images next to my Script in my local, however in Cloud Functions I don't know how to have something similar that can help me to just hold those files while it optimizes and uploads and then just delete the files.
Any ideas?

Video created in OpenCv does open, but shows nothing

I've been trying to merge some pictures to create a video, all of this using Opencv. But, the problem here is that Opencv does create the .avi file and it opens, using VLC Media Player, but when I'm trying to watch the video created, it shows nothing and doesn't show how long does the video last. However, the file size is around 6kb. There are 18 images and they have an average size os 252kb. I think that's too weird and incoherent.
Here's a look at my code:
import cv2
import os
frameSize = (500, 500)
with os.scandir('Taylor') as Taylor_Images:
for image in Taylor_Images:
print(image.name)
with os.scandir('Taylor_5') as Taylor5_Images:
for image in Taylor5_Images:
print(image.name)
image_Taylor = []
image_Taylor_5 = []
ext_2 = '.png'
adding = '_5'
path_2 = 'Taylor_5/'
ext = '.png'
path = 'Taylor/'
for i in range(1,10):
img_name = str(i) + ext
img = path + str(i) + ext
image_Taylor.append(img)
img_name_2 = str(i) + ext_2
img_2 = path_2 + str(i) + adding + ext_2
image_Taylor_5.append(img_2)
out = cv2.VideoWriter('output_video2.avi',cv2.VideoWriter_fourcc(*'DIVX'), 60, frameSize)
for i in range(0,9):
img = cv2.imread(image_Taylor[i])
out.write(img)
img_2 = cv2.imread(image_Taylor_5[i])
out.write(img_2)
out.release()
Update 1
As Vatsal suggested, I checked all the sizes of the images and I found that some of them didn't have the same size(Width,Height), so I resized them for having the same size(400,800).
With regard to what Tim said, the images do have that file size, I attach a picture of what I did according to your suggestion of making their file size a multiple of 4.
Checking the size of the images
This is the kind of pictures I'm using
However, the video generated from the script still has a size of 6kB.

Python WAND resize poor quality

I have the following code to extract PDF to JPG. I had to resize the img because of the large size, I loose the PDF original format (A4, A3 etc..) :
with Img(filename=pdfName, resolution=self.resolution) as document:
reader = PyPDF2.PdfFileReader(pdfName.replace('[0]', ''))
for page_number, page in enumerate(document.sequence):
pdfSize = reader.getPage(page_number).mediaBox
width = pdfSize[2]
height = pdfSize[3]
with Img(page, resolution=self.resolution) as img:
# Do not resize first page, which used to find useful informations
if not get_first_page:
img.resize(int(width), int(height))
img.compression_quality = self.compressionQuality
img.background_color = Color("white")
img.alpha_channel = 'remove'
if get_first_page:
filename = output
else:
filename = tmpPath + '/' + 'tmp-' + str(page_number) + '.jpg'
img.save(filename=filename)
So, for each page, I read the PDF size, and resize the output made with wand. But my problem is the quality of jpg, which is really poor...
My resolution is 300 (I try with upper value, without succes) and compressionQuality is 100
Any ideas ?
Thanks

Resize multiple images in a folder (Python)

I already saw the examples suggested but some of them don't work.
So, I have this code which seems to work fine for one image:
im = Image.open('C:\\Users\\User\\Desktop\\Images\\2.jpg') # image extension *.png,*.jpg
new_width = 1200
new_height = 750
im = im.resize((new_width, new_height), Image.ANTIALIAS)
im.save('C:\\Users\\User\\Desktop\\resized.tif') # .jpg is deprecated and raise error....
How can I iterate it and resize more than one image ? Aspect ration need to be maintained.
Thank you
# Resize all images in a directory to half the size.
#
# Save on a new file with the same name but with "small_" prefix
# on high quality jpeg format.
#
# If the script is in /images/ and the files are in /images/2012-1-1-pics
# call with: python resize.py 2012-1-1-pics
import Image
import os
import sys
directory = sys.argv[1]
for file_name in os.listdir(directory):
print("Processing %s" % file_name)
image = Image.open(os.path.join(directory, file_name))
x,y = image.size
new_dimensions = (x/2, y/2) #dimension set here
output = image.resize(new_dimensions, Image.ANTIALIAS)
output_file_name = os.path.join(directory, "small_" + file_name)
output.save(output_file_name, "JPEG", quality = 95)
print("All done")
Where it says
new_dimensions = (x/2, y/2)
You can set any dimension value you want
for example, if you want 300x300, then change the code like the code line below
new_dimensions = (300, 300)
I assume that you want to iterate over images in a specific folder.
You can do this:
import os
from datetime import datetime
for image_file_name in os.listdir('C:\\Users\\User\\Desktop\\Images\\'):
if image_file_name.endswith(".tif"):
now = datetime.now().strftime('%Y%m%d-%H%M%S-%f')
im = Image.open('C:\\Users\\User\\Desktop\\Images\\'+image_file_name)
new_width = 1282
new_height = 797
im = im.resize((new_width, new_height), Image.ANTIALIAS)
im.save('C:\\Users\\User\\Desktop\\test_resize\\resized' + now + '.tif')
datetime.now() is just added to make the image names unique. It is just a hack that came to my mind first. You can do something else. This is needed in order not to override each other.
I assume that you have a list of images in some folder and you to resize all of them
from PIL import Image
import os
source_folder = 'path/to/where/your/images/are/located/'
destination_folder = 'path/to/where/you/want/to/save/your/images/after/resizing/'
directory = os.listdir(source_folder)
for item in directory:
img = Image.open(source_folder + item)
imgResize = img.resize((new_image_width, new_image_height), Image.ANTIALIAS)
imgResize.save(destination_folder + item[:-4] +'.tif', quality = 90)

cv2.resize() error: saves the same picture with different names

I am new in programming and trying to make an image resizer. I wanted to make possibility to write custom prefix by the user before in the filenames. Sizes are also customable.
The cv2.imshow() works fine, but cv2.resize() does not. If I check it with imshow, it shows only one picture despite of the for loop, and then cv2.imwrite saves only one picture with the names all the selected pictures.
The lists seems to be OK.
I hope I am clear, the code:
def openfiles():
global picture_original
global file_path
global f
# Valid filetypes
file_types=[("Jpeg files","*.jpg"),("PNG files","*.png"),("BMP files","*.bmp"),("all files","*.*")]
window.filenames = filedialog.askopenfilenames(initialdir = "/",title = "Select file",filetypes = (file_types)) # TUPLE of filepath/filenames
#f = []
# Creating a list from the tuple
for pics in window.filenames:
f.append(pics)
f = [picture.replace('/', "\\") for picture in f]
try:
for picture in f:
picture_original = cv2.imread(picture, 1)
#cv2.imshow("Preview", picture_original)
#cv2.waitKey(1)
except:
msgbox_openerror() # Error opening the file
# Getting the filepath only from the list "f":
file_path = f[0].rsplit("\\",1)[0]
view_list()
def save_command():
"""
function to save the resized pictures
"""
global picture_resized
global prefix
prefix = "Resized_"
lst_filename = []
lst_renamed = []
for i in f:
#print(f)
path,filename = os.path.split(i) # path - only filepath | filename - only filename with extension
lst_filename.append(prefix+filename)
for i in range(len(f)):
lst_renamed.append(os.path.join(path, lst_filename[i]))
for i in range(len(f)):
picture_resized = cv2.resize(picture_original, ((int(width.get())), int(height.get())))
cv2.imshow("Preview", picture_resized)
cv2.waitKey(1)
for i in lst_renamed:
cv2.imwrite(i, picture_resized)
I hope someone have some ideas. Thank you in advance!
This is an example to resize by a ratio and saves your image
def ResizeImage(filepath, newfileName,ratio):
image = cv2.imread(filepath) #Open image
height, width = image.shape[:2] #Shapes
image2 = cv2.resize(image, (width/ratio, height/ratio), interpolation = cv2.INTER_AREA)
cv2.imwrite(newfileName,image2) #saves, True if OK
return filepath
So if you call
image = "originalpath"
resized = ResizeImage(image,"Resized_"+image,2)
newImage = cv2.imread(resized)
cv2.imshow("new",newImage)
cv2.waitKey(1)
You should get your Image resized by half

Categories

Resources