发生异常:非法参数 - 参数 2,预期对象(使用 win32com 建立 Photoshop 联系 sheet)

Exception occured: Illegal Argument - Argument 2, Object Expected (Making a Photoshop contact sheet using win32com)

我正在尝试使用 Photoshop API 中包含的 MakeContactSheet 功能创建 Photoshop 联系人 sheet。可以使用 'win32com.client'.

访问它

我的第一行: psApp = Dispatch("Photoshop.Application")

创建一个 win32com.gen_py.E891EE9A-D0AE-4CB4-8871-F92C0109F18Ex0x1x0._Application._Application 对象。

此对象的 class 似乎具有 documentation 中列出的所有可用功能。

然后我继续用 os.walk 制作一个字符串列表。

CSInputFiles = [path.join(r, f) for r, sd, fs in walk('C:\Users\chris\Desktop\1A') for f in fs]

然后是一组混合选项:

CSoptions = [True, psApp, False, False, 6, True, None, 0, 7, 4, 3, 300, 3, None, True]

最后我传递了这些论点: psApp.MakeContactSheet(CSInpuFiles, CSoptions)

考虑到 _Application 中的函数定义,这似乎是正确的:

def MakeContactSheet(self, InputFiles=defaultNamedNotOptArg, Options=defaultNamedOptArg):
    'create a contact sheet from multiple files'
    # Result is a Unicode object
    return self._oleobj_.InvokeTypes(1129599816, LCID, 1, (8, 0), ((12, 1), (12, 17)),InputFiles
        , Options)

唉,我收到以下错误:

Traceback (most recent call last):
  File "C:\Users\chris\Desktop\test.py", line 17, in <module>
    psApp.MakeContactSheet(CSInputFiles, CSoptions)
  File "C:\Users\chris\AppData\Local\Temp\gen_py.9\E891EE9A-D0AE-4CB4-8871-F92C0109F18Ex0x1x0\_Application.py", line 97, in MakeContactSheet
    return self._oleobj_.InvokeTypes(1129599816, LCID, 1, (8, 0), ((12, 1), (12, 17)),InputFiles
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'Adobe Photoshop', 'Illegal argument - argument 2\n- Object expected', None, 0, -2147220261), None)

我最初的直觉是将我的 csInputFiles 数组中的所有字符串转换为带有 pathlib 的路径对象。

from pathlib import Path

CSInputFiles = [Path(path.join(r, f)) for r, sd, fs in walk('C:\Users\chris\Desktop\1A') for f in fs]

当我将数组传递给函数时产生了这个晦涩的垃圾:

psApp.MakeContactSheet(CSInputFiles, CSoptions)

#RUN!

File "C:\Users\chris\Desktop\test.py", line 17, in <module>
    psApp.MakeContactSheet(CSInputFiles, CSoptions)
  File "C:\Users\chris\AppData\Local\Temp\gen_py.9\E891EE9A-D0AE-4CB4-8871-F92C0109F18Ex0x1x0\_Application.py", line 97, in MakeContactSheet
    return self._oleobj_.InvokeTypes(1129599816, LCID, 1, (8, 0), ((12, 1), (12, 17)),InputFiles
TypeError: must be real number, not WindowsPath

这根本说不通!它怎么可能期待一个实数呢?这是一组输入文件!

问题中指定的错误是由于我将选项参数设为列表而不是对象造成的。有关对象结构的信息,您可以查看 here.

然而,在 GitHub 上询问后,我发现 MakeContactSheet 是一个已弃用的函数,如 this 文档第 19 页所述。

这让我使用 pillow 库开发了一种替代品。

解决方案是简单地创建一个空的 png,然后将您想要放在联系人 sheet 上的所有图像粘贴到那个 png

为了解决这里的问题,我把这个程序的简化版贴出来。

from PIL import Image
from os import walk, path

#rows = amount of rows (int)
#columns = amount of clomns (int)
#sheetWidth = the width of the contact sheet in inch (int)
#sheetHeight = the height of the contact sheet in inch (int)
#aspectRatio = the simplified height to width ratio of the images on the contact sheet (height/width) (float)
#ppi = pixels per inch
#path = the folder containing all the images you wish to make a contact sheet of (string)

def make_contact_sheet(rows, columns, sheetWidth, sheetHeight, aspectRatio, ppi, filePath):

    #convert inches to pixels
    sheetWidth *= ppi
    sheetHeight *= ppi

    #Calculate the size that images will be on the sheet
    imageHeight = sheetHeight // columns
    imageWidth = int(imageHeight * aspectRatio)

    #Calculate how far apart the images will be spaced (I call this padding)
    xRemSpace = sheetWidth - (imageWidth * columns)
    xPad = xRemSpace // (columns-1)

    yRemSpace = sheetHeight - (imageHeight * rows)
    yPad = yRemSpace // (rows+1)

    #Now make the empty png
    sheet = Image.new("RGBA", (sheetWidth, sheetHeight), color=(0,0,0,255))

    #Loop through paths of the images and paste the images one by one
    x, y = 0, yPad
    images = [Image.open(path.join(r,f)) for r,sd,fs in walk(filePath) for f in fs]

    for i in range(len(images)):
        #Resize the image
        resized = images[i].resize((imageWidth, imageHeight))

        #Paste the images
        if i == 0:
            sheet.paste(resized, (x,y))
        elif i % columns == 0:
            x = 0
            y += imageHeight + yPad
            sheet.paste(resized, (x,y))
        else:
            x += imageWidth + xPad
            sheet.paste(resized, (x,y))

    return sheet

if __name__ == "__main__":
    sheet = make_contact_sheet(3, 5, 8, 5, (2/3), 300, r"Some path")
    sheet.show()

如上所述,这是一个非常粗略的示例,它基于我编写的最终程序的更精细版本。但是我已经越界了。