Skip to content

Commit

Permalink
Added image conversion commands
Browse files Browse the repository at this point in the history
  • Loading branch information
leprinco committed Nov 18, 2024
1 parent de07429 commit 4a4dc93
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

public class MimeTypeUtil {
Expand All @@ -15,7 +14,7 @@ public static String determineMimeType(File file) {
try {
String mimeType = Files.probeContentType(file.toPath());
if (mimeType == null) {
String suffix = FilenameUtils.getExtension(file.getName()).toLowerCase();
String suffix = FilenameUtils.getExtension(file.getName());
mimeType = determineMimeType(suffix);
}
return mimeType;
Expand All @@ -28,33 +27,45 @@ public static String determineMimeType(File file) {

public static String determineMimeType(String suffix) {
String mimeType = null;
if (suffix.endsWith("apng")) {
mimeType = "image/apng";
}
else if (suffix.endsWith("png")) {
mimeType = "image/png";
}
else if (suffix.endsWith("jpg")) {
mimeType = "image/jpg";
}
else if (suffix.endsWith("mp3")) {
mimeType = "audio.mp3";
}
else if (suffix.endsWith("ogg")) {
mimeType = "audio.ogg";
}
else if (suffix.endsWith("mp4")) {
mimeType = "video/mp4";
}
else if (suffix.endsWith("f4v")) {
mimeType = "video/mp4";
}
else if (suffix.endsWith("avi")) {
mimeType = "video/avi";
}
else {
LOG.error("Failed to determine mime type for " + suffix);
if (suffix != null) {
suffix = suffix.toLowerCase();

if (suffix.endsWith("apng")) {
mimeType = "image/apng";
}
else if (suffix.endsWith("png")) {
mimeType = "image/png";
}
else if (suffix.endsWith("jpg")) {
mimeType = "image/jpg";
}
else if (suffix.endsWith("mp3")) {
mimeType = "audio.mp3";
}
else if (suffix.endsWith("ogg")) {
mimeType = "audio.ogg";
}
else if (suffix.endsWith("mp4")) {
mimeType = "video/mp4";
}
else if (suffix.endsWith("f4v")) {
mimeType = "video/mp4";
}
else if (suffix.endsWith("avi")) {
mimeType = "video/avi";
}
else {
LOG.error("Failed to determine mime type for " + suffix);
}
}
return mimeType;
}

/**
* Return audio, video or image depending on extension
*/
public static String determineBaseType(String suffix) {
String mimeType = determineMimeType(suffix);
return mimeType != null ? mimeType.substring(0, 5): null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ public class VideoConversionCommand {

public static final int TYPE_FILE = 1;
public static final int TYPE_FFMEPG = 2;
public static final int TYPE_IMAGE = 3;

public static enum ImageOp {
ROTATE_90, ROTATE_90_CCW, ROTATE_180
}

private String name;
private String command;
Expand Down Expand Up @@ -51,6 +56,21 @@ public VideoConversionCommand setFFmpegArgs(String args) {
this.command = args;
return this;
}
public VideoConversionCommand setImageArgs(ImageOp op) {
this.type = TYPE_IMAGE;
this.command = op.name();
return this;
}

public boolean isActiveForType(String mediaType) {
if ("video".equalsIgnoreCase(mediaType)) {
return type == TYPE_FILE || type == TYPE_FFMEPG;
}
else if ("image".equalsIgnoreCase(mediaType)) {
return type == TYPE_IMAGE;
}
return false;
}

@Override
public String toString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

import javax.imageio.ImageIO;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
Expand Down Expand Up @@ -53,7 +52,6 @@ public static int convertFontPosture(String posture) {
return Font.PLAIN;
}

@SuppressWarnings("unused")
public static BufferedImage loadImage(File file) throws IOException {
if (!file.exists()) {
throw new FileNotFoundException("File not found " + file.getAbsolutePath());
Expand All @@ -67,22 +65,27 @@ public static BufferedImage loadImage(File file) throws IOException {
}
}

@SuppressWarnings("unused")
public static BufferedImage rotateLeft(BufferedImage image) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
return create(image, -Math.PI / 2, gc);
}

@SuppressWarnings("unused")
public static BufferedImage rotateRight(BufferedImage image) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
return create(image, Math.PI / 2, gc);
}

public static BufferedImage rotate180(BufferedImage image) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
return create(image, Math.PI, gc);
}

private static BufferedImage create(BufferedImage image, double angle, GraphicsConfiguration gc) {
double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle));
int w = image.getWidth(), h = image.getHeight();
Expand All @@ -97,14 +100,12 @@ private static BufferedImage create(BufferedImage image, double angle, GraphicsC
return result;
}

@SuppressWarnings("unused")
public static void setDefaultColor(GraphicsContext g, String fontColor) {
Paint paint = Paint.valueOf(fontColor);
g.setStroke(paint);
// setRendingHints(g);
}

@SuppressWarnings("unused")
public static void applyAlphaComposites(BufferedImage image, float alphaWhite, float alphaBlack) {
Graphics g = image.getGraphics();
int imageWidth = image.getWidth();
Expand All @@ -131,7 +132,6 @@ public static void applyAlphaComposites(BufferedImage image, float alphaWhite, f
}
}

@SuppressWarnings("unused")
public static void drawBorder(GraphicsContext g, int strokeWidth, int width, int height) {
if (strokeWidth > 0) {
g.setStroke(g.getFill());
Expand Down Expand Up @@ -173,7 +173,6 @@ public static BufferedImage crop(BufferedImage image, int xRatio, int yRatio) {
return image.getSubimage(x, y, targetWidth, targetHeight);
}

@SuppressWarnings("unused")
public static BufferedImage blurImage(BufferedImage originalImage, int radius) {
GaussianFilter filter = new GaussianFilter(radius);
return filter.filter(originalImage, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import de.mephisto.vpin.restclient.frontend.FrontendType;
import de.mephisto.vpin.restclient.util.FileUtils;
import de.mephisto.vpin.restclient.util.SystemCommandExecutor;
import de.mephisto.vpin.restclient.video.VideoConversionCommand;
import de.mephisto.vpin.restclient.video.VideoOperation;
import de.mephisto.vpin.restclient.video.VideoConversionCommand;
import de.mephisto.vpin.restclient.video.VideoConversionCommand.ImageOp;
import de.mephisto.vpin.server.frontend.FrontendService;
import de.mephisto.vpin.server.games.Game;
import de.mephisto.vpin.server.util.ImageUtil;
import edu.umd.cs.findbugs.annotations.NonNull;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
Expand All @@ -18,6 +20,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
Expand All @@ -30,6 +33,7 @@ public class VideoConverterService implements InitializingBean {

private final List<VideoConversionCommand> commands = new ArrayList<>();


@Autowired
private FrontendService frontendService;

Expand Down Expand Up @@ -78,6 +82,9 @@ else if (command.getType() == VideoConversionCommand.TYPE_FFMEPG) {
String[] args = StringUtils.split(command.getCommand());
return convertWithFfmpeg(args, mediaFile);
}
else if (command.getType() == VideoConversionCommand.TYPE_IMAGE) {
return convertWithImageUtils(command.getCommand(), mediaFile);
}
else {
LOG.warn("Not supported implementation of command {} for {}", command.getClass().getName(), command.getName());
}
Expand Down Expand Up @@ -144,6 +151,29 @@ private String convertWithFfmpeg(String[] args, File mediaFile) throws Exception
return null;
}

private String convertWithImageUtils(String command, File mediaFile) {
try {
BufferedImage img = ImageUtil.loadImage(mediaFile);
switch (ImageOp.valueOf(command)) {
case ROTATE_90:
img = ImageUtil.rotateRight(img);
break;
case ROTATE_90_CCW :
img = ImageUtil.rotateLeft(img);
break;
case ROTATE_180:
img = ImageUtil.rotate180(img);
break;
}

ImageUtil.write(img, mediaFile);
return null;
}
catch (Exception e) {
return e.getMessage();
}
}

@Override
public void afterPropertiesSet() throws Exception {
commands.clear();
Expand Down Expand Up @@ -183,6 +213,11 @@ public boolean accept(File dir, String name) {
commands.add(new VideoConversionCommand("Rotate 180°").setFFmpegArgs("-vf \"transpose=2,transpose=2\""));
commands.add(new VideoConversionCommand("Mute Volume").setFFmpegArgs("-c:v copy -an"));
}

// add image commandes
commands.add(new VideoConversionCommand("Rotate Clockwise 90°").setImageArgs(ImageOp.ROTATE_90));
commands.add(new VideoConversionCommand("Rotate Counter Clockwise 90°").setImageArgs(ImageOp.ROTATE_90_CCW));
commands.add(new VideoConversionCommand("Rotate 180°").setImageArgs(ImageOp.ROTATE_180));
}

public List<VideoConversionCommand> getCommandList() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -804,20 +804,31 @@ public void changed(ObservableValue<? extends FrontendMediaItemRepresentation> o

WidgetFactory.disposeMediaPane(mediaPane);
infoBtn.setDisable(mediaItem == null);
conversionMenu.setDisable(mediaItem == null || !mediaItem.getName().endsWith(".mp4"));
renameBtn.setDisable(mediaItem == null);
downloadAssetBtn.setDisable(mediaItem == null);

if (mediaItem == null) {
conversionMenu.setDisable(true);

Label label = new Label("No media selected");
label.setStyle("-fx-font-size: 14px;-fx-text-fill: #444444;");
label.setUserData(mediaItem);
mediaPane.setCenter(label);
return;
}

// else
String mimeType = mediaItem.getMimeType();
String baseType = mimeType.split("/")[0];

boolean atleastone = false;
for (MenuItem item : conversionMenu.getItems()) {
VideoConversionCommand cmd = (VideoConversionCommand) item.getUserData();
boolean visible = cmd.isActiveForType(baseType);
atleastone |= visible;
item.setVisible(visible);
}
conversionMenu.setDisable(!atleastone);

String url = client.getURL(mediaItem.getUri()) + "/" + URLEncoder.encode(mediaItem.getName(), Charset.defaultCharset());
LOG.info("Loading " + url);

Expand Down Expand Up @@ -857,6 +868,7 @@ else if (baseType.equals("video")) {
conversionMenu.setVisible(!commandList.isEmpty());
for (VideoConversionCommand command : commandList) {
MenuItem item = new MenuItem(command.getName());
item.setUserData(command);
conversionMenu.getItems().add(item);
item.setOnAction(new EventHandler<ActionEvent>() {
@Override
Expand Down

0 comments on commit 4a4dc93

Please sign in to comment.