home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1997 May / Pcwk0597.iso / sybase / starbuck / java.z / PixelGrabber.java < prev    next >
Text File  |  1996-05-03  |  11KB  |  369 lines

  1. /*
  2.  * @(#)PixelGrabber.java    1.5 96/01/16 Jim Graham
  3.  *
  4.  * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package java.awt.image;
  21.  
  22. import java.util.Hashtable;
  23. import java.awt.image.ImageProducer;
  24. import java.awt.image.ImageConsumer;
  25. import java.awt.image.ColorModel;
  26. import java.awt.Image;
  27.  
  28. /**
  29.  * The PixelGrabber class implements an ImageConsumer which can be attached
  30.  * to an Image or ImageProducer object to retrieve a subset of the pixels
  31.  * in that image.  Here is an example:
  32.  * <pre>
  33.  *
  34.  * public void handlesinglepixel(int x, int y, int pixel) {
  35.  *    int alpha = (pixel >> 24) & 0xff;
  36.  *    int red   = (pixel >> 16) & 0xff;
  37.  *    int green = (pixel >>  8) & 0xff;
  38.  *    int blue  = (pixel      ) & 0xff;
  39.  *    // Deal with the pixel as necessary...
  40.  * }
  41.  *
  42.  * public void handlepixels(Image img, int x, int y, int w, int h) {
  43.  *    int[] pixels = new int[w * h];
  44.  *    PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixels, 0, w);
  45.  *    try {
  46.  *        pg.grabPixels();
  47.  *    } catch (InterruptedException e) {
  48.  *        System.err.println("interrupted waiting for pixels!");
  49.  *        return;
  50.  *    }
  51.  *    if ((pg.status() & ImageObserver.ABORT) != 0) {
  52.  *        System.err.println("image fetch aborted or errored");
  53.  *        return;
  54.  *    }
  55.  *    for (int j = 0; j < h; j++) {
  56.  *        for (int i = 0; i < w; i++) {
  57.  *        handlesinglepixel(x+i, y+j, pixels[j * w + i]);
  58.  *        }
  59.  *    }
  60.  * }
  61.  *
  62.  * </pre>
  63.  *
  64.  * @see ColorModel#getRGBdefault
  65.  *
  66.  * @version     1.5, 16 Jan 1996
  67.  * @author     Jim Graham
  68.  */
  69. public class PixelGrabber implements ImageConsumer {
  70.     ImageProducer producer;
  71.  
  72.     int dstX;
  73.     int dstY;
  74.     int dstW;
  75.     int dstH;
  76.  
  77.     int[] pixelbuf;
  78.     int dstOff;
  79.     int dstScan;
  80.  
  81.     private boolean grabbing;
  82.     private int flags;
  83.  
  84.     private final int GRABBEDBITS = (ImageObserver.FRAMEBITS
  85.                      | ImageObserver.ALLBITS);
  86.     private final int DONEBITS = (GRABBEDBITS
  87.                   | ImageObserver.ERROR);
  88.  
  89.     /**
  90.      * Create a PixelGrabber object to grab the (x, y, w, h) rectangular
  91.      * section of pixels from the specified image into the given array.
  92.      * The pixels are stored into the array in the default RGB ColorModel.
  93.      * The RGB data for pixel (i, j) where (i, j) is inside the rectangle
  94.      * (x, y, w, h) is stored in the array at
  95.      * <tt>pix[(j - y) * scansize + (i - x) + off]</tt>.
  96.      * @see ColorModel#getRGBdefault
  97.      * @param img the image to retrieve pixels from
  98.      * @param x the x coordinate of the upper left corner of the rectangle
  99.      * of pixels to retrieve from the image, relative to the default
  100.      * (unscaled) size of the image
  101.      * @param y the y coordinate of the upper left corner of the rectangle
  102.      * of pixels to retrieve from the image
  103.      * @param w the width of the rectangle of pixels to retrieve
  104.      * @param h the height of the rectangle of pixels to retrieve
  105.      * @param pix the array of integers which are to be used to hold the
  106.      * RGB pixels retrieved from the image
  107.      * @param off the offset into the array of where to store the first pixel
  108.      * @param scansize the distance from one row of pixels to the next in
  109.      * the array
  110.      */
  111.     public PixelGrabber(Image img, int x, int y, int w, int h,
  112.             int[] pix, int off, int scansize) {
  113.     this(img.getSource(), x, y, w, h, pix, off, scansize);
  114.     }
  115.  
  116.     /**
  117.      * Create a PixelGrabber object to grab the (x, y, w, h) rectangular
  118.      * section of pixels from the image produced by the specified
  119.      * ImageProducer into the given array.
  120.      * The pixels are stored into the array in the default RGB ColorModel.
  121.      * The RGB data for pixel (i, j) where (i, j) is inside the rectangle
  122.      * (x, y, w, h) is stored in the array at
  123.      * <tt>pix[(j - y) * scansize + (i - x) + off]</tt>.
  124.      * @see ColorModel#getRGBdefault
  125.      * @param img the image to retrieve pixels from
  126.      * @param x the x coordinate of the upper left corner of the rectangle
  127.      * of pixels to retrieve from the image, relative to the default
  128.      * (unscaled) size of the image
  129.      * @param y the y coordinate of the upper left corner of the rectangle
  130.      * of pixels to retrieve from the image
  131.      * @param w the width of the rectangle of pixels to retrieve
  132.      * @param h the height of the rectangle of pixels to retrieve
  133.      * @param pix the array of integers which are to be used to hold the
  134.      * RGB pixels retrieved from the image
  135.      * @param off the offset into the array of where to store the first pixel
  136.      * @param scansize the distance from one row of pixels to the next in
  137.      * the array
  138.      */
  139.     public PixelGrabber(ImageProducer ip, int x, int y, int w, int h,
  140.             int[] pix, int off, int scansize) {
  141.     producer = ip;
  142.     dstX = x;
  143.     dstY = y;
  144.     dstW = w;
  145.     dstH = h;
  146.     dstOff = off;
  147.     dstScan = scansize;
  148.     pixelbuf = pix;
  149.     }
  150.  
  151.     /**
  152.      * Request the Image or ImageProducer to start delivering pixels and
  153.      * wait for all of the pixels in the rectangle of interest to be
  154.      * delivered.
  155.      * @return true if the pixels were successfully grabbed, false on
  156.      * abort, error or timeout
  157.      * @exception InterruptedException 
  158.      *            Another thread has interrupted this thread.
  159.      */
  160.     public boolean grabPixels() throws InterruptedException {
  161.     return grabPixels(0);
  162.     }
  163.  
  164.     /**
  165.      * Request the Image or ImageProducer to start delivering pixels and
  166.      * wait for all of the pixels in the rectangle of interest to be
  167.      * delivered or until the specified timeout has elapsed.
  168.      * @param ms the number of milliseconds to wait for the image pixels
  169.      * to arrive before timing out
  170.      * @return true if the pixels were successfully grabbed, false on
  171.      * abort, error or timeout
  172.      * @exception InterruptedException 
  173.      *            Another thread has interrupted this thread. 
  174.      */
  175.     public synchronized boolean grabPixels(long ms)
  176.     throws InterruptedException
  177.     {
  178.     if ((flags & DONEBITS) != 0) {
  179.         return (flags & GRABBEDBITS) != 0;
  180.     }
  181.     long end = ms + System.currentTimeMillis();
  182.     if (!grabbing) {
  183.         grabbing = true;
  184.         flags &= ~(ImageObserver.ABORT);
  185.         producer.startProduction(this);
  186.     }
  187.     while (grabbing) {
  188.         long timeout;
  189.         if (ms == 0) {
  190.         timeout = 0;
  191.         } else {
  192.         timeout = end - System.currentTimeMillis();
  193.         if (timeout <= 0) {
  194.             break;
  195.         }
  196.         }
  197.         wait(timeout);
  198.     }
  199.     return (flags & GRABBEDBITS) != 0;
  200.     }
  201.  
  202.     /**
  203.      * Return the status of the pixels.  The ImageObserver flags
  204.      * representing the available pixel information are returned.
  205.      * @see ImageObserver
  206.      * @return the bitwise OR of all relevant ImageObserver flags
  207.      */
  208.     public synchronized int status() {
  209.     return flags;
  210.     }
  211.  
  212.     /**
  213.      * The setDimensions method is part of the ImageConsumer API which
  214.      * this class must implement to retrieve the pixels.
  215.      */
  216.     public void setDimensions(int width, int height) {
  217.     return;
  218.     }
  219.  
  220.     /**
  221.      * The setHints method is part of the ImageConsumer API which
  222.      * this class must implement to retrieve the pixels.
  223.      */
  224.     public void setHints(int hints) {
  225.     return;
  226.     }
  227.  
  228.     /**
  229.      * The setProperties method is part of the ImageConsumer API which
  230.      * this class must implement to retrieve the pixels.
  231.      */
  232.     public void setProperties(Hashtable props) {
  233.     return;
  234.     }
  235.  
  236.     /**
  237.      * The setColorModel method is part of the ImageConsumer API which
  238.      * this class must implement to retrieve the pixels.
  239.      */
  240.     public void setColorModel(ColorModel model) {
  241.     return;
  242.     }
  243.  
  244.     /**
  245.      * The setPixels method is part of the ImageConsumer API which
  246.      * this class must implement to retrieve the pixels.
  247.      */
  248.     public void setPixels(int srcX, int srcY, int srcW, int srcH,
  249.               ColorModel model,
  250.               byte pixels[], int srcOff, int srcScan) {
  251.     if (srcY < dstY) {
  252.         int diff = dstY - srcY;
  253.         if (diff >= srcH) {
  254.         return;
  255.         }
  256.         srcOff += srcScan * diff;
  257.         srcY += diff;
  258.         srcH -= diff;
  259.     }
  260.     if (srcY + srcH > dstY + dstH) {
  261.         srcH = (dstY + dstH) - srcY;
  262.         if (srcH <= 0) {
  263.         return;
  264.         }
  265.     }
  266.     if (srcX < dstX) {
  267.         int diff = dstX - srcX;
  268.         if (diff >= srcW) {
  269.         return;
  270.         }
  271.         srcOff += diff;
  272.         srcX += diff;
  273.         srcW -= diff;
  274.     }
  275.     if (srcX + srcW > dstX + dstW) {
  276.         srcW = (dstX + dstW) - srcX;
  277.         if (srcW <= 0) {
  278.         return;
  279.         }
  280.     }
  281.     int dstPtr = dstOff + (srcY - dstY) * dstScan + (srcX - dstX);
  282.     int dstRem = dstScan - dstW;
  283.     int srcRem = srcScan - srcW;
  284.     for (int h = srcH; h > 0; h--) {
  285.         for (int w = srcW; w > 0; w--) {
  286.         pixelbuf[dstPtr++] = model.getRGB(pixels[srcOff++] & 0xff);
  287.         }
  288.         srcOff += srcRem;
  289.         dstPtr += dstRem;
  290.     }
  291.     flags |= ImageObserver.SOMEBITS;
  292.     }
  293.  
  294.     /**
  295.      * The setPixels method is part of the ImageConsumer API which
  296.      * this class must implement to retrieve the pixels.
  297.      */
  298.     public void setPixels(int srcX, int srcY, int srcW, int srcH,
  299.               ColorModel model,
  300.               int pixels[], int srcOff, int srcScan) {
  301.     if (srcY < dstY) {
  302.         int diff = dstY - srcY;
  303.         if (diff >= srcH) {
  304.         return;
  305.         }
  306.         srcOff += srcScan * diff;
  307.         srcY += diff;
  308.         srcH -= diff;
  309.     }
  310.     if (srcY + srcH > dstY + dstH) {
  311.         srcH = (dstY + dstH) - srcY;
  312.         if (srcH <= 0) {
  313.         return;
  314.         }
  315.     }
  316.     if (srcX < dstX) {
  317.         int diff = dstX - srcX;
  318.         if (diff >= srcW) {
  319.         return;
  320.         }
  321.         srcOff += diff;
  322.         srcX += diff;
  323.         srcW -= diff;
  324.     }
  325.     if (srcX + srcW > dstX + dstW) {
  326.         srcW = (dstX + dstW) - srcX;
  327.         if (srcW <= 0) {
  328.         return;
  329.         }
  330.     }
  331.     int dstPtr = dstOff + (srcY - dstY) * dstScan + (srcX - dstX);
  332.     int dstRem = dstScan - dstW;
  333.     int srcRem = srcScan - srcW;
  334.     for (int h = srcH; h > 0; h--) {
  335.         for (int w = srcW; w > 0; w--) {
  336.         pixelbuf[dstPtr++] = model.getRGB(pixels[srcOff++]);
  337.         }
  338.         srcOff += srcRem;
  339.         dstPtr += dstRem;
  340.     }
  341.     flags |= ImageObserver.SOMEBITS;
  342.     }
  343.  
  344.     /**
  345.      * The imageComplete method is part of the ImageConsumer API which
  346.      * this class must implement to retrieve the pixels.
  347.      */
  348.     public synchronized void imageComplete(int status) {
  349.     grabbing = false;
  350.     switch (status) {
  351.     default:
  352.     case IMAGEERROR:
  353.         flags |= ImageObserver.ERROR | ImageObserver.ABORT;
  354.         break;
  355.     case IMAGEABORTED:
  356.         flags |= ImageObserver.ABORT;
  357.         break;
  358.     case STATICIMAGEDONE:
  359.         flags |= ImageObserver.ALLBITS;
  360.         break;
  361.     case SINGLEFRAMEDONE:
  362.         flags |= ImageObserver.FRAMEBITS;
  363.         break;
  364.     }
  365.     producer.removeConsumer(this);
  366.     notifyAll();
  367.     }
  368. }
  369.