Как сохранить сюжет, занимающий всю страницу файла PDF - PullRequest
1 голос
/ 16 апреля 2019

Я хочу создать многостраничный файл PDF для печати с использованием python. Я бы предпочел сделать это с библиотекой, которая могла бы хорошо работать в любой среде, поэтому я попытался с matplotlib .

Я могу создать нужную фигуру формата А4 и создать многостраничный файл PDF, но художник рисунков сжимается и не занимает всю страницу .

Я могу создать PDF-файл страниц формата A4 с отступом вокруг рисунка или файл PDF с меньшим размером страницы (страница сжимается вокруг рисунка, чтобы удалить отступы, при этом рисунок остается того же размера).

Может кто-нибудь помочь?

(Я не думаю, что это дублируется, есть и другие вопросы о заполнении, но не с той же целью, что и у меня, и я не смог найти ответа, который бы сработал для меня - я искал несколько дней!)

То, что я пробовал до сих пор после нескольких SO вопросов / ответов:

  • Использование bbox_inches='tight', pad_inches=0 в функции pyplot.savefig(), которая дает PDF-страницу меньшего размера, чем A4, без отступов.

(странно, это хорошо работает с форматом EPS, который печатает прямо в реальном размере на бумаге формата А4, но я не знаю, как сделать из этого многостраничный файл.)

  • Если я не использую bbox_inches='tight', pad_inches=0, размер фигуры кажется более или менее одинаковым, но отступы заполняют пространство для создания страницы А4.

  • Использование fig.tight_layout(rect=[0,0,1,1]) или fig.tight_layout(pad=0), которое сохраняет заполнение.

Этот пример кода создает рисунок в формате EPS (A4 без отступа), PDF (A4 с отступом) и TIFF (без заполнения, но меньшего размера, поэтому при печати он имеет отступ):

import matplotlib.pyplot as plt
from matplotlib import gridspec

def plot_form_page():
    # A4 canvas
    fig_width_cm = 21                                # A4 page
    fig_height_cm = 29.7
    inches_per_cm = 1 / 2.54                         # Convert cm to inches
    fig_width = fig_width_cm * inches_per_cm         # width in inches
    fig_height = fig_height_cm * inches_per_cm       # height in inches
    fig_size = [fig_width, fig_height]

    plt.rc('text', usetex=False) # so that LaTeX is not needed when creating a PDF with PdfPages later on
    fig = plt.figure()
    fig.set_size_inches(fig_size)
    fig.set_facecolor('#9999ff')

    gs = gridspec.GridSpec(29, 21, wspace=0.1, hspace=0.1)    

    # external axis
    ax0 = fig.add_subplot(gs[:, :])
    # for side in ["top", "bottom", "left", "right"]:
    #     ax0.spines[side].set_visible(False)

    # header
    ax1 = fig.add_subplot(gs[1:4, 1:4])
    ax1.set_facecolor('#bbffbb')

    ax2 = fig.add_subplot(gs[1:4, 4:-6])
    ax2.set_facecolor('#ffbbff')

    ax3 = fig.add_subplot(gs[1:4, -6:-1])
    ax3.set_facecolor('#00bbff')

    # form
    ax4, ax5, ax6, ax7   = [fig.add_subplot(gs[ 5+(i*6):10+(i*6), 1:10]) for i in range(4)]    
    [ax8, ax9, ax10, ax11] = [fig.add_subplot(gs[ 5+(i*6):10+(i*6), 11:20]) for i in range(4)]
    axes = [ax4, ax8, ax5, ax9, ax6, ax10, ax7, ax11]
    for ax in axes:
        ax.set_facecolor('#bbbbbb')

    for ax in fig.axes:
        ax.set_xticks([])
        ax.set_yticks([])

    print(fig.properties()['figwidth'], fig.properties()['figheight'])

    # from previous tests:
    #fig.tight_layout(pad=0)

plot_form_page()

plt.savefig('page.tiff',
            dpi=300,
            orientation='portrait',
            box_inches='tight', pad_inches=0)
plt.savefig('page.pdf',
            dpi=300,
            orientation='portrait',
            bbox_inches='tight', pad_inches=0)
plt.savefig('page.eps',
            dpi=300,
            orientation='portrait',
            papertype='a4',
            bbox_inches='tight', pad_inches=0)

fig.properties () дайте мне правильный размер для A4 в дюймах:

fig.properties()['figwidth']
fig.properties()['figheight']

8,26771653543307 11,69291338582677

Но рисунок уменьшается, чтобы допустить заполнение, когда дело доходит до печати

Вы можете увидеть эффекты в файле PDF здесь:

https://www.dropbox.com/s/naqy9vj4ht6g2mv/Screenshot%202019-04-16%20at%2011.46.48.png?dl=0

С EPS меньше проблем:

https://www.dropbox.com/s/umycd8ofwod3nk5/Screenshot%202019-04-16%20at%2012.05.52.png?dl=0

(но опять же, я не знаю, как создать многостраничный EPS)

С файлом TIFF я получаю то же самое:

https://www.dropbox.com/s/eid1zstbm954121/Screenshot%202019-04-16%20at%2012.11.59.png?dl=0

И это не обязательно, потому что программное обеспечение для печати добавляет отступы - теперь эта цифра на самом деле меньше, так как она составляет 1929 × 2655 пикселей при 300 точек на дюйм, это делает ее 6,43 × 8,85 дюйма - безусловно, меньше, чем A4.

РЕДАКТИРОВАТЬ: Это, конечно, можно решить путем печати с параметром «Подогнать страницу», но это может работать с любым изображением, имеющим пропорции А4, я хочу иметь контроль над размер, если это возможно.

1 Ответ

0 голосов
/ 18 апреля 2019

Благодаря комментариям @ImportanceOfBeingErnest и небольшому количеству проб и ошибок я нашел решение, которое создает фигуру в форме А4, которая при сохранении в виде страницы формата А4 PDF занимает всю страницу (не на 100% верно)., есть очень маленький запас, но он служит цели).

Требуется только добавить gs.tight_layout(fig, pad=0).Я не до конца понимаю, почему, но я подозреваю, что когда я пытался устранить заполнение объекта figureplt.savefig(..., bbox_inches='tight', pad_inches=0) или fig.tight_layout(...)), рисунок мог бы достигнуть границы страницы A4, но GridSpec не будет, поэтому заполнение, которое я видел, было между границами GridSpec и figure, а не с границей бумаги.Когда отступ между GridSpec и figure установлен на 0, а figure имеет размер A4, кажется, что все работает так, как я хотел.

(я до сих пор не понимаю, почему в некоторых случаяхразмер страницы PDF-файла уменьшился бы, но я собираюсь оставить ее здесь).

Это код, который делает то, что я хочу, если вы создаете файл PDF, открываете и проверяете свойства,размер A4, с прямоугольниками близко к границе.С другими вариантами было либо широкое поле, либо меньший размер страницы.

import matplotlib.pyplot as plt
from matplotlib import gridspec

def plot_form_page():
    # A4 canvas
    fig_width_cm = 21                                # A4 page
    fig_height_cm = 29.7
    inches_per_cm = 1 / 2.54                         # Convert cm to inches
    fig_width = fig_width_cm * inches_per_cm         # width in inches
    fig_height = fig_height_cm * inches_per_cm       # height in inches
    fig_size = [fig_width, fig_height]

    plt.rc('text', usetex=False) # so that LaTeX is not needed when creating a PDF with PdfPages later on
    fig = plt.figure()
    fig.set_size_inches(fig_size)
    fig.set_facecolor('#9999ff')

    gs = gridspec.GridSpec(29, 21, wspace=0.1, hspace=0.1)    

    # external axis
    ax0 = fig.add_subplot(gs[:, :])
    # for side in ["top", "bottom", "left", "right"]:
    #     ax0.spines[side].set_visible(False)

    # header
    ax1 = fig.add_subplot(gs[1:4, 1:4])
    ax1.set_facecolor('#bbffbb')

    ax2 = fig.add_subplot(gs[1:4, 4:-6])
    ax2.set_facecolor('#ffbbff')

    ax3 = fig.add_subplot(gs[1:4, -6:-1])
    ax3.set_facecolor('#00bbff')

    # form
    ax4, ax5, ax6, ax7   = [fig.add_subplot(gs[ 5+(i*6):10+(i*6), 1:10]) for i in range(4)]    
    [ax8, ax9, ax10, ax11] = [fig.add_subplot(gs[ 5+(i*6):10+(i*6), 11:20]) for i in range(4)]
    axes = [ax4, ax8, ax5, ax9, ax6, ax10, ax7, ax11]
    for ax in axes:
        ax.set_facecolor('#bbbbbb')

    for ax in fig.axes:
        ax.set_xticks([])
        ax.set_yticks([])

    #print(fig.properties()['figwidth'], fig.properties()['figheight'])

    gs.tight_layout(fig, pad=0)

plot_form_page()

plt.savefig('page.pdf',
            dpi=300,
            orientation='portrait')
...