/*******************************************************************************
* Copyright (c) 2016 Weasis Team and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nicolas Roduit - initial API and implementation
*******************************************************************************/
package org.weasis.core.api.image;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import java.util.Optional;
import javax.media.jai.InterpolationBilinear;
import javax.media.jai.JAI;
import javax.media.jai.operator.TransposeDescriptor;
import javax.media.jai.operator.TransposeType;
import org.weasis.core.api.Messages;
import org.weasis.core.api.gui.util.MathUtil;
import org.weasis.core.api.image.util.ImageToolkit;
public class RotationOp extends AbstractOp {
public static final String OP_NAME = Messages.getString("RotationOperation.title"); //$NON-NLS-1$
/**
* Set the clockwise angle value in degree (Required parameter).
*
* Integer value.
*/
public static final String P_ROTATE = "rotate"; //$NON-NLS-1$
public RotationOp() {
setName(OP_NAME);
}
public RotationOp(RotationOp op) {
super(op);
}
@Override
public RotationOp copy() {
return new RotationOp(this);
}
@Override
public void process() throws Exception {
RenderedImage source = (RenderedImage) params.get(Param.INPUT_IMG);
RenderedImage result = source;
Integer rotationAngle = Optional.ofNullable((Integer) params.get(P_ROTATE)).orElse(0);
rotationAngle = rotationAngle % 360;
if (rotationAngle != 0) {
// optimize rotation by right angles
TransposeType rotOp = null;
if (rotationAngle == 90) {
rotOp = TransposeDescriptor.ROTATE_90;
} else if (rotationAngle == 180) {
rotOp = TransposeDescriptor.ROTATE_180;
} else if (rotationAngle == 270) {
rotOp = TransposeDescriptor.ROTATE_270;
}
if (rotOp != null) {
// use Transpose operation
ParameterBlock pb = new ParameterBlock();
pb.addSource(source);
pb.add(rotOp);
result = JAI.create("transpose", pb, ImageToolkit.NOCACHE_HINT); //$NON-NLS-1$
// Handle non square images. Translation is necessary because the transpose operator keeps the same
// origin (top left not the center of the image)
float diffw = source.getWidth() / 2.0f - result.getWidth() / 2.0f;
float diffh = source.getHeight() / 2.0f - result.getHeight() / 2.0f;
if (MathUtil.isDifferentFromZero(diffw) || MathUtil.isDifferentFromZero(diffh)) {
pb = new ParameterBlock();
pb.addSource(result);
pb.add(diffw);
pb.add(diffh);
result = JAI.create("translate", pb, ImageToolkit.NOCACHE_HINT); //$NON-NLS-1$
}
} else {
ParameterBlock pb = new ParameterBlock();
pb.addSource(source);
pb.add(source.getWidth() / 2.0f);
pb.add(source.getHeight() / 2.0f);
pb.add((float) (rotationAngle * Math.PI / 180.0));
pb.add(new InterpolationBilinear());
result = JAI.create("rotate", pb, ImageToolkit.NOCACHE_HINT); //$NON-NLS-1$
// // Untile this rotate node so that when compute the next node,
// // no extra memory and time are used in PlanarImage.getExtendedData().
// ImageLayout il = new ImageLayout();
// il.setTileWidth(result.getWidth());
// il.setTileHeight(result.getHeight());
// il.setTileGridXOffset(result.getMinX());
// il.setTileGridYOffset(result.getMinY());
// RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, il);
//
// result = JAI.create("rotate", pb, hints);
}
}
params.put(Param.OUTPUT_IMG, result);
}
}