在 xlsxwriter 中以可读的方式缩放图像

Scale images in a readable manner in xlsxwriter

我正在使用 xlsxwriter 在 excel 单元格中插入图像及其元数据。但我似乎无法以可读的方式正确缩放它。

我的代码是:

def resize_image(path,name):
    img=Image.open(path)
    img= img.resize((512,512))
    global temp_path
    full_path=os.path.join(temp_path,name)
    img.save(full_path)
    return full_path

def rotate_image(path ,name):
    img=Image.open(path)
    img= img.rotate(90,Image.NEAREST, expand=1)
    global temp_path
    full_path=os.path.join(temp_path,name)
    img.save(full_path)
    return full_path
    
def scale(size):
    row=100
    col=50
    return (row/size[0],col/size[1])

row=1
workbook=xlsxwriter.Workbook('data.xlsx')
bold = workbook.add_format({'bold': True})
worksheet=workbook.add_worksheet()
wrap = workbook.add_format({'text_wrap': True})
worksheet.set_column(1,4,50 ,wrap)

worksheet.write('A1','Image Name',bold)
worksheet.write('B1',"Resized Image",bold)
worksheet.write('C1',"Rotated Image",bold)
worksheet.write('D1',"Metadata",bold)
for i in glob.iglob(path+'\*.jpg',recursive=True):
    col=0
    size=np.asarray(Image.open(i)).shape
    x,y=scale(size)
    worksheet.set_row(row,50,wrap)
    name=get_image_name(i)
    worksheet.write(row,col, name)
    col+=1
    worksheet.insert_image(row,col,resize_image(i,name),{'x_scale':x, 'y_scale':y,'object_position': 1})

    col+=1
    worksheet.insert_image(row,col,rotate_image(i,name),{'x_scale':x, 'y_scale':y,'object_position': 1})

    col+=1

    worksheet.write(row,col,get_metadata(i),wrap)
    row+=1
workbook.close() 

我得到的输出是 output and I need something like this desired output。有人能告诉我我做错了什么吗?我试过缩放、改变宽度和高度等,但 none 似乎有效。

编辑这里是我的代码,在评论中进行了更改:

image_data={}
row=1
workbook=xlsxwriter.Workbook('data.xlsx')
bold = workbook.add_format({'bold': True})
worksheet=workbook.add_worksheet()
wrap = workbook.add_format({'text_wrap': True})
worksheet.set_column(4,4,50)
worksheet.set_column(1,3,32)
worksheet.set_column(0,0,20)
worksheet.write('A1','Image Name',bold)
worksheet.write('B1',"Resized Image",bold)
worksheet.write('C1',"Rotated Image",bold)
worksheet.write('D1',"Metadata",bold)
for i in glob.iglob(path+'\*.jpg',recursive=True):
    col=0
    size=np.asarray(Image.open(i)).shape
    x,y=scale(size)
    worksheet.set_row(row,64)
    name=get_image_name(i)
    worksheet.write(row,col, name)
    col+=1
    worksheet.insert_image(row,col,resize_image(i,name),{'x_scale':x, 'y_scale':y})

    col+=1
    worksheet.insert_image(row,col,rotate_image(i,name),{'x_scale':x, 'y_scale':y})

    col+=1
    s=get_metadata(i)
    if(len(s)!=0):
        worksheet.write(row,col,s,wrap)
        
    
        image_data[name]=s
    else:
        print('No Metadata found for image {}'.format(name))
    row+=1
workbook.close() 

我没有找到自动找到正确的列和行宽以进行缩放的解决方案,但也许这个解决方案可以帮助您。

import glob
import io
import os
from typing import Tuple

import xlsxwriter
from pil import Image


def buffer_image(image: Image, format: str = 'JPEG'):
    # Store image in buffer, so we don't have to write it to disk.
    buffer = io.BytesIO()
    image.save(buffer, format=format)
    return buffer, image


def resize(path: str, size: Tuple[int, int], format='JPEG'):
    image = Image.open(path)
    image = image.resize(size)
    return buffer_image(image, format)


def rotate(image: Image, rotation: int = 90, format='JPEG'):
    image = image.rotate(rotation, Image.NEAREST, expand=1)
    return buffer_image(image, format)


def create_header(worksheet: xlsxwriter.workbook.Worksheet):
    bold = workbook.add_format({'bold': True})
    worksheet.write('A1', 'Image Name', bold)
    worksheet.write('B1', "Resized Image", bold)
    worksheet.write('C1', "Rotated Image", bold)
    worksheet.write('D1', "Metadata", bold)
    return worksheet


if __name__ == '__main__':
    workbook = xlsxwriter.Workbook('image.xlsx')
    worksheet = workbook.add_worksheet()

    # Update the worksheet.
    wrap = workbook.add_format({'text_wrap': True})
    worksheet.set_column(0, 4, 27.5, wrap)
    worksheet = create_header(worksheet)

    for row, path in enumerate(glob.iglob("images/*.jpg"), start=1):
        worksheet.set_row(row, 150, wrap)

        # Add image name
        worksheet.write(row, 0, os.path.basename(path))

        # Add images
        image_buffer, image = resize(path, (512, 512), format='JPEG')

        data = {'x_scale': 200 / image.width, 'y_scale': 200 / image.height, 'object_position': 1}
        worksheet.insert_image(row, 1, path, {'image_data': image_buffer, **data})

        image_buffer, image = rotate(image, 90, format='JPEG')
        worksheet.insert_image(row, 2, path, {'image_data': image_buffer, **data})

        # Add metadata
        worksheet.write(row, 3, "Meta data", wrap)

    workbook.close()

方法

我手动检查了列和行的首选大小,以修复图像大小 (200, 200)。列和行的值分别为 27.5150

查看行:

worksheet.set_column(0, 4, 27.5, wrap)
worksheet.set_row(row, 150, wrap)

由于我现在知道了一个固定的缩放比例,我可以通过将其与已知的 (200, 200) 的情况进行比较来计算其他图像尺寸

data = {'x_scale': 200 / image.width, 'y_scale': 200 / image.height, 'object_position': 1}

额外

  • 我没有将临时图像写入磁盘,而是使用缓冲区将图像保存在内存中,这大约快两倍。

    def buffer_image(image: Image, format: str = 'JPEG'):
        # Store image in buffer, so we don't have to write it to disk.
        buffer = io.BytesIO()
        image.save(buffer, format=format)
        return buffer, image
    
  • 图像格式对缓冲区很重要,因此 resizerotate 函数中有一个 format 参数。如果您使用 .png 图片 JPEG 必须更改为 PNG