/*
* #%L
* BroadleafCommerce Open Admin Platform
* %%
* Copyright (C) 2009 - 2013 Broadleaf Commerce
* %%
* 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 org.broadleafcommerce.openadmin.server.service.artifact.image.effects.chain.filter;
import org.broadleafcommerce.openadmin.server.service.artifact.image.Operation;
import org.broadleafcommerce.openadmin.server.service.artifact.image.effects.chain.UnmarshalledParameter;
import org.broadleafcommerce.openadmin.server.service.artifact.image.effects.chain.conversion.ParameterTypeEnum;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.Map;
public class Resize extends BaseFilter {
private RenderingHints hints;
private int targetWidth;
private int targetHeight;
private boolean highQuality;
private Object hint;
private boolean maintainAspectRatio;
private boolean reduceOnly;
public Resize() {
//do nothing
}
public Resize(int targetWidth, int targetHeight, boolean highQuality, boolean maintainAspectRatio, boolean reduceOnly, RenderingHints hints) {
this.hints = hints;
this.targetWidth = targetWidth;
this.targetHeight = targetHeight;
this.highQuality = highQuality;
this.hint = RenderingHints.VALUE_INTERPOLATION_BICUBIC;
this.maintainAspectRatio = maintainAspectRatio;
this.reduceOnly = reduceOnly;
}
@Override
public Operation buildOperation(Map<String, String> parameterMap, InputStream artifactStream, String mimeType) {
String key = FilterTypeEnum.RESIZE.toString().toLowerCase();
if (!containsMyFilterParams(key, parameterMap)) {
return null;
}
Operation operation = new Operation();
operation.setName(key);
String factor = parameterMap.get(key + "-factor");
operation.setFactor(factor==null?null:Double.valueOf(factor));
UnmarshalledParameter targetWidth = new UnmarshalledParameter();
String targetWidthApplyFactor = parameterMap.get(key + "-width-apply-factor");
targetWidth.setApplyFactor(targetWidthApplyFactor == null ? false : Boolean.valueOf(targetWidthApplyFactor));
targetWidth.setName("target-width");
targetWidth.setType(ParameterTypeEnum.INT.toString());
targetWidth.setValue(parameterMap.get(key + "-width-amount"));
UnmarshalledParameter targetHeight = new UnmarshalledParameter();
String targetHeightApplyFactor = parameterMap.get(key + "-height-apply-factor");
targetHeight.setApplyFactor(targetHeightApplyFactor == null ? false : Boolean.valueOf(targetHeightApplyFactor));
targetHeight.setName("target-height");
targetHeight.setType(ParameterTypeEnum.INT.toString());
targetHeight.setValue(parameterMap.get(key + "-height-amount"));
UnmarshalledParameter highQuality = new UnmarshalledParameter();
highQuality.setName("high-quality");
highQuality.setType(ParameterTypeEnum.BOOLEAN.toString());
highQuality.setValue(parameterMap.get(key + "-high-quality")==null?"false":parameterMap.get(key + "-high-quality"));
UnmarshalledParameter maintainAspectRatio = new UnmarshalledParameter();
maintainAspectRatio.setName("maintain-aspect-ratio");
maintainAspectRatio.setType(ParameterTypeEnum.BOOLEAN.toString());
maintainAspectRatio.setValue(parameterMap.get(key + "-maintain-aspect-ratio") == null ? "false" : parameterMap.get(key + "-maintain-aspect-ratio"));
UnmarshalledParameter reduceOnly = new UnmarshalledParameter();
reduceOnly.setName("reduce-only");
reduceOnly.setType(ParameterTypeEnum.BOOLEAN.toString());
reduceOnly.setValue(parameterMap.get(key + "-reduce-only") == null ? "false" : parameterMap.get(key + "-reduce-only"));
operation.setParameters(new UnmarshalledParameter[]{targetWidth, targetHeight, highQuality, maintainAspectRatio, reduceOnly});
return operation;
}
/* (non-Javadoc)
* @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage, java.awt.image.BufferedImage)
*/
public BufferedImage filter(BufferedImage src, BufferedImage dst) {
if (src == null) {
throw new NullPointerException("src image is null");
}
if (src == dst) {
throw new IllegalArgumentException("src image cannot be the "+
"same as the dst image");
}
if (src.getWidth() <= targetWidth && src.getHeight() <= targetHeight && reduceOnly) {
return src;
}
BufferedImage temp = getScaledInstance(src, targetWidth, targetHeight, hint, highQuality, maintainAspectRatio, reduceOnly);
if (dst != null) {
Graphics g = dst.createGraphics();
g.drawImage(temp, 0, 0, temp.getWidth(), temp.getHeight(), null);
g.dispose();
} else {
dst = temp;
}
return dst;
}
private BufferedImage getScaledInstance(BufferedImage img, int targetWidth, int targetHeight, Object hint, boolean higherQuality, boolean maintainAspectRatio, boolean reduceOnly) {
BufferedImage ret = (BufferedImage) img;
int w, h, destW, destH;
if (maintainAspectRatio) {
int wDiff = Math.abs(img.getWidth() - targetWidth);
int hDiff = Math.abs(img.getHeight() - targetHeight);
if (wDiff > hDiff) {
destH = targetHeight;
destW = Double.valueOf((((double) img.getWidth()) * ((double) destH))/((double) img.getHeight())).intValue();
} else {
destW = targetWidth;
destH = Double.valueOf((((double) img.getHeight()) * ((double) destW))/((double) img.getWidth())).intValue();
}
} else {
destW = targetWidth;
destH = targetHeight;
}
if (higherQuality) {
// Use multi-step technique: start with original size, then
// scale down in multiple passes with drawImage()
// until the target size is reached
w = img.getWidth();
h = img.getHeight();
} else {
// Use one-step technique: scale directly from original
// size to target size with a single drawImage() call
if (!maintainAspectRatio) {
w = targetWidth;
h = targetHeight;
} else {
w = destW;
h = destH;
}
}
do {
if (higherQuality && w > destW) {
w /= 2;
if (w < destW) {
w = destW;
}
} else if (higherQuality && w < destW) {
w *= 2;
if (w > destW) {
w = destW;
}
}
if (higherQuality && h > destH) {
h /= 2;
if (h < destH) {
h = destH;
}
} else if (higherQuality && h < destH) {
h *= 2;
if (h > destH) {
h = destH;
}
}
int type;
if (img.getType()!=BufferedImage.TYPE_INT_ARGB && img.getType()!=BufferedImage.TYPE_INT_RGB) {
type = BufferedImage.TYPE_INT_ARGB;
} else {
type = img.getType();
}
BufferedImage tmp = new BufferedImage(w, h, type);
Graphics2D g2 = tmp.createGraphics();
g2.drawImage(ret.getScaledInstance(w, h, Image.SCALE_SMOOTH), 0, 0, w, h, null);
g2.dispose();
ret = tmp;
} while (w != destW || h != destH);
return ret;
}
}