3

pythonとwin32comを使用してAdobeのソフトウェアフォームを自動化すると、2D座標の配列を渡す際に問題が発生します。AdobeがVisualBasic(VB)用に出荷しているコードを見ると、その単純なものです。Illustratorで線を描く簡単な例は、次のようになります。

Set appObj = CreateObject("Illustrator.Application")
Set docObj = appObj.Documents.Add

Set pathItem = docObj.PathItems.Add
    pathItem.SetEntirePath Array(Array(0.0, 0.0), Array(20.0, 20.0))

ここで、単純な仮定は、VBコードを次のように変換することでPythonに変換できるということです。

from win32com.client import Dispatch

appObj = Dispatch("Illustrator.Application")  
docObj = appObj.Documents.Add()

pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( [ [0.0,0.0], [20.0,20.0] ] )

明らかに、それはそれほど簡単ではありません。Pythonは、「次元1の配列のみがサポートされています」というエラーを発行します。これで、配列の配列と2次元配列の間に違いがあることがわかりました。だから問題は、Pythonに正しい種類の配列を作成させるにはどうすればよいですか?

自分でVARIANT型を作ってみましたが、無残に失敗しました。私はこれについてもctypesを調べました。誰かが同じ問題を抱えていて、いくつかの光を当てることができますか?

PS:

以下を使用することで問題を回避できることを認識しています。

pathItem = docObj.PathItems.Add()
for point in (  [0.0,0.0], [20.0,20.0] ):
    pp = pathItem.PathPoints.Add() 
    pp.Anchor = point

しかし、これが実際には機能しない同様のケースがあります。とにかく重要なのは、学生への移植に関するガイドラインを書くことです。そうすれば、元の意図にできるだけ近い方がよいでしょう。

4

2 に答える 2

8

これは、実際にwin32comモジュールを使用する代替ソリューションです。IllustratorPhotoshopの配列型は、バリアント型の単一の配列であることがあります。バリアントタイプも配列です。同じ戦略を使用するSolidworksのような他のアプリケーションもあります。次のコードを使用して、win32comにバリアントタイプを作成させることができます。

from win32com.client import VARIANT
from pythoncom import VT_VARIANT

def variant(data):
    return VARIANT(VT_VARIANT, data)

常にどこでもバリアントを入力する必要がないので、Python配列を取得して、各サブ要素のバリアントを次のように作成できると便利です。

import collections

def vararr(*data):
    if (  len(data) == 1 and 
          isinstance(data, collections.Iterable) ):
        data = data[0]
    return map(variant, data)

したがって、最終的に私の完全なコードは次のようになります。

from win32com.client import Dispatch, VARIANT
from pythoncom import VT_VARIANT
import collections


appObj = Dispatch("Illustrator.Application")  
docObj = appObj.Documents.Add()

def variant(data):
    return VARIANT(VT_VARIANT, data)

def vararr(*data):
    if (  len(data) == 1 and 
          isinstance(data, collections.Iterable) ):
        data = data[0]
    return map(variant, data)

pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( vararr( [0.0,0.0], [20.0,20.0] )  )

#or you can have a iterable of iterables
pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( vararr( [[30.0,10.0], [60.0,60.0]] )  )

はい、これはcomtypesで実行できますが、これはwin32comでこれを実行する方法についての私の本当の質問に答えます。さらに、定数を生成できるなど、win32comを使用する理由があります。それで、久しぶりに、私は本当に私を困惑させた質問への答えをついに見つけました。これが誰かに役立つことを願っています。

于 2013-07-26T21:56:11.453 に答える
2

win32comを使用して選択領域を決定しようとしたときに、これと同じ問題が発生しました。win32comではなくcomtypesを使用してフォトショップにアクセスすると、多次元配列の問題が完全に解決されることがわかりました。

一次元配列の問題はwin32comの制限だと思いますが、間違っているかもしれません。

ここでcomtypesを入手できます: http ://sourceforge.net/projects/comtypes/

Tech Artists Orgにこの問題に関する投稿があり、一見の価値があります。

これは、上記のリンク先の技術アーティストのフォーラム投稿のcomtypeを使用して配列を通過する例です。パスポイントの実装も同様である必要があります。

import comtypes.client
ps_app = comtypes.client.CreateObject('Photoshop.Application') 
# makes a new 128x128 image
ps_app.Documents.Add(128, 128, 72)

# select 10x10 pixels in the upper left corner
sel_area = ((0, 0), (10, 0), (10, 10), (0, 10), (0, 0))
ps_app.ActiveDocument.Selection.Select(sel_area)
于 2012-04-16T01:54:02.687 に答える