I am trying to upload an image that has been converted to grayscale, like this:
blob_path = os.path.join(os.path.split(__file__)[0], 'static/img/blob-masks/1.png')
blob = Image.open(blob_path).convert('L')
buffer = StringIO()
blob.save(buffer)
upload_image(buffer.getvalue(),"foo.png")
But it just seem to upload a black square.
If I got to the command line python and run:
col = Image.open("/static/img/blob-masks/5.png")
col.convert('L')
col.save("result_bw.png")
result_bw.png is perfect. What is going wrong?
Is there a reason you can't just upload the greyscale image after you convert it? Like:
image = Image.open('static/img/blob-masks/1.png')
image.convert('L')
image.save("temp/bw.png")
upload_image("temp/bw.png")
# maybe delete the temporary file when you're done
import os
os.remove("temp/bw.png")
I'm not sure how your upload_image() function works, but when I upload using django if I do any manipulations I write a temporary file and then re-import. If I don't manipulate the image at all I can just upload it directly.
Related
I'm a beginner in python and I'm trying to send someone my small python program together with a picture that'll display when the code is run.
I tried to first convert the image to a binary file thinking that I'd be able to paste it in the source code but I'm not sure if that's even possible as I failed to successfully do it.
You can base64-encode your JPEG/PNG image which will make it into a regular (non-binary string) like this:
base64 -w0 IMAGE.JPG
Then you want to get the result into a Python variable, so repeat the command but copy the output to your clipboard:
base64 -w0 IMAGE.JPG | xclip -selection clipboard # Linux
base64 -w0 IMAGE.JPG | pbcopy # macOS
Now start Python and make a variable called img and paste the clipboard into it:
img = 'PASTE'
It will look like this:
img = '/9j/4AAQSk...' # if your image was JPEG
img = 'iVBORw0KGg...' # if your image was PNG
Now do some imports:
from PIL import Image
import base64
import io
# Make PIL Image from base64 string
pilImage = Image.open(io.BytesIO(base64.b64decode(img)))
Now you can do what you like with your image:
# Print its description and size
print(pilImage)
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=200x100>
# Save it to local disk
pilImage.save('result.jpg')
You can save a picture in byte format inside a variable in your program. You can then convert the bytes back into a file-like object using the BytesIO function of the io module and plot that object using the Image module from the Pillow library.
import io
import PIL.Image
with open("filename.png", "rb") as file:
img_binary = file.read()
img = PIL.Image.open(io.BytesIO(img_binary))
img.show()
To save the binary data inside your program without having to read from the source file you need to encode it with something like base64, use print() and then simply copy the output into a new variable and remove the file reading operation from your code.
That would look like this:
img_encoded = base64.encodebytes(img_binary)
print(img_binary)
img_encoded = " " # paste the output from the console into the variable
the output will be very long, especially if you are using a big image. I only used a very small png for testing.
This is how the program should look like at the end:
import io
import base64
import PIL.Image
# with open("filename.png", "rb") as file:
# img_binary = file.read()
# img_encoded = base64.encodebytes(img_binary)
img_encoded = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABX[...]'
img = PIL.Image.open(io.BytesIO(base64.decodebytes(img_encoded)))
img.show()
You could perhaps have your Python program download the image from a site where you upload files such as Google Drive, Mega, or Imgur. That way, you can always access and view the image easily without the need of running the program or for example converting the binary back into the image in the method you mentioned.
Otherwise, you could always store the image as bytes in a variable and have your program read this variable. I'm assuming that you really wish to do it this way as it would be easier to distribute as there is only one file that needs to be downloaded and run.
Or you could take a look at pyinstaller which is made for python programs to be easily distributed across machines without the need to install Python by packaging it as an executable (.exe) file! That way you can include the image file together by embedding it into the program. There are plenty of tutorials for pyinstaller you could google up. Note: Include the '--onefile' in your parameters when running pyinstaller as this will package the executable into a single file that the person you're sending it to can easily open whoever it may be-- granted the executable file can run on the user's operating system. :)
I want to convert an image RGB dataset to Grayscale dataset using pillow. I want to write a script that takes in the dataset path and converts all images one by one into grayscale. At the end I want to save this script, and want to run this script on the server to avoid the copying of huge data to the server.
Probably this code would work for you?
Code:
import os
from PIL import Image
dir = '/content/pizza_steak/test/pizza'
for i in range(len(os.listdir(dir))):
# directory where images are stored
dir = '/content/pizza_steak/test/steak'
# get the file name
file_name = os.listdir(dir)[i]
# creating a final path
final_path = dir + '/' + file_name
# convet and save the image
Image.open(final_path).convert('L').save(f"/content/meow/gray{file_name}")
# uncomment this is you want to delete the file
# os.remove(final_path)
I want to remove exif from an image before uploading to s3. I found a similar question (here), but it saves as a new file (I don't want it). Then I found an another way (here), then I tried to implemented it, everything was ok when I tested it. But after I deployed to prod, some users reported they occasionally got a problem while uploading images with a size of 1 MB and above, so they must try it several times.
So, I just want to make sure is my code correct?, or maybe there is something I can improve.
from PIL import Image
# I got body from http Request
img = Image.open(body)
img_format = img.format
# Save it in-memory to remove EXIF
temp = io.BytesIO()
img.save(temp, format=img_format)
body = io.BytesIO(temp.getvalue())
# Upload to s3
s3_client.upload_fileobj(body, BUCKET_NAME, file_key)
*I'm still finding out if this issue is caused by other things.
You should be able to copy the pixel data and palette (if any) from an existing image to a new stripped image like this:
from PIL import Image
# Load existing image
existing = Image.open(...)
# Create new empty image, same size and mode
stripped = Image.new(existing.mode, existing.size)
# Copy pixels, but not metadata, across
stripped.putdata(existing.getdata())
# Copy palette across, if any
if 'P' in existing.mode: stripped.putpalette(existing.getpalette())
Note that this will strip ALL metadata from your image... EXIF, comments, IPTC, 8BIM, ICC colour profiles, dpi, copyright, whether it is progressive, whether it is animated.
Note also that it will write JPEG images with PIL's default quality of 75 when you save it, which may or may not be the same as your original image had - i.e. the size may change.
If the above stripping is excessive, you could just strip the EXIF like this:
from PIL import Image
im = Image.open(...)
# Strip just EXIF data
if 'exif' in im.info: del im.info['exif']
When saving, you could test if JPEG, and propagate the existing quality forward with:
im.save(..., quality='keep')
Note: If you want to verify what metadata is in any given image, before and after stripping, you can use exiftool or ImageMagick on macOS, Linux and Windows, as follows:
exiftool SOMEIMAGE.JPG
magick identify -verbose SOMEIMAGE.JPG
I'm looking for a way to download an 640x640 image from a URL, resize the image to 180x180 and append the word small to the end of the resized image filename.
For example, the image is located at this link
http://0height.com/wp-content/uploads/2013/07/18-japanese-food-instagram-1.jpg
Once resized, I would like to append the world small to the end of the filename like so:
18-japanese-food-instagram-1small.jpeg
How can this be done? Also will the downloaded image be saved to memory or will it save to the actual drive? If it does save to the drive, is it possible to delete the original image and keep the resized version?
Why don't you try urllib?
import urllib
urllib.urlretrieve("http://0height.com/wp-content/uploads/2013/07/18-japanese-food-instagram-1.jpg", "18-japanese-food-instagram-1.jpg")
Then, to resize this you can use PIL or another library
import Image
im1 = Image.open("18-japanese-food-instagram-1.jpg")
im_small = im1.resize((width, height), Image.ANTIALIAS)
im_small.save("18-japanese-food-instagram-1_small.jpg")
References:
http://www.daniweb.com/software-development/python/code/216637/resize-an-image-python
Downloading a picture via urllib and python
I want to generate a barcode image. So, I used elaphe package. It works correctly but it returns PIL.EPSImageFile instance. I don't know how I can convert it to image format like SVG, PNG or JPG.
The code I have written is:
barcode('code128', 'barcodetest')
And it returns:
<PIL.EpsImagePlugin.EpsImageFile image mode=RGB size=145x72 at 0x9AA47AC>
How can I convert this instance to image?
Actually I think my question is wrong but I don't know how to explain it well!
Simply save that file object to something with a .png or .jpg filename:
bc = barcode('qrcode',
'Hello Barcode Writer In Pure PostScript.',
options=dict(version=9, eclevel='M'),
margin=10, data_mode='8bits')
bc.save('yourfile.jpg')
or state the format explicitly:
bc.save('yourfile.jpg', 'JPEG')
PIL will then convert the image to the correct format.
Note that the PIL EPS module uses the gs command from the Ghostscript project to do it's conversions, you'll need to have it installed for this to work.