home *** CD-ROM | disk | FTP | other *** search
/ Java Programmer's Toolkit / Java Programmer's Toolkit.iso / src / java / awt / image / pixelg~1.jav < prev    next >
Encoding:
Text File  |  1996-01-12  |  10.6 KB  |  361 lines

  1. /*
  2.  * @(#)PixelGrabber.java    1.3 95/12/06 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 abstract void handlesinglepixel(int x, int y, int pixel);
  35.  *
  36.  * public void handlepixels(Image img, int x, int y, int w, int h) {
  37.  *    int[] pixels = new int[w * h];
  38.  *    PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixels, 0, w);
  39.  *    try {
  40.  *        pg.grabPixels();
  41.  *    } catch (InterruptedException e) {
  42.  *        System.err.println("interrupted waiting for pixels!");
  43.  *        return;
  44.  *    }
  45.  *    if ((pg.status() & ImageObserver.ABORT) != 0) {
  46.  *        System.err.println("image fetch aborted or errored");
  47.  *        return;
  48.  *    }
  49.  *    for (int j = 0; j < h; j++) {
  50.  *        for (int i = 0; i < w; i++) {
  51.  *        handlesinglepixel(x+i, y+j, pixels[j * w + i]);
  52.  *        }
  53.  *    }
  54.  * }
  55.  *
  56.  * </pre>
  57.  *
  58.  * @version     1.3, 12/06/95
  59.  * @author     Jim Graham
  60.  */
  61. public class PixelGrabber implements ImageConsumer {
  62.     ImageProducer producer;
  63.  
  64.     int dstX;
  65.     int dstY;
  66.     int dstW;
  67.     int dstH;
  68.  
  69.     int[] pixelbuf;
  70.     int dstOff;
  71.     int dstScan;
  72.  
  73.     private boolean grabbing;
  74.     private int flags;
  75.  
  76.     private final int GRABBEDBITS = (ImageObserver.FRAMEBITS
  77.                      | ImageObserver.ALLBITS);
  78.     private final int DONEBITS = (GRABBEDBITS
  79.                   | ImageObserver.ERROR);
  80.  
  81.     /**
  82.      * Create a PixelGrabber object to grab the (x, y, w, h) rectangular
  83.      * section of pixels from the specified image into the given array.
  84.      * The pixels are stored into the array in the default RGB ColorModel.
  85.      * The RGB data for pixel (i, j) where (i, j) is inside the rectangle
  86.      * (x, y, w, h) is stored in the array at
  87.      * <tt>pix[(j - y) * scansize + (i - x) + off]</tt>.
  88.      * @see ColorModel#getRGBdefault
  89.      * @param img the image to retrieve pixels from
  90.      * @param x the x coordinate of the upper left corner of the rectangle
  91.      * of pixels to retrieve from the image, relative to the default
  92.      * (unscaled) size of the image
  93.      * @param y the y coordinate of the upper left corner of the rectangle
  94.      * of pixels to retrieve from the image
  95.      * @param w the width of the rectangle of pixels to retrieve
  96.      * @param h the height of the rectangle of pixels to retrieve
  97.      * @param pix the array of integers which are to be used to hold the
  98.      * RGB pixels retrieved from the image
  99.      * @param off the offset into the array of where to store the first pixel
  100.      * @param scansize the distance from one row of pixels to the next in
  101.      * the array
  102.      */
  103.     public PixelGrabber(Image img, int x, int y, int w, int h,
  104.             int[] pix, int off, int scansize) {
  105.     this(img.getSource(), x, y, w, h, pix, off, scansize);
  106.     }
  107.  
  108.     /**
  109.      * Create a PixelGrabber object to grab the (x, y, w, h) rectangular
  110.      * section of pixels from the image produced by the specified
  111.      * ImageProducer into the given array.
  112.      * The pixels are stored into the array in the default RGB ColorModel.
  113.      * The RGB data for pixel (i, j) where (i, j) is inside the rectangle
  114.      * (x, y, w, h) is stored in the array at
  115.      * <tt>pix[(j - y) * scansize + (i - x) + off]</tt>.
  116.      * @see ColorModel#getRGBdefault
  117.      * @param img the image to retrieve pixels from
  118.      * @param x the x coordinate of the upper left corner of the rectangle
  119.      * of pixels to retrieve from the image, relative to the default
  120.      * (unscaled) size of the image
  121.      * @param y the y coordinate of the upper left corner of the rectangle
  122.      * of pixels to retrieve from the image
  123.      * @param w the width of the rectangle of pixels to retrieve
  124.      * @param h the height of the rectangle of pixels to retrieve
  125.      * @param pix the array of integers which are to be used to hold the
  126.      * RGB pixels retrieved from the image
  127.      * @param off the offset into the array of where to store the first pixel
  128.      * @param scansize the distance from one row of pixels to the next in
  129.      * the array
  130.      */
  131.     public PixelGrabber(ImageProducer ip, int x, int y, int w, int h,
  132.             int[] pix, int off, int scansize) {
  133.     producer = ip;
  134.     dstX = x;
  135.     dstY = y;
  136.     dstW = w;
  137.     dstH = h;
  138.     dstOff = off;
  139.     dstScan = scansize;
  140.     pixelbuf = pix;
  141.     }
  142.  
  143.     /**
  144.      * Request the Image or ImageProducer to start delivering pixels and
  145.      * wait for all of the pixels in the rectangle of interest to be
  146.      * delivered.
  147.      * @return true if the pixels were successfully grabbed, false on
  148.      * abort, error or timeout
  149.      * @exception InterruptedException 
  150.      *            Another thread has interrupted this thread.
  151.      */
  152.     public boolean grabPixels() throws InterruptedException {
  153.     return grabPixels(0);
  154.     }
  155.  
  156.     /**
  157.      * Request the Image or ImageProducer to start delivering pixels and
  158.      * wait for all of the pixels in the rectangle of interest to be
  159.      * delivered or until the specified timeout has elapsed.
  160.      * @param ms the number of milliseconds to wait for the image pixels
  161.      * to arrive before timing out
  162.      * @return true if the pixels were successfully grabbed, false on
  163.      * abort, error or timeout
  164.      * @exception InterruptedException 
  165.      *            Another thread has interrupted this thread. 
  166.      */
  167.     public synchronized boolean grabPixels(long ms)
  168.     throws InterruptedException
  169.     {
  170.     if ((flags & DONEBITS) != 0) {
  171.         return (flags & GRABBEDBITS) != 0;
  172.     }
  173.     long end = ms + System.currentTimeMillis();
  174.     if (!grabbing) {
  175.         producer.startProduction(this);
  176.         grabbing = true;
  177.         flags &= ~(ImageObserver.ABORT);
  178.     }
  179.     while (grabbing) {
  180.         long timeout;
  181.         if (ms == 0) {
  182.         timeout = 0;
  183.         } else {
  184.         timeout = end - System.currentTimeMillis();
  185.         if (timeout <= 0) {
  186.             break;
  187.         }
  188.         }
  189.         wait(timeout);
  190.     }
  191.     return (flags & GRABBEDBITS) != 0;
  192.     }
  193.  
  194.     /**
  195.      * Return the status of the pixels.  The ImageObserver flags
  196.      * representing the available pixel information are returned.
  197.      * @see ImageObserver
  198.      * @return the bitwise OR of all relevant ImageObserver flags
  199.      */
  200.     public synchronized int status() {
  201.     return flags;
  202.     }
  203.  
  204.     /**
  205.      * The setDimensions method is part of the ImageConsumer API which
  206.      * this class must implement to retrieve the pixels.
  207.      */
  208.     public void setDimensions(int width, int height) {
  209.     return;
  210.     }
  211.  
  212.     /**
  213.      * The setHints method is part of the ImageConsumer API which
  214.      * this class must implement to retrieve the pixels.
  215.      */
  216.     public void setHints(int hints) {
  217.     return;
  218.     }
  219.  
  220.     /**
  221.      * The setProperties method is part of the ImageConsumer API which
  222.      * this class must implement to retrieve the pixels.
  223.      */
  224.     public void setProperties(Hashtable props) {
  225.     return;
  226.     }
  227.  
  228.     /**
  229.      * The setColorModel method is part of the ImageConsumer API which
  230.      * this class must implement to retrieve the pixels.
  231.      */
  232.     public void setColorModel(ColorModel model) {
  233.     return;
  234.     }
  235.  
  236.     /**
  237.      * The setPixels method is part of the ImageConsumer API which
  238.      * this class must implement to retrieve the pixels.
  239.      */
  240.     public void setPixels(int srcX, int srcY, int srcW, int srcH,
  241.               ColorModel model,
  242.               byte pixels[], int srcOff, int srcScan) {
  243.     if (srcY < dstY) {
  244.         int diff = dstY - srcY;
  245.         if (diff >= srcH) {
  246.         return;
  247.         }
  248.         srcOff += srcScan * diff;
  249.         srcY += diff;
  250.         srcH -= diff;
  251.     }
  252.     if (srcY + srcH > dstY + dstH) {
  253.         srcH = (dstY + dstH) - srcY;
  254.         if (srcH <= 0) {
  255.         return;
  256.         }
  257.     }
  258.     if (srcX < dstX) {
  259.         int diff = dstX - srcX;
  260.         if (diff >= srcW) {
  261.         return;
  262.         }
  263.         srcOff += diff;
  264.         srcX += diff;
  265.         srcW -= diff;
  266.     }
  267.     if (srcX + srcW > dstX + dstW) {
  268.         srcW = (dstX + dstW) - srcX;
  269.         if (srcW <= 0) {
  270.         return;
  271.         }
  272.     }
  273.     int dstPtr = dstOff + (srcY - dstY) * dstScan + (srcX - dstX);
  274.     int dstRem = dstScan - dstW;
  275.     int srcRem = srcScan - srcW;
  276.     for (int h = srcH; h > 0; h--) {
  277.         for (int w = srcW; w > 0; w--) {
  278.         pixelbuf[dstPtr++] = model.getRGB(pixels[srcOff++] & 0xff);
  279.         }
  280.         srcOff += srcRem;
  281.         dstPtr += dstRem;
  282.     }
  283.     flags |= ImageObserver.SOMEBITS;
  284.     }
  285.  
  286.     /**
  287.      * The setPixels method is part of the ImageConsumer API which
  288.      * this class must implement to retrieve the pixels.
  289.      */
  290.     public void setPixels(int srcX, int srcY, int srcW, int srcH,
  291.               ColorModel model,
  292.               int pixels[], int srcOff, int srcScan) {
  293.     if (srcY < dstY) {
  294.         int diff = dstY - srcY;
  295.         if (diff >= srcH) {
  296.         return;
  297.         }
  298.         srcOff += srcScan * diff;
  299.         srcY += diff;
  300.         srcH -= diff;
  301.     }
  302.     if (srcY + srcH > dstY + dstH) {
  303.         srcH = (dstY + dstH) - srcY;
  304.         if (srcH <= 0) {
  305.         return;
  306.         }
  307.     }
  308.     if (srcX < dstX) {
  309.         int diff = dstX - srcX;
  310.         if (diff >= srcW) {
  311.         return;
  312.         }
  313.         srcOff += diff;
  314.         srcX += diff;
  315.         srcW -= diff;
  316.     }
  317.     if (srcX + srcW > dstX + dstW) {
  318.         srcW = (dstX + dstW) - srcX;
  319.         if (srcW <= 0) {
  320.         return;
  321.         }
  322.     }
  323.     int dstPtr = dstOff + (srcY - dstY) * dstScan + (srcX - dstX);
  324.     int dstRem = dstScan - dstW;
  325.     int srcRem = srcScan - srcW;
  326.     for (int h = srcH; h > 0; h--) {
  327.         for (int w = srcW; w > 0; w--) {
  328.         pixelbuf[dstPtr++] = model.getRGB(pixels[srcOff++]);
  329.         }
  330.         srcOff += srcRem;
  331.         dstPtr += dstRem;
  332.     }
  333.     flags |= ImageObserver.SOMEBITS;
  334.     }
  335.  
  336.     /**
  337.      * The imageComplete method is part of the ImageConsumer API which
  338.      * this class must implement to retrieve the pixels.
  339.      */
  340.     public synchronized void imageComplete(int status) {
  341.     grabbing = false;
  342.     switch (status) {
  343.     default:
  344.     case IMAGEERROR:
  345.         flags |= ImageObserver.ERROR | ImageObserver.ABORT;
  346.         break;
  347.     case IMAGEABORTED:
  348.         flags |= ImageObserver.ABORT;
  349.         break;
  350.     case STATICIMAGEDONE:
  351.         flags |= ImageObserver.ALLBITS;
  352.         break;
  353.     case SINGLEFRAMEDONE:
  354.         flags |= ImageObserver.FRAMEBITS;
  355.         break;
  356.     }
  357.     producer.removeConsumer(this);
  358.     notifyAll();
  359.     }
  360. }
  361.