![혼합 인쇄를 지원합니까?](https://linux55.com/image/160149/%ED%98%BC%ED%95%A9%20%EC%9D%B8%EC%87%84%EB%A5%BC%20%EC%A7%80%EC%9B%90%ED%95%A9%EB%8B%88%EA%B9%8C%3F.png)
대부분의 페이지가 A4 라벨(프린터의 수동 트레이에서)에 인쇄되고 일부 구분 페이지가 일반 A3 용지(다른 트레이에서)에 인쇄되는 문서를 생성하고 인쇄해야 합니다.
현재 저는 Python과 Reportlab을 사용하고 있으며 혼합 페이지 크기(기본 페이지는 A4, 구분 페이지는 A3)로 문서를 생성하는 방법을 알고 있습니다. 그런데 evince로 인쇄할 때 인쇄할 페이지 크기를 선택해야 하는데 모든 페이지가 동일한 페이지 크기에 있고 동일한 트레이에서 인쇄됩니다...
내 문서에서 다양한 용지함의 다양한 용지 크기로 홈 페이지와 구분 페이지를 인쇄할 수 있는 방법이 있습니까?
답변1
setpagedevice
meuh의 도움 덕분에 기존 프로그램을 사용하여 생성한 PDF를 장치별 명령을 사용하여 PostScript 파일로 변환하는 짧은 Python 프로그램을 작성할 수 있었습니다 .
이 프로그램은 제가 사용하기에 완벽하지만, 다른 사람들에게도 시작점으로 유용할 수 있다고 생각했습니다. 여기있어:
#! /usr/bin/env python3
import argparse
import re
import subprocess
import sys
import PyPDF2
def make_postscript(f):
"""Convert a PDF file to PostScript, with pdf2ps, and yield it line by line."""
with subprocess.Popen(['pdf2ps', '/dev/stdin', '/dev/stdout'], stdin=f, stdout=subprocess.PIPE, stderr=None) as proc:
for line in proc.stdout:
yield line
def add_device_control(postscript, separator_pages):
"""Add device control commands to a PostScript file with DSC comments."""
DSC_page_re = re.compile(b'%%Page: (?P<page_name>.+) (?P<page_number>[1-9][0-9]*)$')
DSC_begin_page_setup_re = re.compile(b'%%BeginPageSetup$')
page_number = None
for line in postscript:
m = DSC_page_re.match(line)
if m:
assert page_number is None
page_number = int(m.group('page_number').decode('ASCII'))-1
yield line
continue
m = DSC_begin_page_setup_re.match(line)
if m:
assert page_number is not None
yield line
if page_number in separator_pages:
yield b'mark { << /PageSize [1191 842] /ImagingBBox null /MediaType (Plain) /MediaPosition null >> setpagedevice } stopped cleartomark\n'
elif page_number not in separator_pages:
yield b'mark { << /PageSize [595 842] /ImagingBBox null /MediaType (Labels) /MediaPosition 0 >> setpagedevice } stopped cleartomark\n'
page_number = None
continue
yield line
assert page_number is None
def walk_outline(outline, depth=0):
"""Walk through the outline of a PDF file in a depth-first search way, and yield each element with its zero-based depth."""
for obj in outline:
if isinstance(obj, PyPDF2.pdf.Destination):
yield depth, obj
elif isinstance(obj, list):
for result in walk_outline(obj, depth+1):
yield result
else:
assert False
def find_separator_pages(f):
"""Find the page number of the separator pages in a PDF file"""
separator_pages = set()
reader = PyPDF2.PdfFileReader(f)
for depth, obj in walk_outline(reader.outlines):
page_num = reader._getPageNumberByIndirect(obj.page)
if depth == 0:
assert page_num >= 0
separator_pages.add(page_num)
return separator_pages
def main():
parser = argparse.ArgumentParser()
parser.add_argument("input_file", metavar="input.pdf", type=argparse.FileType('rb'))
parser.add_argument("output_file", metavar="output.ps", nargs="?", type=argparse.FileType('wb'), default=sys.stdout.buffer)
args = parser.parse_args()
separator_pages = find_separator_pages(args.input_file)
args.input_file.seek(0)
postscript = make_postscript(args.input_file)
postscript = add_device_control(postscript, separator_pages)
for line in postscript:
args.output_file.write(line)
if __name__ == "__main__":
main()
댓글로 도움을 주신 meuh님께 다시 한 번 감사드립니다.