-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#88 extract media package and add cropping option to media format def…
…inition (#90) Co-authored-by: Thorsten Marx <t.marx@eggheads.de>
- Loading branch information
Showing
15 changed files
with
493 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
35 changes: 35 additions & 0 deletions
35
cms-api/src/main/java/com/github/thmarx/cms/api/media/MediaFormat.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.github.thmarx.cms.api.media; | ||
|
||
/*- | ||
* #%L | ||
* cms-api | ||
* %% | ||
* Copyright (C) 2023 Marx-Software | ||
* %% | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as | ||
* published by the Free Software Foundation, either version 3 of the | ||
* License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public | ||
* License along with this program. If not, see | ||
* <http://www.gnu.org/licenses/gpl-3.0.html>. | ||
* #L% | ||
*/ | ||
|
||
import com.github.thmarx.cms.api.Media; | ||
|
||
/** | ||
* | ||
* @author t.marx | ||
*/ | ||
public record MediaFormat(String name, int width, int height, Media.Format format, boolean compression, boolean cropped) { | ||
public MediaFormat (String name, int width, int height, Media.Format format, boolean compression) { | ||
this(name, width, height, format, compression, false); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>com.github.thmarx.cms</groupId> | ||
<artifactId>cms-parent</artifactId> | ||
<version>2.12.0-SNAPSHOT</version> | ||
</parent> | ||
<artifactId>cms-media</artifactId> | ||
<packaging>jar</packaging> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.github.usefulness</groupId> | ||
<artifactId>webp-imageio</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.github.thmarx.cms</groupId> | ||
<artifactId>cms-api</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.projectlombok</groupId> | ||
<artifactId>lombok</artifactId> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>net.coobird</groupId> | ||
<artifactId>thumbnailator</artifactId> | ||
<version>0.4.20</version> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
126 changes: 126 additions & 0 deletions
126
cms-media/src/main/java/com/github/thmarx/cms/media/Crop.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package com.github.thmarx.cms.media; | ||
|
||
/*- | ||
* #%L | ||
* cms-media | ||
* %% | ||
* Copyright (C) 2023 Marx-Software | ||
* %% | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as | ||
* published by the Free Software Foundation, either version 3 of the | ||
* License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public | ||
* License along with this program. If not, see | ||
* <http://www.gnu.org/licenses/gpl-3.0.html>. | ||
* #L% | ||
*/ | ||
|
||
import java.awt.Graphics2D; | ||
import java.awt.geom.AffineTransform; | ||
import java.awt.geom.Point2D; | ||
import java.awt.image.BufferedImage; | ||
|
||
/** | ||
* code from: http://www.java2s.com/example/java-utility-method/bufferedimage-crop/cropscale-bufferedimage-source-int-width-int-height-63a10.html | ||
* | ||
* @author t.marx | ||
*/ | ||
public class Crop { | ||
|
||
/** | ||
* This function crops the image to the aspect ratio of the width and height and then scales the image to the given | ||
* values | ||
* | ||
* @param source is the image to resize | ||
* @param width is the wanted width | ||
* @param height is the wanted height | ||
* @return a new image with the specified width and height | ||
*/ | ||
public static BufferedImage cropScale(BufferedImage source, int width, int height) { | ||
float aspect = width / height; | ||
BufferedImage tmp = cropToAspectRatio(source, aspect); | ||
tmp = scale(tmp, width, height, false); | ||
return tmp; | ||
} | ||
|
||
public static BufferedImage my_crop (final BufferedImage image, final int target_width, int target_height) { | ||
int width = target_width; | ||
int height = target_height; | ||
|
||
int x = (image.getWidth() / 2) - (width / 2); | ||
int y = (image.getHeight() / 2) - (height / 2); | ||
|
||
if (x < 0 || y < 0) { | ||
x = y = 0; | ||
} | ||
|
||
return image.getSubimage(x, y, width, height); | ||
} | ||
|
||
/** | ||
* Crops a image to a specific aspect ration | ||
* | ||
* @param image is the actual image to crop | ||
* @param aspect is the aspect ratio to convert the image to | ||
* @return a new image with the specified aspect ratio | ||
*/ | ||
public static BufferedImage cropToAspectRatio(BufferedImage image, float aspect) { | ||
int x = 0, y = 0; | ||
int width = image.getWidth(); | ||
int height = image.getHeight(); | ||
|
||
// Check if the width is larger than the height | ||
if (width > height) { | ||
width = (int) (height * aspect); | ||
x = image.getWidth() / 2 - width / 2; | ||
} else { | ||
height = (int) (width * aspect); | ||
y = image.getHeight() / 2 - height / 2; | ||
} | ||
|
||
if (x < 0 || y < 0) { | ||
x = y = 0; | ||
} | ||
|
||
return image.getSubimage(x, y, width, height); | ||
} | ||
|
||
/** | ||
* Resizes a BufferedImage | ||
* | ||
* @param source is the image to resize | ||
* @param width is the wanted width | ||
* @param height is the wanted height | ||
* @param keep_aspect is if the aspect ratio of the image should be kept | ||
* @return the resized image | ||
*/ | ||
public static BufferedImage scale(BufferedImage source, int width, int height, boolean keep_aspect) { | ||
double scale_width = (double) width / source.getWidth(); | ||
double scale_height = (double) height / source.getHeight(); | ||
|
||
// aspect calculation | ||
if (keep_aspect) { | ||
if (scale_width * source.getHeight() > height) { | ||
scale_width = scale_height; | ||
} else { | ||
scale_height = scale_width; | ||
} | ||
} | ||
|
||
BufferedImage tmp = new BufferedImage((int) (scale_width * source.getWidth()), | ||
(int) (scale_height * source.getHeight()), BufferedImage.TYPE_INT_RGB); | ||
Graphics2D g2d = tmp.createGraphics(); | ||
|
||
AffineTransform at = AffineTransform.getScaleInstance(scale_width, scale_height); | ||
g2d.drawRenderedImage(source, at); | ||
g2d.dispose(); | ||
return tmp; | ||
} | ||
} |
141 changes: 141 additions & 0 deletions
141
cms-media/src/main/java/com/github/thmarx/cms/media/MediaManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package com.github.thmarx.cms.media; | ||
|
||
/*- | ||
* #%L | ||
* cms-media | ||
* %% | ||
* Copyright (C) 2023 Marx-Software | ||
* %% | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as | ||
* published by the Free Software Foundation, either version 3 of the | ||
* License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public | ||
* License along with this program. If not, see | ||
* <http://www.gnu.org/licenses/gpl-3.0.html>. | ||
* #L% | ||
*/ | ||
|
||
import com.github.thmarx.cms.api.Media; | ||
import com.github.thmarx.cms.api.SiteProperties; | ||
import com.github.thmarx.cms.api.media.MediaFormat; | ||
import com.github.thmarx.cms.api.theme.Theme; | ||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import lombok.RequiredArgsConstructor; | ||
import net.coobird.thumbnailator.Thumbnails; | ||
import net.coobird.thumbnailator.geometry.Positions; | ||
|
||
/** | ||
* | ||
* @author t.marx | ||
*/ | ||
@RequiredArgsConstructor | ||
public class MediaManager { | ||
|
||
private final Path assetBase; | ||
private final Theme theme; | ||
private final SiteProperties siteProperties; | ||
|
||
private Map<String, MediaFormat> mediaFormats; | ||
private Path tempDirectory; | ||
|
||
public Path resolve (String uri) { | ||
return assetBase.resolve(uri); | ||
} | ||
|
||
public boolean hasMediaFormat (String format) { | ||
return getMediaFormats().containsKey(format); | ||
} | ||
public MediaFormat getMediaFormat (String format) { | ||
return getMediaFormats().get(format); | ||
} | ||
|
||
private Path getTempDirectory() throws IOException { | ||
if (tempDirectory == null) { | ||
tempDirectory = Files.createTempDirectory("cms-media-temp"); | ||
} | ||
return tempDirectory; | ||
} | ||
|
||
public Optional<byte[]> getScaledContent(final String mediaPath, final MediaFormat mediaFormat) throws IOException { | ||
|
||
Path resolve = assetBase.resolve(mediaPath); | ||
|
||
if (Files.exists(resolve)) { | ||
Optional<byte[]> tempContent = getTempContent(mediaPath, mediaFormat); | ||
if (tempContent.isPresent()) { | ||
return tempContent; | ||
} | ||
|
||
Thumbnails.Builder<File> scaleBuilder = Thumbnails | ||
.of(resolve.toFile()) | ||
.size(mediaFormat.width(), mediaFormat.height()) | ||
; | ||
|
||
if (mediaFormat.cropped()) { | ||
scaleBuilder.crop(Positions.CENTER); | ||
} | ||
|
||
byte[] data = Scale.toFormat(scaleBuilder.asBufferedImage(), mediaFormat); | ||
|
||
writeTempContent(mediaPath, mediaFormat, data); | ||
|
||
return Optional.of(data); | ||
} | ||
return Optional.empty(); | ||
} | ||
|
||
public String getTempFilename(final String mediaPath, final MediaFormat mediaFormat) { | ||
var tempFilename = mediaPath.replace("/", "_").replace(".", "_"); | ||
tempFilename += "-" + mediaFormat.name() + Media.fileending4Format(mediaFormat.format()); | ||
|
||
return tempFilename; | ||
} | ||
|
||
private Path writeTempContent(final String mediaPath, final MediaFormat mediaFormat, byte[] content) throws IOException { | ||
var tempFilename = getTempFilename(mediaPath, mediaFormat); | ||
|
||
var tempFile = getTempDirectory().resolve(tempFilename); | ||
Files.deleteIfExists(tempFile); | ||
Files.write(tempFile, content); | ||
|
||
return tempFile; | ||
} | ||
|
||
private Optional<byte[]> getTempContent(final String mediaPath, final MediaFormat mediaFormat) throws IOException { | ||
var tempFilename = getTempFilename(mediaPath, mediaFormat); | ||
|
||
var tempFile = getTempDirectory().resolve(tempFilename); | ||
if (Files.exists(tempFile)) { | ||
return Optional.of(Files.readAllBytes(tempFile)); | ||
} | ||
|
||
return Optional.empty(); | ||
} | ||
|
||
private Map<String, MediaFormat> getMediaFormats() { | ||
|
||
if (mediaFormats == null) { | ||
mediaFormats = new HashMap<>(); | ||
|
||
if (!theme.empty()) { | ||
mediaFormats.putAll(theme.properties().getMediaFormats()); | ||
} | ||
mediaFormats.putAll(siteProperties.getMediaFormats()); | ||
} | ||
|
||
return mediaFormats; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.