Coverage Summary for Class: ImageConverter (org.kitodo.imagemanagement)
Class |
Class, %
|
Method, %
|
Line, %
|
ImageConverter |
100%
(1/1)
|
100%
(7/7)
|
67,6%
(25/37)
|
/*
* (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
*
* This file is part of the Kitodo project.
*
* It is licensed under GNU General Public License version 3 or later.
*
* For the full copyright and license information, please read the
* GPL3-License.txt file that was distributed with this source code.
*/
package org.kitodo.imagemanagement;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.im4java.core.IMOperation;
import org.kitodo.api.imagemanagement.ImageFileFormat;
import org.kitodo.config.KitodoConfig;
import org.kitodo.config.enums.ParameterImageManagement;
/**
* An image conversion task. One conversion task can create multiple result
* images with different properties. This is done in one single ImageMagick
* call, reading and decoding the source image into memory only once.
*/
class ImageConverter {
private static final Logger logger = LogManager.getLogger(ImageConverter.class);
/**
* ImageMagick file type prefix to request no file being written.
*/
private static final String FORMAT_OFF = "NULL:";
/**
* ImageMagick option {@code -units}. Note that {@code -units} must be set
* <i>before</i> the operation whose value shall be interpreted in this
* unit.
*
* @see "https://www.imagemagick.org/script/command-line-options.php?#units"
*/
private static final String OPTION_UNITS = "-units";
/**
* ImageMagick option {@code -depth}’s value {@code PixelsPerInch}.
*
* @see "https://www.imagemagick.org/script/command-line-options.php?#units"
*/
private static final String OPTION_UNITS_TYPE_PIXELSPERINCH = "PixelsPerInch";
/**
* Path to read the source image from.
*/
private final String source;
/**
* Conversion results to create.
*/
private final Collection<FutureDerivative> results = new LinkedList<>();
/**
* Creates a new image conversion task.
*
* @param imageFileUri
* source image to convert
*/
ImageConverter(URI imageFileUri) {
source = uriToPath(imageFileUri);
}
/**
* Defines another result of the conversion process.
*
* @param path
* output file URI
* @return the conversion result object to define conversion properties
*/
FutureDerivative addResult(URI path) {
FutureDerivative futureDerivative = new FutureDerivative(uriToPath(path));
results.add(futureDerivative);
return futureDerivative;
}
/**
* Defines another result of the conversion process.
*
* @param path
* output file URI
* @param resultFileFormat
* image format to generate
* @return the conversion result object to define conversion properties
*/
FutureDerivative addResult(URI path, ImageFileFormat resultFileFormat) {
FutureDerivative futureDerivative = new FutureDerivative(uriToPath(path), resultFileFormat);
results.add(futureDerivative);
return futureDerivative;
}
/**
* Reads further arguments from the configuration and passes them to
* ImageMagick. Arguments can be added to the configuration with the prefix
* {@code ImageManagement.param.}.
*
* <p>
* Examples:
*
* <p>
* <table border=2 cellspacing=1 cellpadding=2>
* <tr>
* <th>Configuration entry</th>
* <th>Arguments sent to ImageMagick</th>
* </tr>
* <tr>
* <td>{@code ImageManagement.param.limit.memory=40MB}</td>
* <td>{@code -limit memory 40MB}</td>
* </tr>
* <tr>
* <td>{@code ImageManagement.param.+set=date\:create}</td>
* <td>{@code +set date:create}</td>
* </tr>
* <tr>
* <td>{@code ImageManagement.param.quiet=}</td>
* <td>{@code -quiet}</td>
* </tr>
* </table>
*
* @param commandLine
* command line to which to add the arguments
*/
private static void configureImageMagick(IMOperation commandLine) {
final String configOptionsPrefix = "ImageManagement.param.";
Iterator<?> keys = KitodoConfig.getConfig().getKeys(configOptionsPrefix);
while (keys.hasNext()) {
Object keyObject = keys.next();
if (keyObject instanceof String) {
String key = (String) keyObject;
String option = key.substring(configOptionsPrefix.length());
if (!(option.startsWith("+") || option.startsWith("-"))) {
option = "-".concat(option);
}
commandLine.addRawArgs(option.split("\\."));
//FIXME: it is not secure to allow any possible key
String value = KitodoConfig.getParameter(key);
if (!value.isEmpty()) {
commandLine.addRawArgs(value);
}
}
}
}
/**
* Performs the conversion by calling ImageMagick.
*/
void run() throws IOException {
IMOperation commandLine = new IMOperation();
configureImageMagick(commandLine);
commandLine.addRawArgs(OPTION_UNITS, OPTION_UNITS_TYPE_PIXELSPERINCH);
commandLine.addImage(source);
results.forEach(result -> result.addToCommandLine(commandLine));
commandLine.addImage(FORMAT_OFF);
ConvertRunner convertRunner = new ConvertRunner();
try {
convertRunner.setSearchPath(KitodoConfig.getParameter(ParameterImageManagement.SEARCH_PATH));
} catch (NoSuchElementException e) {
logger.trace("No deviant search path configured.", e);
}
convertRunner.run(commandLine);
}
/**
* Converts an URI to an absolute local path as String.
*
* @param uri
* input file URI
* @return absolute local path
*/
private static String uriToPath(URI uri) {
return new File(uri).getAbsolutePath();
}
}