/*
* @(#)HalftoneTransition2D.java
*
* $Date: 2014-06-06 20:04:49 +0200 (P, 06 jún. 2014) $
*
* Copyright (c) 2011 by Jeremy Wood.
* All rights reserved.
*
* The copyright of this software is owned by Jeremy Wood.
* You may not use, copy or modify this software, except in
* accordance with the license agreement you entered into with
* Jeremy Wood. For details see accompanying license terms.
*
* This software is probably, but not necessarily, discussed here:
* https://javagraphics.java.net/
*
* That site should also contain the most recent official version
* of this software. (See the SVN repository for more details.)
*/
package com.bric.image.transition;
import java.awt.Dimension;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.RectangularShape;
import java.awt.geom.RoundRectangle2D;
import java.util.Vector;
/** In this transition an image splits apart into several
* tiny circles that shrink in size. Or, seen backwards,
* several incoming tiny circles swirl together and merge
* into the new image.
* <p>Here are playback samples:
* <p><table summary="Sample Animations of HalftoneTransition2D" cellspacing="50" border="0"><tr>
* <td align="center">
* <img src="https://javagraphics.java.net/resources/transition/HalftoneTransition2D/HalftoneIn.gif" alt="Halftone In">
* <p>Halftone In
* </td>
* <td align="center">
* <img src="https://javagraphics.java.net/resources/transition/HalftoneTransition2D/HalftoneOut.gif" alt="Halftone Out">
* <p>Halftone Out
* </td>
* </tr></table>
*
*/
public class HalftoneTransition2D extends Transition2D {
/** This public static method is used by the
* {@link com.bric.image.transition.Transition2DDemoHelper}
* class to create sample animations of this transition.
* @return the transitions that should be used to demonstrate this
* transition.
*/
public static Transition[] getDemoTransitions() {
return new Transition[] {
new HalftoneTransition2D(IN),
new HalftoneTransition2D(OUT)
};
}
int type = OUT;
/** Creates a new halftone transition that moves out */
public HalftoneTransition2D() {}
/** Creates a new halftone transition.
*
* @param type must be OUT or IN.
*/
public HalftoneTransition2D(int type) {
if(type==IN || type==OUT) {
this.type = type;
} else {
throw new IllegalArgumentException("The type must be IN or OUT");
}
}
@Override
public Transition2DInstruction[] getInstructions(float progress,
Dimension size) {
if(type==OUT) {
progress = 1-progress;
}
progress = (float)Math.pow(progress,.5);
float ySize = (size.height)*.05f;
float xSize = (size.width)*.05f;
Vector<RectangularShape> v = new Vector<RectangularShape>();
float angleProgress = (float)Math.pow(1-Math.min(progress, 1),.5);
//pop it over 1:
float progressZ = 1.3f*progress;
double w = xSize*progressZ;
double h = ySize*progressZ;
float min = (float)(Math.min(w,h));
for(float y = 0; y<size.height; y+=ySize) {
for(float x = 0; x<size.width; x+=xSize) {
v.add(new RoundRectangle2D.Double(x+xSize/2-w/2,y+ySize/2-h/2,
w*progress+(1-progress)*min,
h*progress+(1-progress)*min,
w*angleProgress*progress+(1-progress)*min*angleProgress,
h*angleProgress*progress+(1-progress)*min*angleProgress) );
}
}
ImageInstruction[] instr = new ImageInstruction[v.size()+1];
instr[0] = new ImageInstruction(false);
for(int a = 0; a<v.size(); a++) {
float progress2 = progress; //(float)Math.pow(progress, .9+.2*random.nextFloat());
RectangularShape r = v.get(a);
Point2D p1 = new Point2D.Double(r.getCenterX(),r.getCenterY());
Point2D p2 = new Point2D.Double(r.getCenterX(),r.getCenterY());
AffineTransform transform = new AffineTransform();
transform.translate(r.getCenterX(),r.getCenterY());
transform.scale(30*(1-progress)+1, 30*(1-progress)+1 );
transform.translate(-r.getCenterX(),-r.getCenterY());
transform.rotate(.3*(1-progress2),size.width/3,size.height/2);
transform.transform(p1,p2);
transform.setToTranslation(p1.getX()-p2.getX(),p1.getY()-p2.getY());
Shape shape = transform.createTransformedShape(r);
instr[a+1] = new ImageInstruction(true,transform,shape);
}
if(type==IN) {
for(int a = 0; a<instr.length; a++) {
instr[a].isFirstFrame = !instr[a].isFirstFrame;
}
}
return instr;
}
@Override
public String toString() {
if(type==IN) {
return "Halftone In";
} else {
return "Halftone Out";
}
}
}