使用Python将Base64 PNG图像转换为图像文件将返回无效的图像文件



我已经提出了Python代码,它输出Base64图像作为文件,但没有一个文件是有效的,也不能用任何图像查看器查看,因为它给出了一个"未知格式错误"。谁能给我指出正确的方向,什么是不正确的代码:

import mysql.connector
import base64
import binascii

# base64 decoding function
def decode_base64(data, image_type):
if data is None:
return None
missing_padding = 4 - len(data) % 4
if missing_padding:
data += b'=' * missing_padding
try:
return base64.b64decode(data)
except binascii.Error as e:
print(f"Invalid image for id {id} image type: {image_type}, Invalid Padding")
return base64.b64decode(data)
# Connect to the MySQL server
cnx = mysql.connector.connect(user='myuser', password='my_password',
host='127.0.0.1',
database='cms')

# Create a cursor
cursor = cnx.cursor()
# Execute the SELECT statement
cursor.execute("SELECT id, icon, icon_large FROM games")
# Iterate through the results
for (id, icon, icon_large) in cursor:
image_type = 'icon'
try:
# Decode the base64-encoded images
icon_data = decode_base64(icon, 'icon')
icon_large_data = decode_base64(icon_large, 'icon_large')
# Write the images to files if the data is not None
if icon_data is not None:
with open("icon_{}.png".format(id), "wb") as f:
f.write(icon_data)
except binascii.Error as e:
print(f"Invalid image for id {id} image type: {image_type}")
image_type = 'icon_large'
try:
if icon_large_data is not None:
with open("icon_large_{}.png".format(id), "wb") as f:
f.write(icon_large_data)
except binascii.Error as e:
print(f"Invalid image for id {id} image type: {image_type}")
# Close the cursor and connection
cursor.close()
cnx.close()

Base64代码实际上正在生成图像并且很好,有些可能有填充问题,但仍在浏览器上工作,因此我希望它们转换为文件图像也没有问题。

你的图像是jpeg,所以用.png扩展保存它们会让你的浏览者感到困惑。

JPEG的开头大致如下:

00000000: ffd8 ffe0 0010 4a46 4946 0001 0100 0001  ......JFIF......
00000010: 0001 0000 ffe2 0218 4943 435f 5052 4f46  ........ICC_PROF

注意:我可以在你的十六进制打印输出中看到JFIF-这就是我如何知道你的图像是jpeg的。

PNG的开头看起来大概是这样的:

00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
00000010: 0000 01f4 0000 01f4 0802 0000 0044 b448  .............D.H

如果你是在Windows上,没有适当的工具可用,你可以使用在线十六进制查看器在hexedit。

当@jps要求发布部分Base64图像代码时,我看了一下,我很快意识到它出了什么问题。Base64基本上是一个文本,而我从DB输出是二进制的。二进制和BLOB类型的列本身。这暗示我这不是一个Base64图像,而是一个实际的二进制图像数据。所以我找到了一个解决方案,我自己重写我的代码,从MySQL二进制存储导出图像。下面是代码(上面的代码是Base64编码的图像,如果它们存储在MySQL上):

import mysql.connector
from PIL import Image
import io
import base64
from PIL.Image import UnidentifiedImageError
# Connect to the database
cnx = mysql.connector.connect(user='myuser', password='mypassword', host='127.0.0.1', database='cms')
cursor = cnx.cursor()
# Retrieve the all ids from the games table
cursor.execute('SELECT id FROM games')
ids = cursor.fetchall()
# query
query = 'SELECT icon, icon_large FROM games WHERE id = %s'
#create a text file to save ids with no data.
with open("no_data_ids.txt", "w") as f:
# Iterate through all the ids
for id in ids:
cursor.execute(query, (id[0],))
icon_data, icon_large_data = cursor.fetchone()
if icon_data:
# Create an io.BytesIO object from the binary data
image_file = io.BytesIO(icon_data)
# Reset the file pointer to the beginning
image_file.seek(0)
# Open the image using the Image.open() method
image = Image.open(image_file)
#Save the image using the detected file format
image.save(f'icon_{id[0]}.{image.format.lower()}')
if icon_large_data:
# Create an io.BytesIO object from the binary data
image_file = io.BytesIO(icon_large_data)
# Reset the file pointer to the beginning
image_file.seek(0)
# Open the image using the Image.open() method
image = Image.open(image_file)
#Save the image using the detected file format
image.save(f'icon_large_{id[0]}.{image.format.lower()}')
if not icon_data and not icon_large_data:
# write id to no_data_ids.txt
f.write(str(id[0])+"n")
# close cursor and connection
cursor.close()
cnx.close()
f.close()

最新更新