otucurry
@otucurry

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

PILを使ってマルチTIFFファイルを各ページの正しいサイズ・向きでプリンタに印刷したい

python3.7にてPILを使ってマルチTIFFファイル(ページごとにサイズと向きが異なる)を指定プリンタに出力するプログラム(下記)を作成したいと思っているのですが、全てのページが最初に指定したサイズと向きになってしまいます。
各ページを適切なサイズと向きになるようにするにはどうすればよいか教えていただけませんでしょうか?
 ※各ページのサイズと向きは取得できます。StartPage()~EndPage()間にどのように入れたらよいかがわかりません。ページごとにCreateDCするほかないのでしょうか?

pyPrintout.py
import win32print
import win32ui
import win32gui
from PIL import Image, ImageWin
Image.MAX_IMAGE_PIXELS = 20000000000

HORZRES = 8
VERTRES = 10
LOGPIXELSX = 88
LOGPIXELSY = 90
PHYSICALWIDTH = 110
PHYSICALHEIGHT = 111


# PILを使って画像を印刷する
def main(file_name):
    # プリンタ名
    printer_name = 'FUJI XEROX DocuWide 6057'

    # Imageを読み込み
    with Image.open(file_name) as src_image:
        # ページ数
        pages = src_image.n_frames

        # プリンタ情報
        pHandle = win32print.OpenPrinter(printer_name, {'DesiredAccess': win32print.PRINTER_ALL_ACCESS})
        print_processor = win32print.GetPrinter(pHandle, 2)['pPrintProcessor']
        attributes = win32print.GetPrinter(pHandle, 2)
        devmode = attributes['pDevMode']

        # プリンタ設定を書き換え(サイズ)
        devmode.FormName = 'A3'
        devmode.PaperSize = 8
        devmode.PaperWidth = 2970
        devmode.PaperLength = 4200

        # プリンタ設定を書き換え(向き)
        Orientation = 1
        if src_image.size[0] > src_image.size[1]:
            Orientation = 2
        devmode.Orientation = Orientation

        # pDevModeを再設定
        attributes['pDevMode'] = devmode
        win32print.SetPrinter(pHandle, 2, attributes, 0)

        # プリンタ設定ダイアログを表示して確認
        caption = f'{printer_name} ({file_name} - {pages}pages)'
        status = win32print.DocumentProperties(0, pHandle, caption, devmode, devmode, 5)
        # OK
        if status == 1:
            win32print.SetPrinter(pHandle, 2, attributes, 0)
        # キャンセル
        else:
            win32print.ClosePrinter(pHandle)
            return 1

        win32print.ClosePrinter(pHandle)

        # プリンタ出力コンテキスト作成
        pDC = win32gui.CreateDC(print_processor, printer_name, devmode)
        hDC = win32ui.CreateDCFromHandle(pDC)
        hDC.CreatePrinterDC(printer_name)

        # プリンタ印刷領域取得
        printable_area = hDC.GetDeviceCaps(HORZRES), hDC.GetDeviceCaps(VERTRES)
        printer_size = hDC.GetDeviceCaps(PHYSICALWIDTH), hDC.GetDeviceCaps(PHYSICALHEIGHT)

        # 印刷スタート
        hDC.StartDoc(file_name)
        for page in range(pages):
            src_image.seek(page)

            hDC.StartPage()
            dib = ImageWin.Dib(src_image)

            # レシオ、スケールを算出
            ratios = [1.0 * printable_area[0] / src_image.size[0], 1.0 * printable_area[1] / src_image.size[1]]
            scale = min(ratios)

            # スケールされたサイズを取得
            scaled_width, scaled_height = [int(scale * i) for i in src_image.size]
            x1 = int((printer_size[0] - scaled_width) / 2)
            y1 = int((printer_size[1] - scaled_height) / 2)
            x2 = x1 + scaled_width
            y2 = y1 + scaled_height

            # ページをプリンタに出力
            dib.draw(hDC.GetHandleOutput(), (x1, y1, x2, y2))
            hDC.EndPage()

        # 印刷終了
        hDC.EndDoc()
        hDC.DeleteDC()
    return 0


if __name__ == '__main__':
    exit(main('multipage.tif'))

0

1Answer

画像を回転してみてはいかがでしょうか

if src_image.size[0] > src_image.size[1]:
    src_image = src_image.rotate (90)
1Like

Comments

  1. @otucurry

    Questioner

    ありがとうございます。
    ImageWin.Dib(src_image)の前にご回答のコードを入れてみました。確かに画像の向きは変わりますが大元のサイズ・向きは変わらずです。
    また、win32print.SetPrinterをStartPageの直前に入れてみましたがサイズ・向きに変化なしでした。CreateDC時に既にdevmodeをいれており、その値が変わってないようにも見えます。何かそれに関連するのではと確認したところ、ResetDCでdevmodeを引数として設定変更できるようなのですが、pythonにはなさそうです。

Your answer might help someone💌