Как программно создать генератор миниатюр YouTube на Java

Введение

Цель этого документа - продемонстрировать использование API некоторых составных инструментов Aspose.PSD для Java на реальном примере. В этой статье будет описан простой Java-программный код, который генерирует миниатюры YouTube для канала DW Documentary. Этот канал был выбран из реального мира, потому что его миниатюры довольно стандартны и они иллюстрируют использование нескольких популярных составных инструментов Aspose.PSD для Java (например, эффект тени, радиальная градиентная заливка, рисование текста и фигур):

todo:image_alt_text

Как это работает в двух словах

Простая Java-программа принимает на вход два аргумента: подпись и изображение. В ОЗУ генерируется документ Photoshop (PSD) из этого ввода с использованием Aspose.PSD для Java. Затем программа преобразует документ из PSD в формат PNG, чтобы получить миниатюру YouTube размером 1280x720 пикселей. Выходное изображение выглядит примерно следующим образом:

todo:image_alt_text

Технические требования

Для успешного запуска кода этой статьи требуются следующие технологии:

Начало работы

Как уже упоминалось, программа использует в ОЗУ PSD для создания миниатюры. Так что давайте создадим документ PSD, чтобы начать:

PsdImage psdImage = new PsdImage(1280, 720);

Если внимательно посмотреть на миниатюру YouTube выше, можно заметить, что она состоит из нескольких компонентов:

  1. фоновое изображение (печатная маска)
  2. радиальный градиент psd (выделяет область в верхнем правом углу)
  3. логотип с эффектом тени
  4. подпись и простое рисование (синий прямоугольник)

Давайте поглубже посмотрим, как реализовать каждый из этих компонентов с использованием Aspose.PSD для Java в следующих разделах.

1. Добавление фонового изображения

Порядок слоев важен. Поэтому фоновое изображение должно быть добавлено первым, чтобы не перекрывать другие слои. Обратите внимание, что в настоящее время поддерживаются только растровые форматы файлов.

1.1. Добавление фонового изображения в слой Photoshop

Чтобы добавить растровое изображение в PSD, поток ввода должен быть передан как аргумент во время создания слоя (смотрите больше примеров загрузки растровых изображений):

Layer bgImageLayer = new Layer(new FileInputStream(bgImagePath));
psdImage.addLayer(bgImageLayer);

1.2. Приспособление фонового изображения к холсту

Следующие 2 действия (изменение размера, позиционирование) полезны в тех случаях, когда размер изображения отличается от размера холста, хотя изображение в этой статье имеет такой же размер, как и холст (предположим, что это не всегда так).

Убедитесь, что загруженное изображение соответствует размеру холста (больше примеров изменения размера можно найти [здесь](https://docs.aspose.com/display/psdnet/Crop%2C+Rotate+and+Resize+Images#Crop, Rotate and Resize Images-ResizingImages)):

bgImageLayer.resize(psdImage.getWidth(), psdImage.getHeight());

После изменения размера позиция изображения изменяется. Поэтому, чтобы сбросить позицию изображения, переместите измененное изображение в верхний левый угол:

bgImageLayer.setTop(0);
bgImageLayer.setRight(psdImage.getWidth());
bgImageLayer.setBottom(psdImage.getHeight());
bgImageLayer.setLeft(0);

2. Добавление радиального градиента

Существует два способа добавления радиального градиента: используя:

  • эффект наложения градиента (/psd/ru/java/aspose-psd-for-java-20-4-release-notes/#-~ - text = psdjava-163) на существующий слой (эффект градиента, который связывается с текущим слоем и применяется к его содержимому)
  • новый слой заливки градиентом (отдельный слой, который сохраняет самостоятельную конфигурацию градиента)

Для этого примера достаточно использовать эффект наложения градиента. Однако чтобы сделать эту статью более интересной и полезной, используется слой заполнения градиентом, поскольку все эффекты слоя применяются аналогичным образом, и в следующем разделе будет использован еще один эффект слоя.

2.1. Добавление слоя заполнения радиальным градиентом

Процесс добавления нового слоя заполнения градиентом состоит из следующих 2 шагов:

  1. Необходимо объявить настройки заполнения градиента, поскольку заранее определенных не существует. Минимальная требуемая конфигурация выглядит следующим образом (предполагается, что обязательными свойствами являются тип градиента, масштаб, цвет и точки прозрачности):
GradientFillSettings gradientFillSettings = new GradientFillSettings();
gradientFillSettings.setGradientType(GradientType.Radial);
gradientFillSettings.setScale(150);
gradientFillSettings.setTransparencyPoints(new IGradientTransparencyPoint[]{
new GradientTransparencyPoint(0, 3072, 50),
new GradientTransparencyPoint(85, 0, 65),
});
gradientFillSettings.setColorPoints(new IGradientColorPoint[]{
new GradientColorPoint(Color.fromArgb(0, 15, 30), 0, 50),
});

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

Чтобы перевернуть заполнение градиента и слегка сдвинуть его в верхний правый угол, используйте соответствующие необязательные свойства:

gradientFillSettings.setReverse(true);
gradientFillSettings.setHorizontalOffset(psdImage.getWidth() / 10d);
gradientFillSettings.setVerticalOffset(psdImage.getHeight() / -1.5);
  1. Когда конфигурация завершена, добавьте слой заполнения градиентом вместе с его настройками в PSD:
FillLayer gradientLayer = FillLayer.createInstance(FillType.Gradient);
gradientLayer.setFillSettings(gradientFillSettings);
psdImage.addLayer(gradientLayer);

Добавление логотипа с тенью

Тень - это эффект, который позволяет добавить пользовательскую тень вдоль контура объекта (изображение, текст и т. д.).

3.1. Добавление логотипа в слой Photoshop

Тот же подход, что и в разделе 1.1., может быть использован для добавления логотипа в PSD:

Layer logoLayer = new Layer(new FileInputStream(logoPath));
psdImage.addLayer(logoLayer);

3.2. Позиционирование логотипа

Загруженное изображение по умолчанию тесно прилегает к верхнему левому углу. Однако для того, чтобы логотип выглядел как оригинальная миниатюра YouTube на канале, нужно добавить некоторые отступы от краев, чтобы изменить позицию изображения:

final int logoShift = 60;
logoLayer.setTop(logoLayer.getTop() + logoShift);
logoLayer.setRight(logoLayer.getRight() + logoShift);
logoLayer.setBottom(logoLayer.getBottom() + logoShift);
logoLayer.setLeft(logoLayer.getLeft() + logoShift);

3.3. Добавление эффекта тени к логотипу

Логотип может быть невидимым, если используется светлое фоновое изображение. Поэтому желательно добавить эффект тени к логотипу через свойство параметров наложения (смотрите больше примеров создания теней):

DropShadowEffect dropShadowEffect = logoLayer.getBlendingOptions().addDropShadow();
dropShadowEffect.setDistance(0);
dropShadowEffect.setSize(10);
dropShadowEffect.setOpacity((byte)50);

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

4. Добавление рисунка текста и фигуры

3.1. Создание графического слоя

Рисование не поддерживается обычным слоем непосредственно. Поэтому использован движок графики наряду со слоем, чтобы предоставить API для рисования (смотрите больше примеров рисования):

Layer graphicLayer = psdImage.addRegularLayer(); Graphics graphics = new Graphics(graphicLayer);

3.2. Рисование многострочного текста

Опытный читатель может спросить: почему бы не использовать текстовый слой для добавления текста? Что касается текста, в данном случае редактирование текста не требуется, потому что PSD создается с нуля каждый раз; настройка шрифта не поддерживается API текста еще (v20.6 на момент написания).

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

Layer graphicLayer = psdImage.addRegularLayer();
Graphics graphics = new Graphics(graphicLayer);
Font georgiaFont = new Font("Georgia Pro Semibold", 105, FontStyle.Regular, GraphicsUnit.Pixel);
int linesCount = text.split(System.getProperty("line.separator")).length;
int textHeight = (int)(georgiaFont.getSize() * 1.15 * linesCount + 3);
graphics.drawString(text, georgiaFont, new SolidBrush(Color.getWhite()),
110, psdImage.getHeight() - 40 - 15 - textHeight);

Где 1.15 - это высота строки, 3 - отступ текста.

3.3. Рисование прямоугольника

Прямоугольники также легко рисовать даже с градиентной кистью (просто установите область для рисования и диапазон цветов). Когда известна высота текста, вычисляется размер и позиция прямоугольника. Чтобы нарисовать заполненный прямоугольник в psd (не просто рамку), вызовите соответствующий метод из движка графики со всем этим:

Rectangle rectangle = new Rectangle(60,
psdImage.getHeight() - 40 - 25 - textHeight - 15, 40, 25 + textHeight + 15);
LinearGradientBrush linearGradientBrush = new LinearGradientBrush(
new Point(rectangle.getLeft(), rectangle.getTop()),
new Point(rectangle.getLeft(), rectangle.getBottom()),
Color.fromArgb(0, 106, 176), Color.fromArgb(0, 152, 255));
graphics.fillRectangle(linearGradientBrush, rectangle);

Где 40, 15, 25 - отступы.

Результат

Итак, формирование миниатюры завершено. Теперь пришло время экспортировать миниатюру в растровый формат файла (например, PNG) для последующего распространения:

psdImage.save(outThumbnailPath, new PngOptions());

Заключение

В этой статье мы создали генератор миниатюр YouTube для канала DW Documentary и объяснили, как использовать некоторые из наиболее популярных составных инструментов, такие как эффект тени, радиальная градиентная заливка, рисование текста и фигур.

Полный Пример

Скачайте Aspose.PSD SDK

public static void main(String[] args) throws IOException, java.awt.FontFormatException
{
String text = "Printing out\r\nthe world";
String bgImagePath = "background_image.png";
final String logoPath = "DW-Logo-white.png";
final String outThumbnailPath = "thumbnail.png";
final String georgiaFontPath = "GeorgiaPro-SemiBold.ttf";
// Register a custom font
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment()
.registerFont(java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT,
new File(georgiaFontPath)));
// Create a new Photoshop document with Full HD 1080p resolution
PsdImage psdImage = new PsdImage(1280, 720);
try
{
// Load a background image as a layer and bind one to the document
Layer bgImageLayer = new Layer(new FileInputStream(bgImagePath));
psdImage.addLayer(bgImageLayer);
// Fit the background image size to the document size
bgImageLayer.resize(psdImage.getWidth(), psdImage.getHeight());
// Reset the position of the layer (bind to upper left corner)
bgImageLayer.setTop(0);
bgImageLayer.setRight(psdImage.getWidth());
bgImageLayer.setBottom(psdImage.getHeight());
bgImageLayer.setLeft(0);
// Configure the radial gradient
GradientFillSettings gradientFillSettings = new GradientFillSettings();
gradientFillSettings.setGradientType(GradientType.Radial);
gradientFillSettings.setScale(150);
gradientFillSettings.setTransparencyPoints(new IGradientTransparencyPoint[]{
new GradientTransparencyPoint(0, 3072, 50),
new GradientTransparencyPoint(85, 0, 65),
});
gradientFillSettings.setColorPoints(new IGradientColorPoint[]{
new GradientColorPoint(Color.fromArgb(0, 15, 30), 0, 50),
});
gradientFillSettings.setReverse(true);
gradientFillSettings.setHorizontalOffset(psdImage.getWidth() / 10d);
gradientFillSettings.setVerticalOffset(psdImage.getHeight() / -1.5);
// Bind the gradient fill layer to the document
FillLayer gradientLayer = FillLayer.createInstance(FillType.Gradient);
gradientLayer.setFillSettings(gradientFillSettings);
psdImage.addLayer(gradientLayer);
// Add a logo as a layer and bind one to the document
Layer logoLayer = new Layer(new FileInputStream(logoPath));
psdImage.addLayer(logoLayer);
// Move the logo 60px away from upper left corner
final int logoShift = 60;
logoLayer.setTop(logoLayer.getTop() + logoShift);
logoLayer.setRight(logoLayer.getRight() + logoShift);
logoLayer.setBottom(logoLayer.getBottom() + logoShift);
logoLayer.setLeft(logoLayer.getLeft() + logoShift);
// Add a drop shadow effect to the logo
DropShadowEffect dropShadowEffect = logoLayer.getBlendingOptions().addDropShadow();
dropShadowEffect.setDistance(0);
dropShadowEffect.setSize(10);
dropShadowEffect.setOpacity((byte)50);
// Draw customized text
Layer graphicLayer = psdImage.addRegularLayer();
Graphics graphics = new Graphics(graphicLayer);
Font georgiaFont = new Font("Georgia Pro Semibold", 105, FontStyle.Regular, GraphicsUnit.Pixel);
int linesCount = text.split(System.getProperty("line.separator")).length;
int textHeight = (int)(georgiaFont.getSize() * 1.15 * linesCount + 3);
graphics.drawString(text, georgiaFont, new SolidBrush(Color.getWhite()),
110, psdImage.getHeight() - 40 - 15 - textHeight);
// Draw a rectangle filled with a blue gradient
Rectangle rectangle = new Rectangle(60,
psdImage.getHeight() - 40 - 25 - textHeight - 15, 40, 25 + textHeight + 15);
LinearGradientBrush linearGradientBrush = new LinearGradientBrush(
new Point(rectangle.getLeft(), rectangle.getTop()),
new Point(rectangle.getLeft(), rectangle.getBottom()),
Color.fromArgb(0, 106, 176), Color.fromArgb(0, 152, 255));
graphics.fillRectangle(linearGradientBrush, rectangle);
// Export the document to PNG file format
psdImage.save(outThumbnailPath, new PngOptions());
}
finally
{
psdImage.dispose();
}
}