Как программно создать генератор миниатюр YouTube на Java
Введение
Цель этого документа - продемонстрировать использование API некоторых составных инструментов Aspose.PSD для Java на реальном примере. В этой статье будет описан простой Java-программный код, который генерирует миниатюры YouTube для канала DW Documentary. Этот канал был выбран из реального мира, потому что его миниатюры довольно стандартны и они иллюстрируют использование нескольких популярных составных инструментов Aspose.PSD для Java (например, эффект тени, радиальная градиентная заливка, рисование текста и фигур):
Как это работает в двух словах
Простая Java-программа принимает на вход два аргумента: подпись и изображение. В ОЗУ генерируется документ Photoshop (PSD) из этого ввода с использованием Aspose.PSD для Java. Затем программа преобразует документ из PSD в формат PNG, чтобы получить миниатюру YouTube размером 1280x720 пикселей. Выходное изображение выглядит примерно следующим образом:
Технические требования
Для успешного запуска кода этой статьи требуются следующие технологии:
- Java 6+
- Aspose.PSD для Java (последняя версия)
Начало работы
Как уже упоминалось, программа использует в ОЗУ PSD для создания миниатюры. Так что давайте создадим документ PSD, чтобы начать:
PsdImage psdImage = new PsdImage(1280, 720);
Если внимательно посмотреть на миниатюру YouTube выше, можно заметить, что она состоит из нескольких компонентов:
- фоновое изображение (печатная маска)
- радиальный градиент psd (выделяет область в верхнем правом углу)
- логотип с эффектом тени
- подпись и простое рисование (синий прямоугольник)
Давайте поглубже посмотрим, как реализовать каждый из этих компонентов с использованием 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 шагов:
- Необходимо объявить настройки заполнения градиента, поскольку заранее определенных не существует. Минимальная требуемая конфигурация выглядит следующим образом (предполагается, что обязательными свойствами являются тип градиента, масштаб, цвет и точки прозрачности):
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); |
- Когда конфигурация завершена, добавьте слой заполнения градиентом вместе с его настройками в 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 и объяснили, как использовать некоторые из наиболее популярных составных инструментов, такие как эффект тени, радиальная градиентная заливка, рисование текста и фигур.
Полный Пример
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(); | |
} | |
} |