LibreOffice Calc 그리드에 이미지 로드

저는 이미지가 멋져 보이기 때문에 항상 스프레드시트의 그리드에 이미지를 로드하고 싶었기 때문에 이를 수행하는 LibreOffice Calc용 스크립트를 코딩했습니다.



LibreOffice는 Python 스크립팅을 지원합니다. 저는 Python으로 프로그래밍을 많이 하기 때문에 편리하지만 LibreOffice에서 Python 스크립팅을 활성화하려면 Python 스크립트 지원 공급자를 설치해야 합니다.

우분투에서:

sudo apt install libreoffice-script-provider-python


이제 Python 스크립트에서 이미지를 로드하려면 Pillow 라이브러리가 필요합니다. LibreOffice는 시스템 Python을 사용하므로 다음과 같이 간단하게 수행할 수 있습니다.

pip install Pillow


라이브러리는 LibreOffice Python 스크립트에서 사용할 수 있습니다.

다음으로 LibreOffice용 Python 스크립트를 어디에 둘까요? Linux에서 스크립트는 ~/.config/libreoffice/4/user/Scripts/python 에 있습니다. LibreOffice 매크로 엔진이 거기에 입력한 모든 항목을 선택합니다. 예를 들어 ~/.config/libreoffice/4/user/Scripts/python/load_image.py 파일이 있고 해당 파일에 LoadImage 라는 함수가 있고 스크립트가 오류 없이 로드되는 경우 Tools > Macros > Run Macro를 선택할 때 열리는 매크로 선택기에서 이를 볼 수 있습니다. .



이제 스크립트에 무엇을 입력해야 합니까? 먼저 Pillow 라이브러리에서 Image를 가져와야 합니다.

from PIL import Image


다음으로 LoadImage 라는 함수를 만들고 이 함수에서 현재 시트를 가져옵니다. (Calc가 현재 열려 있고 시트도 열려 있다고 가정합니다.)

# Assuming a spreadsheet is currently open.
desktop = XSCRIPTCONTEXT.getDesktop()
model = desktop.getCurrentComponent()
active_sheet = model.CurrentController.ActiveSheet


이를 위해 가져올 필요가 없습니다. XSCRIPTCONTEXT는 LibreOffice의 스크립팅 호스트에 의해 주입됩니다.

로드할 이미지를 알기 위해 스프레드시트의 셀A1에서 전체 경로를 읽어야 합니다.

path = active_sheet.getCellByPosition(0, 0).String


다음으로 이미지를 로드하고 PIL을 사용하여 작은 크기로 조정합니다. 스프레드시트에서 너무 많은 셀을 사용하고 싶지 않기 때문입니다. 문제가 발생하면 여기에서 중단하고 셀A1에 오류 메시지를 입력합니다. 이미지 로드에 성공하면 셀A1(이미지 파일 경로)의 텍스트를 지우고 계속합니다.

try:
    im = Image.open(path)
    scale_factor = LONGER_EDGE_PIXELS / max(im.width, im.height)
    out_w = int(scale_factor * im.width)
    out_h = int(scale_factor * im.height)
    out = Image.new("RGB", (out_w, out_h), (255, 255, 255))
    rsz = im.resize((out_w, out_h))
    out.paste(rsz)
    image_load_successful = True
except Exception as ex:
    active_sheet.getCellByPosition(0, 0).String = str(ex)
    image_load_successful = False

if not image_load_successful:
    return None

active_sheet.getCellByPosition(0, 0).String = ""

LONGER_EDGE_PIXELS는 스크립트에서 추가로 삽입되는 상수입니다. 저는 100으로 설정했습니다. 더 긴 가장자리(너비 또는 높이 중 더 긴 쪽)가 100픽셀을 차지하도록 이미지 크기가 조정됩니다.

사용 중인 이미지가 RGB 픽셀 형식(RGBA 또는 인덱스가 아님)을 사용하고 있는지 확인해야 하기 때문에 크기 조정된 이미지는 새로 생성된 이미지 개체에 붙여넣어집니다.

스프레드시트에 작업을 수행하기 전에 항상 실행되기 때문에 이미지 렌더링 속도를 저하시키는 일부 처리기를 일시적으로 비활성화합니다.

model.enableAutomaticCalculation(False)
model.lockControllers()
model.addActionLock()


이제 픽셀로 사용할 열과 행의 크기를 조정할 차례입니다.

columns = active_sheet.getColumns()
rows = active_sheet.getRows()
for y in range(out_h):
    rows[y].Height = ROW_HEIGHT
for x in range(out_w):
    columns[x].Width = COLUMN_WIDTH

ROW_HEIGHTCOLUMN_WIDTH는 다시 스크립트에서 추가로 삽입되는 상수입니다. 180과 200으로 설정했습니다. 약간의 조정이 필요할 수 있으며 Calc의 확대/축소 기능을 사용하면 종횡비가 변경된다는 것을 알았습니다.

아마도 한 번에 전체 범위의 크기를 조정하는 방법이 있을 것입니다.

마지막으로 실제 이미지 렌더링을 할 수 있습니다. 빨간색, 녹색 및 파란색의 개별 값을 RGB 색상 값으로 변환해야 하므로 _rgb라는 중첩 함수를 추가로 삽입합니다.

def _rgb(r, g, b):
    return (r << 16) | (g << 8) | b


이제 getpixel 를 사용하여 크기 조정된 이미지 픽셀에서 색상 값을 읽고 셀의 CellBackColor 속성을 사용하여 배경색을 설정합니다.

for y in range(out_h):
    for x in range(out_w):
        active_sheet.getCellByPosition(x, y).CellBackColor = _rgb(*out.getpixel((x, y)))



그게 다야! 위의 루프는 시간이 걸립니다. 내 컴퓨터에서 이미지를 렌더링하는 데 6-15초가 걸립니다. 렌더링이 완료되면 위에서 잠긴 핸들러의 잠금을 해제합니다.

model.removeActionLock()
model.unlockControllers()
model.enableAutomaticCalculation(True)


완성된! 이제 이동하여 셀A1에 이미지 파일의 경로를 입력하고 LoadImage를 실행합니다.



항상 활성 시트를 사용하므로 여러 시트가 포함된 통합 문서(?)를 가질 수 있으며 각 시트에 이미지를 로드하여 ODS 파일에 작은 '갤러리'를 만들 수 있습니다.

이 GitHub 리포지토리에서 전체 스크립트를 찾을 수 있습니다.

https://github.com/pc-depp/libreoffice-calc-loadimage

좋은 웹페이지 즐겨찾기