最新消息:20210917 已从crifan.com换到crifan.org

【已解决】Python的Pillow如何返回图像的二进制数据

Python crifan 963浏览 0评论
折腾:
【未解决】Python中实现二进制数据的图片的压缩
期间,此处已经可以压缩图片:
【已解决】Python的Pillow中如何压缩缩放图片且保持原图宽高比例
了,然后希望拿到压缩后图片的二进制数据。
看看属性有没有关于binary data的:
https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.tobytes
Image.tobytes(encoder_name=’raw’, *args)[source]
好像这个可以?
”This method returns the raw image data from the internal storage. For compressed image data (e.g. PNG, JPEG) use save(), with a BytesIO parameter for in-memory data.“
去看看save
https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.save
但是保存参数只支持fp,不支持binary
python  pillow get image binary data
python  pillow  image output to binary data
python – Get binary image data from PIL.Image? – Stack Overflow
用这个好像可以?
”The img object needs to be saved again; write it to another BytesIO object:
output = io.BytesIO()
img.save(output, format=’JPEG’)
then get the written data with the .getvalue() method:
hex_data = output.getvalue()”
Python PIL: how to write PNG image to string – Stack Overflow
好像就是
去写代码试试
fileBytes = fileObj.read()
log.debug("len(fileBytes)=%s", len(fileBytes))

if fileType == MongoFileType.IMAGE.value:
    imageFile = Image.open(fileBytes)
结果报错:
    imageFile = Image.open(fileBytes)
  File "/Users/crifan/.local/share/virtualenvs/EvaluationSystemServer-6RbmF4Wj/lib/python3.6/site-packages/PIL/Image.py", line 2609, in open
    fp = builtins.open(filename, "rb")
ValueError: embedded null byte
换成:
imageStream = io.BytesIO(fileBytes)
imageFile = Image.open(imageStream)
就可以了:
输出:
len(fileBytes)=427306
imageFile=<PIL.PngImagePlugin.PngImageFile image mode=RGBA size=3543x3543 at 0x10615C5C0>
结果代码:
fileBytes = fileObj.read()
log.debug("len(fileBytes)=%s", len(fileBytes))

if fileType == MongoFileType.IMAGE.value:
    imageStream = io.BytesIO(fileBytes)
    imageFile = Image.open(imageStream)
    log.debug("imageFile=%s", imageFile)
    log.debug("imageFile.size=%s", imageFile.size)
    imageFile.thumbnail(IMAGE_COMPRESS_SIZE, Image.ANTIALIAS)
    log.debug("imageFile=%s", imageFile)
    imageOutput = io.BytesIO()
    log.debug("imageOutput=%s", imageOutput)
    imageFile.save(imageOutput)
    log.debug("imageFile=%s", imageFile)
    compressedImageBytes = imageOutput.getvalue()
    log.debug("compressedImageBytes=%s", compressedImageBytes)
    log.debug("len(compressedImageBytes)=%s", len(compressedImageBytes))
    fileBytes = compressedImageBytes
中的
imageFile.save(imageOutput)
还是出错:
    imageFile.save(imageOutput)
  File "/Users/crifan/.local/share/virtualenvs/EvaluationSystemServer-6RbmF4Wj/lib/python3.6/site-packages/PIL/Image.py", line 1951, in save
    raise ValueError('unknown file extension: {}'.format(ext))
ValueError: unknown file extension:
Python PIL: how to write PNG image to string – Stack Overflow
试试
“For Python3 it is required to use BytesIO:”
搜:
python3-flask-pil-in-memory-image
python – How to send image generated by PIL to browser? – Stack Overflow
python – How to send image generated by PIL to browser? – Stack Overflow
试试:StringIO()
先去试试:
https://stackoverflow.com/questions/646286/python-pil-how-to-write-png-image-to-string
的BytesIO,好像已经是了
难道是缺少设置后缀?
去加上后缀
以及去看看save参数
https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.save
Image file formats — Pillow (PIL Fork) 5.3.0 documentation
好像不支持把JPEG写成JPG?
后续试试
才看到:
“* format – Optional format override. If omitted, the format to use is determined from the filename extension. If a file object was used instead of a filename, this parameter should always be used.”
-》此处是Byte,不是filename,没有suffix,所以必要要传递format参数才对
加了后缀:
imageSuffix = fileObj.filename.split(".")[-1] # png
log.debug("imageSuffix=%s", imageSuffix)
imageFormat = imageSuffix.upper() # PNG
log.debug("imageFormat=%s", imageFormat)
# imageFile.save(imageOutput)
imageFile.save(imageOutput, imageFormat)
果然可以了。
【总结】
最后用代码:
imageOutput = io.BytesIO()
log.debug("imageOutput=%s", imageOutput)
imageSuffix = fileObj.filename.split(".")[-1] # png
log.debug("imageSuffix=%s", imageSuffix)
imageFormat = imageSuffix.upper() # PNG
if imageFormat == "JPG":
    imageFormat = "JPEG"
log.debug("imageFormat=%s", imageFormat)
# imageFile.save(imageOutput)
imageFile.save(imageOutput, imageFormat)
log.debug("imageFile=%s", imageFile)
log.debug("imageFile.size=%s", imageFile.size)
compressedImageBytes = imageOutput.getvalue()
实现了要的效果:
可以把压缩后的图片保存成二进制数据了:
其中二进制数据中可以看到PNG
其中:
【后记】
看到:
Python PIL: how to write PNG image to string – Stack Overflow
的评论中说
image.save(output, format=image.format)
看来是Image有format属性-》那就可以直接用,不需要从文件后缀去得到格式了。
去试试
从官网解释:
https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.format
“PIL.Image.format
The file format of the source file. For images created by the library itself (via a factory function, or by running a method on an existing image), this attribute is set to None.
Type:
string or None”
很明显:
此处从binary data输入的image,此处format应该是None
去调试看看,包括另外看看PIL.Image.info
resize后的image的info是:
然后format是有的:
即:此处从binary的byte从读入的Image,是可以解析出来format是PNG的:
同时可见解析后的对象已经是:
<PIL.PngImagePlugin.PngImageFile image mode=RGBA size=3543×3543 at 0x1065F7A20>
了,就已经表示是PNG格式了。
所以去优化代码,用format即可。
outputImageFormat = None
if outputFormat:
    outputImageFormat = outputFormat
elif imageFile.format:
    outputImageFormat = imageFile.format
imageFile.save(imageOutput, outputImageFormat)
是可以的:
再去看看对于jpeg图片能否检测出format:
也是可以的。
更新后的代码是:
imageFile.thumbnail(newSize, resample)

# save and return binary byte
imageOutput = io.BytesIO()
# imageFile.save(imageOutput)
outputImageFormat = None
if outputFormat:
    outputImageFormat = outputFormat
elif imageFile.format:
    outputImageFormat = imageFile.format
imageFile.save(imageOutput, outputImageFormat)
imageFile.close()
compressedImageBytes = imageOutput.getvalue()
log.debug("len(compressedImageBytes)=%s", len(compressedImageBytes))
return compressedImageBytes
【后记2】
从:
https://docs.python.org/3/library/io.html#io.BytesIO.getvalue
也可以看到对应的函数的解释了:
“class io.BytesIO([initial_bytes])
A stream implementation using an in-memory bytes buffer. It inherits BufferedIOBase. The buffer is discarded when the close() method is called.
The optional argument initial_bytes is a bytes-like object that contains initial data.
BytesIO provides or overrides these methods in addition to those from BufferedIOBase and IOBase:
getvalue()
Return bytes containing the entire contents of the buffer.”

转载请注明:在路上 » 【已解决】Python的Pillow如何返回图像的二进制数据

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
92 queries in 0.184 seconds, using 23.42MB memory