?? ch13.htm
字號:
}</TT></BLOCKQUOTE><P>These changes have been incorporated in SpinRoll2, also on theCD-ROM in the file SpinRoll2.java. The new version will animatesmoothly.<H3><A NAME="DynamicImageFilterFXFilter">Dynamic Image Filter:FXFilter</A></H3><P>SpinFilter is static; the FXFilter is dynamic. A <I>static filter</I>alters an image and sends <TT>STATICIMAGEDONE</TT>when the alteration is done, but a <I>dynamic filter</I> makesthe effect take place over multiple frames, much like an animation.The FXFilter has four effects: <I>wipe left</I>, <I>wipe right</I>,<I>wipe from center out</I>, and <I>dissolve</I>. Each effectoperates by erasing the image in stages. The filter will call<TT>imageComplete()</TT> many times,but instead of passing <TT>STATICIMAGEDONE</TT>,it specifies <TT>SINGLEFRAMEDONE</TT>.<P>Because each effect is simply a matter of writing a block of aparticular color, there is no need to refer to the pixels in theoriginal image. Therefore, you don't need to use the <TT>setPixels()</TT>method, so the filter functions very quickly.<P>Each of the wipes operates by moving a column of erased pixelsover the length of the image. The width of the column is calculatedto yield the number of configured iterations. The dissolve worksby erasing a rectangular block at random places throughout theimage. Of all the effects, dissolve is the slowest to executebecause it has to calculate each random location.<P>In <TT>setHints()</TT>, the consumeris told that the filter will send random pixels. This causes theconsumer to call <TT>resendTopDownLeftRight()</TT>when the image is complete. The filter needs to intercept thecall to avoid having the just-erased image repainted by the producerin pristine form.<P>The filter has two constructors. If you don't specify a color,the image dissolves into transparency, allowing you to phase oneimage into a second image. You can also specify an optional color,which causes the image to gradually change into the passed color.You can dissolve an image into the background by passing the backgroundcolor in the filter constructor. The number of iterations andpaints is completely configurable. There is no hard-and-fast formulafor performing these effects, so feel free to alter the valuesto get the result you want. Listing 13.3 contains the source forthe filter.<HR><BLOCKQUOTE><B>Listing 13.3. The special-effects filter.<BR></B></BLOCKQUOTE><BLOCKQUOTE><TT>import java.awt.*;<BR>import java.awt.image.*;<BR>import java.util.*;<BR><BR>public class FXFilter extends ImageFilter<BR>{<BR> private int outwidth, outheight;<BR> private ColorModel defaultRGBModel;<BR> private int dissolveColor;<BR> private int iterations = 50;<BR> private int paintsPer = 2;<BR> private static final int SCALER = 25;<BR> private static final int MINIMUM_BLOCK= 7;<BR> private int dissolve_w, dissolve_h;<BR> private boolean sizeSet = false;<BR> private Thread runThread;<BR><BR> public static final int DISSOLVE = 0;<BR> public static final int WIPE_LR = 1;<BR> public static final int WIPE_RL = 2;<BR> public static final int WIPE_C = 3;<BR> private int type = DISSOLVE;<BR><BR> /**<BR> * Dissolve to transparent constructor<BR> */<BR> FXFilter()<BR> {<BR> defaultRGBModel= ColorModel.getRGBdefault();<BR> dissolveColor= 0;<BR> }<BR><BR> /**<BR> * Dissolve to the passed color constructor<BR> * @param dcolor contains the color todissolve to<BR> */<BR> FXFilter(Color dcolor)<BR> {<BR> this();<BR> dissolveColor= dcolor.getRGB();<BR> }<BR><BR> /**<BR> * Set the type of effect to perform.<BR> */<BR> public void setType(int t)<BR> {<BR> switch (t)<BR> {<BR> case DISSOLVE:type = t; break;<BR> case WIPE_LR: type= t; break;<BR> case WIPE_RL: type= t; break;<BR> case WIPE_C: type= t; break;<BR> }<BR> }<BR><BR> /**<BR> * Set the size of the dissolve blocks(pixels removed).<BR> */<BR> public void setDissolveSize(int w, inth)<BR> {<BR> if ( w < MINIMUM_BLOCK) w = MINIMUM_BLOCK;<BR> if ( h < MINIMUM_BLOCK) w = MINIMUM_BLOCK;<BR> dissolve_w = w;<BR> dissolve_h = h;<BR> sizeSet = true;<BR> }<BR><BR> /**<BR> * Set the dissolve parameters. (Optional,will default to 200 & 2)<BR> * @param num contains the number of timesto loop.<BR> * @param paintsPerNum contains the numberof blocks to remove per paint<BR> */<BR> public void setIterations(int num, intpaintsPerNum)<BR> {<BR> iterations = num;<BR> paintsPer = paintsPerNum;<BR> }<BR><BR> /**<BR> * @see ImageConsumer#setDimensions<BR> */<BR> public void setDimensions(int width, intheight)<BR> {<BR> outwidth = width;<BR> outheight = height;<BR> consumer.setDimensions(width,height);<BR> }<BR><BR> /**<BR> * Don't tell consumer we send completeframes.<BR> * Tell them we send random blocks.<BR> * @see ImageConsumer#setHints<BR> */<BR> public void setHints(int hints)<BR> {<BR> consumer.setHints(ImageConsumer.RANDOMPIXELORDER);<BR> }<BR><BR> /**<BR> * Override this method to keep the producer<BR> * from refreshing our dissolved image<BR> */<BR> public void resendTopDownLeftRight(ImageProducerip)<BR> {<BR> }<BR><BR> /**<BR> * Notification that the image is completeand there will<BR> * be no further setPixel calls.<BR> * @see ImageConsumer#imageComplete<BR> */<BR> public void imageComplete(int status)<BR> {<BR> if (status ==IMAGEERROR || status == IMAGEABORTED)<BR> {<BR> consumer.imageComplete(status);<BR> return;<BR> }<BR> if ( status ==SINGLEFRAMEDONE )<BR> {<BR> runThread= new RunFilter(this);<BR> runThread.start();<BR> }<BR> else<BR> filter();<BR> }<BR><BR> public void filter()<BR> {<BR> switch ( type)<BR> {<BR> case DISSOLVE:dissolve(); break; <BR> case WIPE_LR: wipeLR(); break;<BR> case WIPE_RL: wipeRL(); break;<BR> case WIPE_C: wipeC(); break;<BR> default: dissolve(); break;<BR> }<BR> consumer.imageComplete(STATICIMAGEDONE);<BR> }<BR><BR> /**<BR> * Wipe the image from left to right<BR> */<BR> public void wipeLR()<BR> {<BR> int xw = outwidth/ iterations;<BR> if ( xw <=0 ) xw = 1;<BR> int total = xw* outheight;<BR> int dissolvePixels[]= new int[total];<BR> for ( int x =0; x < total; x++ )<BR> dissolvePixels[x]= dissolveColor;<BR><BR> for ( int t =0; t < (outwidth - xw); t += xw )<BR> {<BR> consumer.setPixels(t,0, xw, outheight,<BR> defaultRGBModel, dissolvePixels,<BR> 0, xw);<BR> //tell consumer we are done with this frame<BR> consumer.imageComplete(ImageConsumer.SINGLEFRAMEDONE);<BR> }<BR> }<BR><BR> /**<BR> * Wipe the image from right to left<BR> */<BR> public void wipeRL()<BR> {<BR> int xw = outwidth/ iterations;<BR> if ( xw <=0 ) xw = 1;<BR> int total = xw* outheight;<BR> int dissolvePixels[]= new int[total];<BR> for ( int x =0; x < total; x++ )<BR>  
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -