TransformedRenditionHandler.java
/*
* #%L
* wcm.io
* %%
* Copyright (C) 2014 wcm.io
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package io.wcm.handler.mediasource.dam.impl;
import static io.wcm.handler.media.impl.ImageTransformation.isValidRotation;
import static io.wcm.handler.media.impl.ImageTransformation.rotateMapHeight;
import static io.wcm.handler.media.impl.ImageTransformation.rotateMapWidth;
import java.util.NavigableSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import io.wcm.handler.media.CropDimension;
import io.wcm.handler.media.MediaArgs;
/**
* Extended rendition handler supporting cropping and rotating of images.
*/
public class TransformedRenditionHandler extends DefaultRenditionHandler {
private final CropDimension cropDimension;
private final Integer rotation;
/**
* @param cropDimension Crop dimension
* @param rotation Rotation
* @param damContext DAM context objects
*/
TransformedRenditionHandler(CropDimension cropDimension, Integer rotation, DamContext damContext) {
super(damContext);
this.cropDimension = cropDimension;
this.rotation = (rotation != null && isValidRotation(rotation)) ? rotation : null;
}
/**
* Searches for the biggest web enabled rendition and, if exists,
* adds a {@link VirtualTransformedRenditionMetadata} to the list.
* @param candidates Candidates
* @param mediaArgs Media args
* @return {@link Set} of {@link RenditionMetadata}
*/
@Override
protected Set<RenditionMetadata> postProcessCandidates(Set<RenditionMetadata> candidates, MediaArgs mediaArgs) {
NavigableSet<RenditionMetadata> processedCandidates = new TreeSet<>(candidates);
if (cropDimension != null) {
VirtualTransformedRenditionMetadata cropRendition = getCropRendition(mediaArgs);
if (cropRendition != null) {
// return only cropped rendition
processedCandidates.clear();
processedCandidates.add(cropRendition);
return processedCandidates;
}
}
return rotateSourceRenditions(processedCandidates, mediaArgs);
}
/**
* Rotates all source renditions if configured.
* @param candidates Candidate renditions
* @param mediaArgs Media args
* @return Virtual-rotated and sorted candidate renditions
*/
private NavigableSet<RenditionMetadata> rotateSourceRenditions(Set<RenditionMetadata> candidates, MediaArgs mediaArgs) {
if (rotation == null) {
return new TreeSet<>(candidates);
}
return candidates.stream()
.filter(rendition -> !rendition.isVectorImage())
.map(rendition -> new VirtualTransformedRenditionMetadata(rendition.getRendition(),
rotateMapWidth(rendition.getWidth(), rendition.getHeight(), rotation),
rotateMapHeight(rendition.getWidth(), rendition.getHeight(), rotation),
mediaArgs.getEnforceOutputFileExtension(), null, rotation, mediaArgs.getImageQualityPercentage()))
.collect(Collectors.toCollection(TreeSet::new));
}
/**
* Searches for the biggest web-enabled rendition that matches the crop dimensions width and height or is bigger.
* @param mediaArgs Media args
* @return Rendition or null if no match found
*/
private VirtualTransformedRenditionMetadata getCropRendition(MediaArgs mediaArgs) {
RenditionMetadata original = getOriginalRendition();
if (original == null || original.isVectorImage()) {
return null;
}
return new VirtualTransformedRenditionMetadata(original.getRendition(),
rotateMapWidth(cropDimension.getWidth(), cropDimension.getHeight(), rotation),
rotateMapHeight(cropDimension.getWidth(), cropDimension.getHeight(), rotation),
mediaArgs.getEnforceOutputFileExtension(), cropDimension, rotation, mediaArgs.getImageQualityPercentage());
}
@Override
protected boolean enforceVirtualRendition(RenditionMetadata rendition, MediaArgs mediaArgs) {
// ignore this setting when already using transformed rendition handler
return false;
}
}