/*
<html> <body> <applet code="pixelpaint.class" codebase="." width="450" height="80" name="pixelpainter"> <param name="off_width" value="450"> <param name="off_height" value="80" > <param name="frame_time" value="40"> <param name="back_col" value="#000000"> <param name="fore_col" value="#00ccff"> </applet> </body> </html> */ /* ************************************************************************
* you can copy, use, modify and distribute this code for educational,
* commercial or recreational use. all we ask is that you include
* this copyright notice in the source code you distribute. for
* compiled code, you will need to make accessible this copyright notice
* somewhere in the distribution, and/or via a link on the web.
* there are several reasons for this caveat - the most important being
* that open source is based on one main principle: what you find and use,
* others should also have access to. don't keep it to yourself!
* credit where credit is due! http://www.orgdot.com/javaopensource
*
*
* this software is provided by the author and contributors ``as is'' and
* any express or implied warranties, including, but not limited to, the
* implied warranties of merchantability and fitness for a particular purpose
* are disclaimed. in no event shall the author or contributors be liable
* for any direct, indirect, incidental, special, exemplary, or consequential
* damages (including, but not limited to, procurement of substitute goods
* or services; loss of use, data, or profits; or business interruption)
* however caused and on any theory of liability, whether in contract, strict
* liability, or tort (including negligence or otherwise) arising in any way
* out of the use of this software, even if advised of the possibility of
* such damage.
*
************************************************************************ */ import java.applet.Applet; import java.awt.Graphics; import java.awt.Image; import java.awt.MediaTracker; import java.awt.image.PixelGrabber; import java.awt.image.DirectColorModel; import java.awt.image.ImageConsumer; import java.awt.image.ImageProducer; import java.util.Hashtable; import java.util.Vector; import java.util.Enumeration; public class pixelpaint extends Applet implements ImageProducer, Runnable { // the main thread private boolean alive; private Thread thr; // the image producer private final Hashtable properties; private final Vector the_consumers; private final DirectColorModel col_mod; // the screen buffer private Image off_screen; private int pixels [], off_width, off_height, frame_count; // for colorizing the image private final int [] back_col, fore_col; private boolean color_changed; /* ////////////////////////////////// INITIATE VALUES: */ ////////////////////////////////// public pixelpaint () { super (); properties = new Hashtable (); the_consumers = new Vector (); col_mod = new DirectColorModel (24, 0xff0000, 0x00ff00, 0x0000ff); back_col = new int[3]; fore_col = new int[3]; color_changed = false; alive = false; thr = null; frame_count = 0; } public void init () { System.out.println ("********************************"); System.out.println ("*** init orgdot pixelpainter ***"); System.out.println ("********************************"); pixels = new int [ ( off_width = parseInt ( getParam ( "off_width") ) ) * ( off_height = parseInt ( getParam ("off_height") ) ) ]; setForeBackColor ( getParam ("back_col" ) + getParam ("fore_col" ) ); off_screen = createImage (this); } /* ////////////////////////////////// THE LOOP: */ ////////////////////////////////// public synchronized void run () { int _x = 0, step_x = 5, delay_x = next (9) + 512, blur_buf[] = new int [off_width * off_height], col_table_256[] = new int[256]; long sleeper, frame_time = parseLong (getParam("frame_time")), timer = System.currentTimeMillis(); while (alive) { decrease (blur_buf, blur_buf, 10); if ( _x < off_width - step_x) drawBlock (blur_buf, off_width, off_height, _x, step_x, 0xff); _x += step_x; if ( _x > off_width + delay_x) { _x = 0; delay_x = next (9) + 512; } blurFromLeft (blur_buf, blur_buf, off_width, off_height); if ( color_changed ) setColTable (col_table_256, back_col, fore_col); grayTo256RGB (pixels, blur_buf, col_table_256); sendPixels (); repaint (); frame_count ++; try { wait (); thr.sleep ( ( sleeper = frame_time + timer - (timer = System.currentTimeMillis() ) ) > 0 ? sleeper : 10L ); } catch (Throwable t) { killThread (); } } } /* ////////////////////////////////// PIXEL ROUTINES: */ ////////////////////////////////// private static void drawBlock ( int[] pix, int _width, int _height, int _x, int _w, int col ) { int width_height = _width * _height; for (int i = _x ; i < width_height; i += _width) { int _wi = i + _w; for (int j = i; j < _wi; ) pix [j++] = col; } } private static void blurFromLeft ( int [] pix_to, int [] pix_from, int _w, int _h ) { int wh = _w * _h, w4 = _w - 4; for ( int i = 0; i < wh; i += _w ) for ( int j = w4 + i; j > i; ) pix_to [j] = (pix_from [j++] + pix_from [j++] + pix_from [j++] + pix_from [j -= 4]) >> 2; } private static void decrease ( int [] pix_to, int [] pix_from, int col_step ) { try { for (int i = 0; ; ) pix_to [i] = ( pix_from [i] > col_step ) ? pix_from [i++] - col_step : pix_from [i++]; } catch (ArrayIndexOutOfBoundsException a) {} } private static void blackMask ( int [] pix_to, int [] pix_from, int cutoff ) { try { for (int i = 0; ; ) pix_to [i] = (pix_from [i] < cutoff) ? pix_from [i++] : pix_to [i++]; } catch (ArrayIndexOutOfBoundsException a) {} } private static void mask ( int [] pix_to, int [] pix_from ) { try { for (int i = 0; ; ) pix_to [i] = (pix_to [i] > pix_from [i]) ? pix_from [i++] : pix_to [i++]; } catch (ArrayIndexOutOfBoundsException a) {} } private static void average ( int [] pix_to, int [] pix_from ) { try { for (int i = 0; ; ) pix_to [i] = ( pix_to [i] + pix_from [i++] ) >> 1; } catch (ArrayIndexOutOfBoundsException a) {} } private static void or ( int [] pix_to, int [] pix_from ) { try { for (int i = 0; ; ) pix_to [i] = pix_to [i] | pix_from [i++]; } catch (ArrayIndexOutOfBoundsException a) {} } private static void copy ( int [] pix_to, int [] pix_from ) { try { for (int i = 0; ; ) pix_to [i] = pix_from [i++]; } catch (ArrayIndexOutOfBoundsException a) {} } private static void grayTo256RGB ( int[] pix_to, int[] pix_from, int[] color_table ) { try { for (int i = 0; ; ) pix_to [i] = color_table [ pix_from [i++] ]; } catch (ArrayIndexOutOfBoundsException a) {} } /*///////////////////////////////////////// CALLED BY THE BROWSER /*///////////////////////////////////////// public void start () { if (!alive) { alive = true; thr = new Thread(this); thr.start(); System.out.println ("thread started"); } } public void stop () { killThread (); } public void destroy () { killThread (); } public void killThread () { if (alive) { alive = false; System.out.println ("rendered " + frame_count + " frames"); System.out.println ("********************************"); System.out.println ("*** exit orgdot pixelpainter ***"); System.out.println ("********************************"); } } /*///////////////////////////////////////// A RANDOMIZER /*///////////////////////////////////////// private static long seed = System.currentTimeMillis (), mask = (1L << 48) - 1; private static int next ( int bits ) { return (int) ( (seed = ( seed * 0x5DEECE66DL + 0xBL) & mask) >>> (48 - bits) ); } /*///////////////////////////////////////// A GRADIENT COLOR TABLE /*///////////////////////////////////////// public void setForeBackColor ( String backfore ) { int len = backfore.length() / 2; String back = backfore.substring (0, len); String fore = backfore.substring (len); color ( back_col, back ); color ( fore_col, fore ); color_changed = true; System.out.println ("Setting background color: " + back + " and foreground color: " + fore); } private void setColTable (int[] table, int [] b_col, int [] f_col) { for (int i = 0, j = 255; i < 256; i++, j--) table [i] = ( ( ( j * b_col [0] + i * f_col [0] ) >> 8 ) << 16 ) + ( ( ( j * b_col [1] + i * f_col [1] ) >> 8 ) << 8 ) + ( ( ( j * b_col [2] + i * f_col [2] ) >> 8 ) ); color_changed = false; } /* ////////////////////////////////// UTILITIES: */ ////////////////////////////////// private Image loadImage ( String str ) { try { Image im = getImage (getCodeBase(), str); MediaTracker mt = new MediaTracker(this); mt.addImage (im, 0); mt.waitForAll(); System.out.println ("image loaded: " + getCodeBase().toString() + str); return im; } catch (Throwable t) { System.out.println ("unable to load image " + str + ": " + t.toString()); return null; } } private int[] getPixels (Image im) { try { int w = im.getWidth(this); int h = im.getHeight (this); int[] pix = new int[w * h]; PixelGrabber pg = new PixelGrabber(im.getSource(), 0, 0, w, h, pix, 0, w); pg.grabPixels(); pg = null; return pix; } catch (Throwable t) { System.out.println ("unable to extract pixel values from image: " + t.toString()); return null; } } private int [] getMaskPixels ( String image ) { Image im = loadImage (image); int [] mask = getPixels (im); try { for (int i = 0; ; ) mask [i++] &= 0xff; } catch (Throwable t) {} im.flush (); return mask; } private static int parseInt ( String str ) { try { return Integer.parseInt (str); } catch (Throwable t) { System.out.println ("unable to parse " + str + ": " + t.toString()); return 0; } } private static int parseHexInt ( String str ) { try { return Integer.parseInt (str, 16); } catch (Throwable t) { System.out.println ("unable to parse " + str + ": " + t.toString()); return 0; } } private static long parseLong ( String str ) { try { return Long.parseLong (str); } catch (Throwable t) { System.out.println ("unable to parse " + str + ": " + t.toString()); return 0L; } } private String getParam ( String str ) { String param = getParameter (str); if (param == null) { System.out.println ("unable to read parameter: " + str); return new String(); } System.out.println ("reading parameter " + str + ": " + param); return param; } private void color ( int [] color, String col_str ) { int chop = col_str.indexOf ("#" ); int col = ( chop > - 1 ) ? parseHexInt (col_str.substring ( chop + 1 )) : parseHexInt (col_str); for (int i = 0; i < 3; i++) color[i] = ( col & (0xff << (16 - 8 * i)) ) >> (16 - 8 * i); } /* ////////////////////////////////// DRAW THE OFF-SCREEN IMAGE: */ ////////////////////////////////// public void update (Graphics g) { paint (g); } public synchronized void paint (Graphics g) { if (off_screen != null) g.drawImage (off_screen, 0, 0, this); notifyAll(); } private void sendPixels() { Enumeration enum = the_consumers.elements(); while(enum.hasMoreElements()) { ImageConsumer ic = (ImageConsumer) enum.nextElement(); if ( isConsumer(ic) ) ic.setPixels(0, 0, off_width, off_height, col_mod, pixels, 0, off_width); if ( isConsumer(ic) ) ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE); } } /* ////////////////////////////////// THE IMAGE PRODUCER ROUTINES: */ ////////////////////////////////// public synchronized void addConsumer(ImageConsumer ic) { if( the_consumers.contains(ic) ) return; the_consumers.addElement(ic); try { initConsumer(ic); sendPixels(); if( isConsumer(ic) ) ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE); } catch (Exception e) { if(isConsumer(ic)) ic.imageComplete(ImageConsumer.IMAGEERROR); } } private void initConsumer(ImageConsumer ic) { if (isConsumer(ic)) ic.setDimensions(off_width, off_height); if (isConsumer(ic)) ic.setProperties(properties); if (isConsumer(ic)) ic.setColorModel(col_mod); if (isConsumer(ic)) ic.setHints (ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES); } public synchronized boolean isConsumer(ImageConsumer ic) { return the_consumers.contains(ic); } public synchronized void removeConsumer(ImageConsumer ic) { the_consumers.removeElement(ic); } public void startProduction(ImageConsumer ic) { addConsumer(ic); } public void requestTopDownLeftRightResend(ImageConsumer ic) { } }