From 963986753fc2e6444bdde8d931b39b47b50dc2bd Mon Sep 17 00:00:00 2001 From: Thorsten Marx Date: Sun, 31 May 2026 12:43:16 +0200 Subject: [PATCH] fix a file naming issue in crop command --- .../processor/ImageProcessorFactory.java | 2 +- .../cms/media/processor/LibVipsProcessor.java | 76 ++++++++++++++----- 2 files changed, 57 insertions(+), 21 deletions(-) diff --git a/cms-media/src/main/java/com/condation/cms/media/processor/ImageProcessorFactory.java b/cms-media/src/main/java/com/condation/cms/media/processor/ImageProcessorFactory.java index f5bc47ff..acc9a1e1 100644 --- a/cms-media/src/main/java/com/condation/cms/media/processor/ImageProcessorFactory.java +++ b/cms-media/src/main/java/com/condation/cms/media/processor/ImageProcessorFactory.java @@ -68,7 +68,7 @@ private ImageProcessor resolve() { private ImageProcessor create(String name) { return switch (name) { - case "libvips" -> new LibVipsProcessor(binPath != null ? binPath : "vips"); + case "libvips" -> new LibVipsProcessor(binPath); case "imagemagick" -> new ImageMagickProcessor(binPath); case "imageio" -> new ImageIOProcessor(); default -> throw new IllegalArgumentException("Unknown image processor: '" + name + "'"); diff --git a/cms-media/src/main/java/com/condation/cms/media/processor/LibVipsProcessor.java b/cms-media/src/main/java/com/condation/cms/media/processor/LibVipsProcessor.java index d926d020..bdcf9781 100644 --- a/cms-media/src/main/java/com/condation/cms/media/processor/LibVipsProcessor.java +++ b/cms-media/src/main/java/com/condation/cms/media/processor/LibVipsProcessor.java @@ -20,33 +20,38 @@ * along with this program. If not, see . * #L% */ - import com.condation.cms.api.media.MediaFormat; import com.condation.cms.media.CropCalculator.CropArea; +import com.google.common.base.Strings; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import lombok.extern.slf4j.Slf4j; /** - * Image processor using libvips CLI ({@code vips} command). - * Crop is applied via {@code vips extract_area}, scaling via {@code vips thumbnail}. + * Image processor using libvips CLI ({@code vips} command). Crop is applied via + * {@code vips extract_area}, scaling via {@code vips thumbnail}. */ @Slf4j public class LibVipsProcessor implements ImageProcessor { private Boolean available = null; - private final String binPath; - - public LibVipsProcessor () { - this("vips"); - } - public LibVipsProcessor (String binPath) { - this.binPath = binPath; - } - + private final String binPath; + + public LibVipsProcessor() { + this("vips"); + } + + public LibVipsProcessor(String binPath) { + if (Strings.isNullOrEmpty(binPath)) { + binPath = "vips"; + } + this.binPath = binPath; + } + @Override public String name() { return "libvips"; @@ -78,7 +83,14 @@ public void process(Path source, Path target, MediaFormat format, CropArea crop) Path inputForScale = source; if (crop != null) { - inputForScale = target.resolveSibling(target.getFileName() + ".crop.tmp"); + String fileName = target.getFileName().toString(); + String ext = fileName.substring(fileName.lastIndexOf('.')); + + inputForScale = Files.createTempFile( + target.getParent(), + "crop-", + ext + ); runExtractArea(source, inputForScale, crop); } @@ -86,7 +98,7 @@ public void process(Path source, Path target, MediaFormat format, CropArea crop) runThumbnail(inputForScale, target, format); } finally { if (crop != null) { - java.nio.file.Files.deleteIfExists(inputForScale); + Files.deleteIfExists(inputForScale); } } } @@ -119,8 +131,8 @@ private void runThumbnail(Path source, Path target, MediaFormat format) throws I } /** - * libvips determines output format from the file extension. - * The target Path already has the correct extension from MediaUtils. + * libvips determines output format from the file extension. The target Path + * already has the correct extension from MediaUtils. */ private String formatTarget(Path target, MediaFormat format) { return target.toString(); @@ -128,14 +140,38 @@ private String formatTarget(Path target, MediaFormat format) { private void runCommand(List cmd) throws IOException { log.debug("libvips: {}", String.join(" ", cmd)); + + Process process = null; + try { - int exit = new ProcessBuilder(cmd) + process = new ProcessBuilder(cmd) .redirectErrorStream(true) - .start() - .waitFor(); + .start(); + + String output; + try (var reader = process.inputReader()) { + output = reader.lines() + .reduce("", (a, b) -> a + System.lineSeparator() + b); + } + + int exit = process.waitFor(); + if (exit != 0) { - throw new IOException("vips exited with code " + exit + " for command: " + String.join(" ", cmd)); + throw new IOException(""" + vips exited with code %d + + Command: + %s + + Output: + %s + """.formatted(exit, String.join(" ", cmd), output)); + } + + if (!output.isBlank()) { + log.debug("vips output:\n{}", output); } + } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IOException("vips interrupted", e);