5.7. Компонування зображень

Примітиви малювання з попередньої сторінки наносять геометричні мітки на зображення – лінію, прямокутник, фрагмент тексту. Це охоплює більшість анотацій, які алгоритм має відображати, але не всі. Іноді анотацією є саме зображення: захоплений еталонний кадр для відображення поряд із поточним, мініатюра попереднього знімку в куті попереднього перегляду, раніше збережений шаблон, накладений поверх живого кадру для калібрування. Механізм малювання одного зображення поверх іншого – єдиний метод draw_image() – з достатньою кількістю параметрів для керування позицією, масштабуванням, кольоровою палітрою та прозорістю, які потрібні для справжнього компонування.

5.7.1. Базовий виклик

У найпростішій формі draw_image приймає інший об’єкт Image і позицію для малювання:

reference = image.Image("/sdcard/reference.bmp")
img.draw_image(reference, x=10, y=10)

Призначенням є img; джерелом є reference; верхній лівий піксель джерела розміщується в точці (10, 10) зображення img, а решта пікселів джерела йдуть праворуч і донизу від неї. Пікселі призначення, які покриває джерело, замінюються відповідними пікселями джерела; пікселі за межами площі джерела залишаються незмінними.

Якщо джерело виходить за край призначення, частини, що виступають, мовчки обрізаються – така ж поблажлива поведінка, що й у set_pixel для позицій поза діапазоном. Код програми не зобов’язаний заздалегідь обмежувати позицію розмірами зображення – можна передати потрібну позицію і дозволити методу виконати обрізання самостійно.

5.7.2. Завантаження файлу безпосередньо

draw_image приймає шлях до файлу замість аргументу Image і завантажує файл перед компонуванням:

img.draw_image("/sdcard/reference.bmp", x=10, y=10)

Це виглядає як зручність – один рядок замість двох – і так і є, але різниця не лише в синтаксисі. Створення Image з файлу виділяє буфер для зберігання декодованих пікселів, і цей буфер існує до звільнення збирачем сміття. Передача шляху безпосередньо до draw_image дозволяє модулю декодувати файл у тимчасовий буфер, скомпонувати з нього та звільнити буфер після завершення виклику, без необхідності тримати посилання на окремий Image між кадрами.

5.7.3. Масштабування

Коли джерело і призначення мають різні розміри – низькороздільний знімок компонується на полотно з вищою роздільною здатністю, або мініатюра, яку потрібно розмістити в певній частині кадру – два параметри масштабування дбають про зміну розміру джерела під час малювання:

img.draw_image(reference, x=10, y=10, x_scale=2.0, y_scale=2.0)

x_scale і y_scale – незалежні числа з рухомою комою; передача однакових значень для обох забезпечує рівномірне масштабування, а різних – розтягування або стискання джерела вздовж однієї осі. Масштабування відбувається під час малювання; джерело reference не змінюється.

Бітова маска прапорів підказок визначає, як насправді виконується інтерполяція між пікселями при масштабуванні. image.BILINEAR дає більш плавні результати ціною більших обчислень; image.BICUBIC дає ще більш плавні результати і коштує ще дорожче; за замовчуванням використовується найближчий сусід – найдешевший варіант і правильний вибір, коли джерело вже має роздільну здатність пікселів призначення. Прапори обробки пропорцій – SCALE_ASPECT_KEEP, SCALE_ASPECT_EXPAND, SCALE_ASPECT_IGNORE – визначають, що робити, коли співвідношення сторін джерела не збігається з прямокутником, у який воно малюється.

5.7.4. Змішування з прозорістю (alpha blending)

За замовчуванням draw_image замінює пікселі призначення пікселями джерела. Коли мета – напівпрозоре накладення, щоб призначення просвічувало крізь джерело, параметр alpha контролює спосіб змішування двох зображень. alpha=0 показує лише призначення (джерело не відображається); alpha=255 – значення за замовчуванням, показує лише джерело (повна заміна); проміжні значення змішують їх пропорційно:

img.draw_image(overlay, x=0, y=0, alpha=128)

Окремий аргумент alpha_palette – єдиний механізм прозорості на рівні пікселів у модулі. Він приймає зображення GRAYSCALE, значення якого використовуються як alpha у відповідній позиції джерела – наприклад, теплова карта, прозорість якої змінюється залежно від інтенсивності. Alpha потрібно передавати як окремий аргумент у відтінках сірого; вихідне зображення, що містить власний альфа-канал (наприклад, PNG із прозорістю), не передає його автоматично.

5.7.5. ROI джерела та палітра

Ще два параметри завершують механізм компонування:

  • roi=(x, y, w, h) обмежує джерело підпрямокутником самого себе, щоб лише цей прямокутник компонувався на призначення. Корисно для обрізання в межах того самого виклику без підготовки проміжного обрізаного зображення.

  • color_palette пропускає значення кожного пікселя джерела через таблицю підстановки перед малюванням – той самий механізм, який використовують to_rainbow() та to_ironbow(), відкритий тут для того, щоб накладення можна було палетизувати під час нанесення на призначення без окремого проходу конвертації.

Обидва параметри поєднуються з усіма іншими параметрами виклику: масштабуванням, alpha, аргументом mask на стороні призначення та параметром roi на стороні призначення, що обмежує запис прямокутником призначення.