Skip to content

Commit

Permalink
Throw if images of assets with unsupported mime types are being gener…
Browse files Browse the repository at this point in the history
…ated (e.g. gif, video)
  • Loading branch information
eschleb committed Feb 16, 2024
1 parent 844cac2 commit 8c7953a
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 53 deletions.
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,20 +189,21 @@ public class CustomDynamicImageParameter extends DynamicImageParameter {
</component>
```
#### [ImageOperationProvider](src/main/java/com/merkle/oss/magnolia/imaging/flexible/generator/ImageOperationProvider.java)

```java
import com.merkle.oss.magnolia.imaging.flexible.generator.ImageOperationProvider;
import com.merkle.oss.magnolia.imaging.flexible.generator.DefaultImageOperationProvider;
import com.merkle.oss.magnolia.imaging.flexible.model.FlexibleParameter;
import info.magnolia.imaging.ParameterProvider;
import info.magnolia.imaging.operations.ImageOperationChain;

import java.util.Optional;
import java.util.function.Function;

public class CustomImageOperationProvider extends ImageOperationProvider {
public class CustomImageOperationProvider extends DefaultImageOperationProvider {

@Override
public ImageOperationChain<ParameterProvider<FlexibleParameter>> get(final FlexibleParameter parameter) {
final ImageOperationChain<ParameterProvider<FlexibleParameter>> chain = super.get(parameter);
final ImageOperationChain<ParameterProvider<FlexibleParameter>> chain = super.get(parameter);
if (get(parameter, CustomDynamicImageParameter::isTriggerCustomOperation).orElse(false)) {
...
chain.addOperation(someCustomOperation);
Expand All @@ -218,10 +219,12 @@ public class CustomImageOperationProvider extends ImageOperationProvider {
}
}
```

```xml

<component>
<type>com.merkle.oss.magnolia.imaging.flexible.generator.ImageOperationProvider</type>
<implementation>com.somepackage.CustomImageOperationProvider</implementation>
<type>com.merkle.oss.magnolia.imaging.flexible.generator.ImageOperationProvider</type>
<implementation>com.somepackage.CustomImageOperationProvider</implementation>
</component>
```

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.merkle.oss.magnolia.imaging.flexible.generator;

import com.merkle.oss.magnolia.imaging.flexible.generator.operation.FlexibleAutoCropAndResize;
import com.merkle.oss.magnolia.imaging.flexible.generator.operation.FlexibleBoundedResize;
import com.merkle.oss.magnolia.imaging.flexible.generator.operation.FromFlexibleParameter;
import com.merkle.oss.magnolia.imaging.flexible.model.DynamicImageParameter;
import com.merkle.oss.magnolia.imaging.flexible.model.FlexibleParameter;
import info.magnolia.imaging.ParameterProvider;
import info.magnolia.imaging.operations.ImageOperationChain;

import javax.inject.Inject;
import javax.inject.Provider;

public class DefaultImageOperationProvider implements ImageOperationProvider {
private final Provider<FromFlexibleParameter> fromFlexibleParameter;
private final Provider<FlexibleAutoCropAndResize> flexibleAutoCropAndResize;
private final Provider<FlexibleBoundedResize> flexibleBoundedResize;

@Inject
public DefaultImageOperationProvider(
final Provider<FromFlexibleParameter> fromFlexibleParameter,
final Provider<FlexibleAutoCropAndResize> flexibleAutoCropAndResize,
final Provider<FlexibleBoundedResize> flexibleBoundedResize
) {
this.fromFlexibleParameter = fromFlexibleParameter;
this.flexibleAutoCropAndResize = flexibleAutoCropAndResize;
this.flexibleBoundedResize = flexibleBoundedResize;
}

@Override
public ImageOperationChain<ParameterProvider<FlexibleParameter>> get(final FlexibleParameter parameter) {
final ImageOperationChain<ParameterProvider<FlexibleParameter>> chain = new ImageOperationChain<>();
chain.addOperation(fromFlexibleParameter.get());

if (parameter.getDynamicImageParameter().map(DynamicImageParameter::isCrop).orElse(true)) {
chain.addOperation(flexibleAutoCropAndResize.get());
} else {
chain.addOperation(flexibleBoundedResize.get());
}
return chain;
}


}
Original file line number Diff line number Diff line change
@@ -1,55 +1,9 @@
package com.merkle.oss.magnolia.imaging.flexible.generator;

import com.merkle.oss.magnolia.imaging.flexible.generator.operation.FromFlexibleParameter;
import com.merkle.oss.magnolia.imaging.flexible.model.DynamicImageParameter;
import com.merkle.oss.magnolia.imaging.flexible.model.FlexibleParameter;
import com.merkle.oss.magnolia.imaging.flexible.model.bundle.RatioParser;
import info.magnolia.imaging.ParameterProvider;
import info.magnolia.imaging.operations.ImageOperationChain;
import info.magnolia.imaging.operations.cropresize.AutoCropAndResize;
import info.magnolia.imaging.operations.cropresize.BoundedResize;
import info.magnolia.imaging.operations.cropresize.resizers.MultiStepResizer;

import javax.inject.Inject;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Optional;

public class ImageOperationProvider {
private final RatioParser ratioParser;

@Inject
public ImageOperationProvider(final RatioParser ratioParser) {
this.ratioParser = ratioParser;
}

public ImageOperationChain<ParameterProvider<FlexibleParameter>> get(final FlexibleParameter parameter) {
final ImageOperationChain<ParameterProvider<FlexibleParameter>> chain = new ImageOperationChain<>();
chain.addOperation(new FromFlexibleParameter());

if (parameter.getDynamicImageParameter().map(DynamicImageParameter::isCrop).orElse(true)) {
final AutoCropAndResize resize = new AutoCropAndResize();
resize.setResizer(new MultiStepResizer());
resize.setTargetWidth(parameter.getWidth());
calculateHeight(parameter).ifPresent(resize::setTargetHeight);
chain.addOperation(resize);
} else {
final BoundedResize resize = new BoundedResize();
resize.setResizer(new MultiStepResizer());
resize.setMaxWidth(parameter.getWidth());
resize.setMaxHeight(calculateHeight(parameter).orElse(Integer.MAX_VALUE));
chain.addOperation(resize);
}
return chain;
}

protected Optional<Integer> calculateHeight(final FlexibleParameter parameter) {
return parameter.getRatio().flatMap(ratioParser::parse).map(ratio ->
calculateHeight(parameter.getWidth(), ratio)
);
}

private int calculateHeight(final int width, final double ratio) {
return BigDecimal.valueOf(width / ratio).setScale(0, RoundingMode.UP).intValue();
}
public interface ImageOperationProvider {
ImageOperationChain<ParameterProvider<FlexibleParameter>> get(FlexibleParameter parameter);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.merkle.oss.magnolia.imaging.flexible.generator.operation;

import info.magnolia.dam.api.Asset;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.io.IOException;

public class AssetUtil {

public boolean isAnimated(final Asset asset) throws IOException {
try (ImageInputStream iis = ImageIO.createImageInputStream(asset.getContentStream())) {
final ImageReader imageReader = ImageIO.getImageReadersByMIMEType(asset.getMimeType()).next();
imageReader.setInput(iis);

final int numImages = imageReader.getNumImages(true);
return numImages > 1;
}
}

public boolean isImage(final Asset asset) {
return ImageIO.getImageReadersByMIMEType(asset.getMimeType()).hasNext();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.merkle.oss.magnolia.imaging.flexible.generator.operation;

import com.merkle.oss.magnolia.imaging.flexible.model.FlexibleParameter;
import info.magnolia.imaging.ImagingException;
import info.magnolia.imaging.ParameterProvider;
import info.magnolia.imaging.operations.ImageOperation;
import info.magnolia.imaging.operations.cropresize.AutoCropAndResize;
import info.magnolia.imaging.operations.cropresize.resizers.MultiStepResizer;

import javax.inject.Inject;
import java.awt.image.BufferedImage;

public class FlexibleAutoCropAndResize implements ImageOperation<ParameterProvider<FlexibleParameter>> {
private final AssetUtil assetUtil;
private final HeightCalculator heightCalculator;

@Inject
public FlexibleAutoCropAndResize(
final AssetUtil assetUtil,
final HeightCalculator heightCalculator
) {
this.assetUtil = assetUtil;
this.heightCalculator = heightCalculator;
}

@Override
public BufferedImage apply(final BufferedImage source, final ParameterProvider<FlexibleParameter> params) throws ImagingException {
final FlexibleParameter parameter = params.getParameter();
if (!isSupported(parameter)) {
throw new ImagingException(getClass() + " doesn't support " + parameter);
}
final AutoCropAndResize autoCropAndResize = new AutoCropAndResize();
autoCropAndResize.setResizer(new MultiStepResizer());
autoCropAndResize.setTargetWidth(parameter.getWidth());
heightCalculator.calculateHeight(parameter).ifPresent(autoCropAndResize::setTargetHeight);
return autoCropAndResize.apply(source, params);
}

public boolean isSupported(final FlexibleParameter parameter) {
try {
return !assetUtil.isAnimated(parameter);
} catch (Exception e) {
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.merkle.oss.magnolia.imaging.flexible.generator.operation;

import com.merkle.oss.magnolia.imaging.flexible.model.FlexibleParameter;
import info.magnolia.imaging.ImagingException;
import info.magnolia.imaging.ParameterProvider;
import info.magnolia.imaging.operations.ImageOperation;
import info.magnolia.imaging.operations.cropresize.BoundedResize;
import info.magnolia.imaging.operations.cropresize.resizers.MultiStepResizer;

import javax.inject.Inject;
import java.awt.image.BufferedImage;

public class FlexibleBoundedResize implements ImageOperation<ParameterProvider<FlexibleParameter>> {
private final AssetUtil assetUtil;
private final HeightCalculator heightCalculator;

@Inject
public FlexibleBoundedResize(
final AssetUtil assetUtil,
final HeightCalculator heightCalculator
) {
this.assetUtil = assetUtil;
this.heightCalculator = heightCalculator;
}

@Override
public BufferedImage apply(final BufferedImage source, final ParameterProvider<FlexibleParameter> params) throws ImagingException {
final FlexibleParameter parameter = params.getParameter();
if (!isSupported(parameter)) {
throw new ImagingException(getClass() + " doesn't support " + parameter);
}
final BoundedResize boundedResize = new BoundedResize();
boundedResize.setResizer(new MultiStepResizer());
boundedResize.setMaxWidth(parameter.getWidth());
boundedResize.setMaxHeight(heightCalculator.calculateHeight(parameter).orElse(Integer.MAX_VALUE));
return boundedResize.apply(source, params);
}

public boolean isSupported(final FlexibleParameter parameter) {
try {
return !assetUtil.isAnimated(parameter);
} catch (Exception e) {
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,26 @@
import info.magnolia.imaging.ParameterProvider;
import info.magnolia.imaging.operations.load.AbstractLoader;

import javax.inject.Inject;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;

public class FromFlexibleParameter extends AbstractLoader<ParameterProvider<FlexibleParameter>> {
private final AssetUtil assetUtil;

@Inject
public FromFlexibleParameter(final AssetUtil assetUtil) {
this.assetUtil = assetUtil;
}

@Override
protected BufferedImage loadSource(final ParameterProvider<FlexibleParameter> param) throws ImagingException {
try {
final FlexibleParameter parameter = param.getParameter();
if (!assetUtil.isImage(parameter)) {
throw new ImagingException(getClass() + " doesn't support " + parameter);
}
return doReadAndClose(toInputStream(param));
} catch (IOException e) {
throw new ImagingException("Can't read image stream from flexibleParam.");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.merkle.oss.magnolia.imaging.flexible.generator.operation;

import com.merkle.oss.magnolia.imaging.flexible.model.FlexibleParameter;
import com.merkle.oss.magnolia.imaging.flexible.model.bundle.RatioParser;

import javax.inject.Inject;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Optional;

public class HeightCalculator {
private final RatioParser ratioParser;

@Inject
public HeightCalculator(final RatioParser ratioParser) {
this.ratioParser = ratioParser;
}

public Optional<Integer> calculateHeight(final FlexibleParameter parameter) {
return parameter.getRatio().flatMap(ratioParser::parse).map(ratio ->
calculateHeight(parameter.getWidth(), ratio)
);
}

private int calculateHeight(final int width, final double ratio) {
return BigDecimal.valueOf(width / ratio).setScale(0, RoundingMode.UP).intValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public String toString() {
"dynamicImageParameter=" + dynamicImageParameter +
", ratio='" + ratio + '\'' +
", width=" + width +
", fileName=" + getFileName() +
"} " + super.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
<implementation>com.merkle.oss.magnolia.imaging.flexible.model.bundle.ProcessedBundlesProvider</implementation>
<scope>singleton</scope>
</component>
<component>
<type>com.merkle.oss.magnolia.imaging.flexible.generator.ImageOperationProvider</type>
<implementation>com.merkle.oss.magnolia.imaging.flexible.generator.DefaultImageOperationProvider</implementation>
</component>
</components>

<dependencies>
Expand Down

0 comments on commit 8c7953a

Please sign in to comment.