Pull to refresh

Готовим скриншоты для документации в GIMP (часть 2)

Developer Soft corporate blog Technical Writing *
В первой части статьи мы рассмотрели script-fu скрипты «Быстрая тень» и «Подрезать уголки» и пообещали показать, как красиво оформить скриншот фрагмента окна. Пришло время исполнить обещанное. Сегодня будем разбирать скрипт «Кадрирование с эффектом волны», который позволяет отсечь часть изображения по волнистым линиям, похожим на синусоиды.

Дополнительно мы рассмотрим, как можно собрать несколько скриптов в один для ускорения выполнения типовых действий над изображением.


Чтобы отсечь часть изображения, надо сначала его выделить. Выделение произвольной формы в GIMP можно нарисовать «от руки» с помощью инструмента «Свободное выделение (Free Select)», но вряд ли получится что-то плавное и красивое. Зато из скрипта мы можем обратиться к процедуре gimp-free-select и передать ей массив координат точек, по которым будет составлено выделение. Ну а чтобы точки выстраивались в некие приятные глазу формы, можно вычислять их координаты по определённым математическим правилам. Итак, пусть пользователь выбрал фрагмент изображения инструментом «Прямоугольное выделение (Rectangle Select)»:



Нам нужно создать новое видоизмененное выделение, основываясь на положении исходного. Затем убрать части изображения, не попавшие внутрь. Ниже приведён код скрипта «Кадрирование с эффектом волны», с комментариями.

(define (script-fu-wave-crop image 
				drawable
				ampl-factor
				reverse-phase)
	(gimp-context-push)
	(gimp-image-set-active-layer image drawable)
	(gimp-image-undo-group-start image)
	; Проверяем наличие выделения
	(if (= (car (gimp-selection-bounds image)) FALSE)
	(gimp-message "Кадрирование не выполнено, так как отсутствует выделение.")
	(let* (
			; Получаем координаты углов выделения
			(selection-box (cdr (gimp-selection-bounds image)))
			; Получаем координаты верхнего левого угла выделения
			(x1 (car selection-box))
			(y1 (cadr selection-box))
			; Получаем координаты нижнего правого угла выделения
			(x2 (caddr selection-box))
			(y2 (cadddr selection-box))
			; Получаем размеры изображения
			(image-width (car (gimp-image-width image)))
		        (image-height (car (gimp-image-height image)))
		)
	; Проверяем, не выделено ли все изображение
	(if (and (= x1 0) (= y1 0) (= x2 image-width) (= y2 image-height))
		(gimp-message "Кадрирование не выполнено, так как выделено все изображение.")
		(let* (
			; Создаем массив координат точек для gimp-free-select.
			; Для каждой точки требуется 2 элемента (x и y координаты)
			(points (cons-array 
				(* (+ (* 2 (- x2 x1)) (* 2 (- y2 y1))) 2)
				'double))
			(i 0)
			; Вычисляем коэффициенты, влияющие на амплитуду волн
			(ampl-x (* (- y2 y1) ampl-factor 0.005))
			(ampl-y (* (- x2 x1) ampl-factor 0.005))
			; В вычислениях понадобится значение "два пи"
			(2pi 6.2832)
			(x x1)
			(y y1)
			)
		; Если нужна обратная фаза
		(if (= reverse-phase TRUE) 
			(begin
				; меняем знак коэфициентов
				(set! ampl-x (- ampl-x))
				(set! ampl-y (- ampl-y))
			)
		)
		; Идем от верхнего левого к верхнему правому углу выделения
		(while (< x x2)
			(aset points i x)
			; Если верхний край выделения 
			; не совпадает с краем изображения,
			(if (> y1 0)
				; то движемся по волнистой линии,
				(aset points (+ i 1) 
					(+ y1 (* ampl-y
					(sin (* 2pi (/ (- x x1) (- x2 x1)))))))
				; иначе - по прямой.
				(aset points (+ i 1) 0)
			)
			(set! i (+ i 2))
			(set! x (+ x 1))
		)
		; Идем от верхнего правого к нижнему правому углу выделения
		(while (< y y2)
			; Если правый край выделения 
			; не совпадает с краем изображения,
			(if (< x2 image-width)
				; то движемся по волнистой линии,
				(aset points i 
					(+ x2 (* ampl-x 
					(sin (- (* 2pi (/ (- y y1) (- y2 y1))))))))
				; иначе - по прямой.
				(aset points i image-width)
			)
			(aset points (+ i 1) y)
			(set! i (+ i 2))
			(set! y (+ y 1))
		)
		; Идем от нижнего правого к нижнему левому углу выделения
		(while (> x x1)
			(aset points i x)
			; Если нижний край выделения 
			; не совпадает с краем изображения,
			(if (< y2 image-height)
				; то движемся по волнистой линии,
				(aset points (+ i 1) 
					(+ y2 (* ampl-y 
					(sin (* 2pi (/ (- x x1) (- x2 x1)))))))
				; иначе - по прямой.
				(aset points (+ i 1) image-height)
			)
			(set! i (+ i 2))
			(set! x (- x 1))
		)
		; Идем от нижнего левого к верхнему левому углу выделения
		(while (> y y1)
			; Если левый край выделения 
			; не совпадает с краем изображения,
			(if (> x1 0)
				; то движемся по волнистой линии,
				(aset points i 
					(+ x1 (* ampl-x 
					(sin (- (* 2pi (/ (- y y1) (- y2 y1))))))))
				; иначе - по прямой.
				(aset points i 0)
			)
			(aset points (+ i 1) y)
			(set! i (+ i 2))
			(set! y (- y 1))
		)
		; Создаем новое выделение по координатам точкек
		(gimp-free-select image i points CHANNEL-OP-REPLACE TRUE FALSE 0)
		; Инвертируем выделение
		(gimp-selection-invert image)
		; Добавляем прозрачность
		(gimp-layer-add-alpha drawable)
		; Удаляем выделенную часть изображения
		(gimp-edit-clear drawable)
		; Снимаем выделение
		(gimp-selection-none image)
		; Отсекаем пустоту
		(plug-in-autocrop 1 image drawable)
		)
	) ) )
	(gimp-image-undo-group-end image)
	(gimp-displays-flush)
	(gimp-context-pop)
)

(script-fu-register "script-fu-wave-crop"
	"Кадрирование с эффектом волны"
	"Откадрировать изображение с эффектом волны по текущему выделению."
	"Василий Пупкин <pupkin@example.com>"
	"ООО Рога и Копыта"
	"2010/10/28"
	"RGB* GRAY*"
	SF-IMAGE      	"Image"                   	0
	SF-DRAWABLE   	"Drawable"                	0
	SF-ADJUSTMENT  "Сила волн (0 - штиль, 10 - цунами)"  '(3 0 10 1 0 0)
	SF-TOGGLE      "Обратная фаза"		       	FALSE
)

(script-fu-menu-register "script-fu-wave-crop"
                         "<Image>/Filters/Мои скрипты")


Подключение скриптов под Windows и Linux рассмотрено в первой части статьи. Настраивать параметры скрипта «Кадрирование с эффектом волны» можно через коэффициент «Сила волн», влияющий на амплитуду синусоиды, и чекбокс «Обратная фаза», меняющий направление волн на противоположное.



Результат последовательного выполнения скриптов «Подрезать уголки», «Кадрирование с эффектом волны» и «Быстрая тень» показан ниже:



При активной работе над иллюстрациями, скорее всего, потребуется вызывать эти скрипты совместно. Чтобы ускорить работу, напишем обёртку «Обработка скриншота» для скриптов «Подрезать уголки», «Кадрирование с эффектом волны» и «Быстрая тень». Для этого определим процедуру script-fu-screenshot-processing, из которой наши скрипты будут вызываться последовательно. Нужно только учесть, что script-fu-cut-corners при работе использует инструменты выделения и удалит текущее выделение. Поэтому следует сохранить текущее выделение в отдельный канал перед вызовом script-fu-cut-corners и восстановить его для script-fu-wave-crop.

(define (script-fu-screenshot-processing image 
				drawable
				cut-corners
				radius
				only-top
				ampl-factor
				reverse-phase)
	(gimp-context-push)
	(gimp-image-set-active-layer image drawable)
	(gimp-image-undo-group-start image)
	(let* (
		(selection-channel nil)
		; Определяем по наличию выделения, требуется ли кадрирование
		(cropping-required (car (gimp-selection-bounds image))) )
		; Если требуется подрезать уголки,
		(if (= cut-corners TRUE) (begin
			; то запоминаем текущее выделение и подрезаем уголки
			(set! selection-channel (car (gimp-selection-save image)))
			(script-fu-cut-corners image drawable radius only-top)
		) )
		; Если требуется кадрирование,
		(if (= cropping-required TRUE) (begin
			; то восстанавливаем исходное выделение и кадрируем по нему
			(if (= cut-corners TRUE) (gimp-selection-load selection-channel))
			(script-fu-wave-crop image drawable ampl-factor reverse-phase)
		) )
		; Используем script-fu-quick-shadow
		(script-fu-quick-shadow image drawable)
	)
	(gimp-image-undo-group-end image)
	(gimp-displays-flush)
	(gimp-context-pop)
)

(script-fu-register "script-fu-screenshot-processing"
	"Обработка скриншота"
	"Очистить уголки, обрезать и добавить тень."
	"Василий Пупкин <pupkin@example.com>"
	"ООО Рога и Копыта"
	"2010/10/28"
	"RGB* GRAY*"
	SF-IMAGE      	"Image"                   	0
	SF-DRAWABLE   	"Drawable"                	0
	SF-TOGGLE	"Очищать уголки"		TRUE
	SF-ADJUSTMENT 	"Радиус (0 - 20 пикселей)"	'(8 0 20 1 10 0 0)
	SF-TOGGLE	"Только верхние"		FALSE
	SF-ADJUSTMENT  "Сила волн (0 - штиль, 10 - цунами)"  '(3 0 10 1 0 0)
	SF-TOGGLE      "Обратная фаза"		       	FALSE
	
)

(script-fu-menu-register "script-fu-screenshot-processing"
                         "<Image>/Filters/Мои скрипты")


В результате параметры скриптов собраны в одном окне.



Тот факт что GIMP помнит настройки, использованные при предыдущем выполнении скрипта, значительно ускоряет работу. Нажав Ctrl+F, можно выполнить последний вызванный скрипт, пропустив диалог настроек.

Обратите внимание — при кадрировании учитывается положение краёв выделения относительно краёв изображения. Если исходное выделение идет по краю изображения (или выходит за его пределы), соответствующий сегмент нового выделения проходит по прямой, по краю изображения. Можно вырезать части изображения, как с краёв, так и из середины:

Tags:
Hubs:
Total votes 127: ↑118 and ↓9 +109
Views 18K
Comments Comments 14

Information

Founded
1998
Location
Россия
Website
www.developersoft.ru
Employees
201–500 employees
Registered