Hello,
This patch completes the PixelGrabber implementation, updates its
javadocs and includes a mauve test case.
OK to commit?
Tom
2003-11-24 Thomas Fitzsimmons <[EMAIL PROTECTED]>
* gnu/java/awt/peer/gtk/GtkImage.java (setDimensions,
setProperties): Check that io is not null before calling
io.imageUpdate.
* java/awt/image/ImageConsumer.java (setPixels, imageComplete):
Update javadocs.
* java/awt/image/PixelGrabber.java: Fix implementation and
update javadocs.
Index: gnu/java/awt/peer/gtk/GtkImage.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/awt/peer/gtk/GtkImage.java,v
retrieving revision 1.3
diff -u -r1.3 GtkImage.java
--- gnu/java/awt/peer/gtk/GtkImage.java 12 Nov 2003 00:37:33 -0000 1.3
+++ gnu/java/awt/peer/gtk/GtkImage.java 25 Nov 2003 03:59:01 -0000
@@ -1,5 +1,5 @@
/* GtkImage.java
- Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -168,13 +168,15 @@
for (int i = 0; i < widthObservers.size (); i++)
{
ImageObserver io = (ImageObserver) widthObservers.elementAt (i);
- io.imageUpdate (this, ImageObserver.WIDTH, -1, -1, width, height);
+ if (io != null)
+ io.imageUpdate (this, ImageObserver.WIDTH, -1, -1, width, height);
}
for (int i = 0; i < heightObservers.size (); i++)
{
ImageObserver io = (ImageObserver) heightObservers.elementAt (i);
- io.imageUpdate (this, ImageObserver.HEIGHT, -1, -1, width, height);
+ if (io != null)
+ io.imageUpdate (this, ImageObserver.HEIGHT, -1, -1, width, height);
}
if (observer != null)
@@ -192,7 +194,8 @@
for (int i = 0; i < propertyObservers.size (); i++)
{
ImageObserver io = (ImageObserver) propertyObservers.elementAt (i);
- io.imageUpdate (this, ImageObserver.PROPERTIES, -1, -1, width, height);
+ if (io != null)
+ io.imageUpdate (this, ImageObserver.PROPERTIES, -1, -1, width, height);
}
}
Index: java/awt/image/ImageConsumer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/image/ImageConsumer.java,v
retrieving revision 1.6
diff -u -r1.6 ImageConsumer.java
--- java/awt/image/ImageConsumer.java 11 Oct 2003 17:19:46 -0000 1.6
+++ java/awt/image/ImageConsumer.java 25 Nov 2003 03:59:01 -0000
@@ -1,5 +1,5 @@
/* ImageConsumer.java -- Java interface for image consumption
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -160,17 +160,45 @@
void setHints(int flags);
/**
- * This function delivers a rectangle of pixels where any
- * pixel(m,n) is stored in the array as a <code>byte</code> at
- * index (n * scansize + m + offset).
+ * Deliver a subset of an ImageProducer's pixels to this ImageConsumer.
+ *
+ * Each element of the pixels array represents one pixel. The
+ * pixel data is formatted according to the color model model.
+ * The x and y parameters are the coordinates of the block of
+ * pixels being delivered to this ImageConsumer. They are
+ * specified relative to the top left corner of the image being
+ * produced. Likewise, w and h are the pixel block's dimensions.
+ *
+ * @param x x coordinate of pixel block
+ * @param y y coordinate of pixel block
+ * @param w width of pixel block
+ * @param h height of pixel block
+ * @param model color model used to interpret pixel data
+ * @param pixels pixel block data
+ * @param offset offset into pixels array
+ * @param scansize width of one row in the pixel block
*/
void setPixels(int x, int y, int w, int h,
ColorModel model, byte[] pixels, int offset, int scansize);
/**
- * This function delivers a rectangle of pixels where any
- * pixel(m,n) is stored in the array as an <code>int</code> at
- * index (n * scansize + m + offset).
+ * Deliver a subset of an ImageProducer's pixels to this ImageConsumer.
+ *
+ * Each element of the pixels array represents one pixel. The
+ * pixel data is formatted according to the color model model.
+ * The x and y parameters are the coordinates of the rectangular
+ * region of pixels being delivered to this ImageConsumer,
+ * specified relative to the top left corner of the image being
+ * produced. Likewise, w and h are the pixel region's dimensions.
+ *
+ * @param x x coordinate of pixel block
+ * @param y y coordinate of pixel block
+ * @param w width of pixel block
+ * @param h height of pixel block
+ * @param model color model used to interpret pixel data
+ * @param pixels pixel block data
+ * @param offset offset into pixels array
+ * @param scansize width of one row in the pixel block
*/
void setPixels(int x, int y, int w, int h,
ColorModel model, int[] pixels, int offset, int scansize);
@@ -180,7 +208,9 @@
* single frame or the entire image is complete. The method is
* also used to indicate an error in loading or producing the
* image.
+ *
+ * @param status the status of image production, represented by a
+ * bitwise OR of ImageConsumer flags
*/
void imageComplete(int status);
}
-
Index: java/awt/image/PixelGrabber.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/image/PixelGrabber.java,v
retrieving revision 1.4
diff -u -r1.4 PixelGrabber.java
--- java/awt/image/PixelGrabber.java 27 Jun 2003 20:53:01 -0000 1.4
+++ java/awt/image/PixelGrabber.java 25 Nov 2003 03:59:01 -0000
@@ -1,39 +1,39 @@
-/* PixelGrabber.java -- Java class for providing image data
- Copyright (C) 1999 Free Software Foundation, Inc.
+/* PixelGrabber.java -- retrieve a subset of an image's data
+ Copyright (C) 1999, 2003 Free Software Foundation, Inc.
-This file is part of GNU Classpath.
+ This file is part of GNU Classpath.
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
package java.awt.image;
@@ -42,309 +42,583 @@
import java.util.Hashtable;
/**
- PixelGrabber is an ImageConsumer designed to extract a rectangular region of pixels
- from an Image
+ * PixelGrabber is an ImageConsumer that extracts a rectangular region
+ * of pixels from an Image.
*/
-public class PixelGrabber implements ImageConsumer
+public class PixelGrabber implements ImageConsumer
{
- int x, y, width, height, status, scansize, offset;
- ColorModel model = ColorModel.getRGBdefault();
- //int hints;
- //Hashtable props;
- int pixel_bufferi[];
- byte pixel_bufferb[];
- boolean grabbing;
- ImageProducer ip;
-
- /**
- * Create a PixelGrabber used to grab pixels from the specified Image
- * in the specified rectangle
- *
- * @param img the Image to grab pixels from
- * @param x the x coordinate of the rectangle
- * @param y the y coordinate of the rectangle
- * @param w the width of the rectangle
- * @param h the height of the rectangle
- * @param pixels the array of pixel values
- * @param offset the index of the first pixels in the <code>pixels</code> array
- * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
- */
- public PixelGrabber(Image img, int x, int y, int w, int h,
- int pix[], int off, int scansize)
- {
- this( img.getSource(), x, y, w, h, pix, off, scansize );
- }
-
- /**
- * Create a PixelGrabber used to grab pixels from the specified ImageProducer
- * in the specified rectangle
- *
- * @param ip the ImageProducer to grab pixels from
- * @param x the x coordinate of the rectangle
- * @param y the y coordinate of the rectangle
- * @param w the width of the rectangle
- * @param h the height of the rectangle
- * @param pixels the array of pixel values
- * @param offset the index of the first pixels in the <code>pixels</code> array
- * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
- */
- public PixelGrabber(ImageProducer ip, int x, int y, int w, int h,
- int pix[], int off, int scansize)
- {
- this.ip = ip;
- this.x = x;
- this.y = y;
- this.width = w;
- this.height = h;
- this.pixel_bufferi = pix;
- this.offset = off;
- this.scansize = scansize;
- pixel_bufferb = new byte[pix.length * 4];
- }
-
-
- /**
- * Create a PixelGrabber used to grab pixels from the specified Image
- * in the specified rectangle
- *
- * @param img the Image to grab pixels from
- * @param x the x coordinate of the rectangle
- * @param y the y coordinate of the rectangle
- * @param w the width of the rectangle
- * @param h the height of the rectangle
- * @param forceRGB true to force conversion to RGB
- */
- public PixelGrabber(Image img,
- int x, int y,
- int w, int h,
- boolean forceRGB)
- {
- //FIXME
- }
-
- /**
- Start Grabbing Pixels
- */
- public synchronized void startGrabbing()
- {
- if ( grabbing == false )
+ int x, y, offset;
+ int width = -1;
+ int height = -1;
+ int scansize = -1;
+ boolean forceRGB = true;
+
+ ColorModel model = ColorModel.getRGBdefault();
+ int hints;
+ Hashtable props;
+
+ int int_pixel_buffer[];
+ boolean ints_delivered = false;
+ byte byte_pixel_buffer[];
+ boolean bytes_delivered = false;
+
+ ImageProducer ip;
+ int observerStatus;
+ int consumerStatus;
+
+ private Thread grabberThread;
+ boolean grabbing = false;
+
+ /**
+ * Construct a PixelGrabber that will retrieve RGB data from a given
+ * Image.
+ *
+ * The RGB data will be retrieved from a rectangular region
+ * <code>(x, y, w, h)</code> within the image. The data will be
+ * stored in the provided <code>pix</code> array, which must have
+ * been initialized to a size of at least <code>w * h</code>. The
+ * data for a pixel (m, n) in the grab rectangle will be stored at
+ * <code>pix[(n - y) * scansize + (m - x) + off]</code>.
+ *
+ * @param img the Image from which to grab pixels
+ * @param x the x coordinate, relative to <code>img</code>'s
+ * top-left corner, of the grab rectangle's top-left pixel
+ * @param y the y coordinate, relative to <code>img</code>'s
+ * top-left corner, of the grab rectangle's top-left pixel
+ * @param w the width of the grab rectangle, in pixels
+ * @param h the height of the grab rectangle, in pixels
+ * @param pix the array in which to store grabbed RGB pixel data
+ * @param off the offset into the <code>pix</code> array at which to
+ * start storing RGB data
+ * @param scansize a set of <code>scansize</code> consecutive
+ * elements in the <code>pix</code> array represents one row of
+ * pixels in the grab rectangle
+ */
+ public PixelGrabber(Image img, int x, int y, int w, int h,
+ int pix[], int off, int scansize)
+ {
+ this (img.getSource(), x, y, w, h, pix, off, scansize);
+ }
+
+ /**
+ * Construct a PixelGrabber that will retrieve RGB data from a given
+ * ImageProducer.
+ *
+ * The RGB data will be retrieved from a rectangular region
+ * <code>(x, y, w, h)</code> within the image produced by
+ * <code>ip</code>. The data will be stored in the provided
+ * <code>pix</code> array, which must have been initialized to a
+ * size of at least <code>w * h</code>. The data for a pixel (m, n)
+ * in the grab rectangle will be stored at
+ * <code>pix[(n - y) * scansize + (m - x) + off]</code>.
+ *
+ * @param ip the ImageProducer from which to grab pixels
+ * @param x the x coordinate of the grab rectangle's top-left pixel,
+ * specified relative to the top-left corner of the image produced
+ * by <code>ip</code>
+ * @param y the y coordinate of the grab rectangle's top-left pixel,
+ * specified relative to the top-left corner of the image produced
+ * by <code>ip</code>
+ * @param w the width of the grab rectangle, in pixels
+ * @param h the height of the grab rectangle, in pixels
+ * @param pix the array in which to store grabbed RGB pixel data
+ * @param off the offset into the <code>pix</code> array at which to
+ * start storing RGB data
+ * @param scansize a set of <code>scansize</code> consecutive
+ * elements in the <code>pix</code> array represents one row of
+ * pixels in the grab rectangle
+ */
+ public PixelGrabber(ImageProducer ip, int x, int y, int w, int h,
+ int pix[], int off, int scansize)
+ {
+ this.ip = ip;
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ this.offset = off;
+ this.scansize = scansize;
+
+ int_pixel_buffer = pix;
+ // Initialize the byte array in case ip sends us byte-formatted
+ // pixel data.
+ byte_pixel_buffer = new byte[pix.length * 4];
+ }
+
+ /**
+ * Construct a PixelGrabber that will retrieve data from a given
+ * Image.
+ *
+ * The RGB data will be retrieved from a rectangular region
+ * <code>(x, y, w, h)</code> within the image. The data will be
+ * stored in an internal array which can be accessed by calling
+ * <code>getPixels</code>. The data for a pixel (m, n) in the grab
+ * rectangle will be stored in the returned array at index
+ * <code>(n - y) * scansize + (m - x) + off</code>.
+ * If forceRGB is false, then the returned data will be not be
+ * converted to RGB from its format in <code>img</code>.
+ *
+ * If <code>w</code> is negative, the width of the grab region will
+ * be from x to the right edge of the image. Likewise, if
+ * <code>h</code> is negative, the height of the grab region will be
+ * from y to the bottom edge of the image.
+ *
+ * @param img the Image from which to grab pixels
+ * @param x the x coordinate, relative to <code>img</code>'s
+ * top-left corner, of the grab rectangle's top-left pixel
+ * @param y the y coordinate, relative to <code>img</code>'s
+ * top-left corner, of the grab rectangle's top-left pixel
+ * @param w the width of the grab rectangle, in pixels
+ * @param h the height of the grab rectangle, in pixels
+ * @param forceRGB true to force conversion of the rectangular
+ * region's pixel data to RGB
+ */
+ public PixelGrabber(Image img,
+ int x, int y,
+ int w, int h,
+ boolean forceRGB)
+ {
+ this.ip = img.getSource();
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ // If width or height is negative, postpone pixel buffer
+ // initialization until setDimensions is called back by ip.
+ if (width >= 0 && height >= 0)
+ {
+ int_pixel_buffer = new int[width * height];
+ byte_pixel_buffer = new byte[width * height];
+ }
+ this.forceRGB = forceRGB;
+ }
+
+ /**
+ * Start grabbing pixels.
+ *
+ * Spawns an image production thread that calls back to this
+ * PixelGrabber's ImageConsumer methods.
+ */
+ public synchronized void startGrabbing()
+ {
+ // Make sure we're not already grabbing.
+ if (grabbing == false)
+ {
+ grabbing = true;
+ grabberThread = new Thread ()
+ {
+ public void run ()
{
- grabbing = true;
- ip.startProduction( this );
+ ip.startProduction (PixelGrabber.this);
}
- }
-
- /**
- Abort the grabbing of pixels
- */
- public synchronized void abortGrabbing()
- {
- if ( grabbing == true )
- {
- grabbing = false;
- ip.removeConsumer( this );
- }
- }
-
- /**
- Grab the Pixels.
-
- @return true if successful
-
- @throws InterruptedException if interrupted by another thread.
- */
- public boolean grabPixels() throws InterruptedException
- {
- return grabPixels(0);
- }
-
- /**
- Grab the Pixels and abort if it takes too long
-
- @return true if successful
-
- @throws InterruptedException if interrupted by another thread.
- or time runs out
- */
- public synchronized boolean grabPixels(long ms) throws InterruptedException
- {
- startGrabbing();
-
- if (ms < 0)
- return (status == ImageObserver.ALLBITS);
-
- wait(ms);
-
- if (status == ImageObserver.ALLBITS)
- return true;
- else
- return false;
- }
-
- /**
- Get the status of the pixel grabbing representing by ImageObserver flags
-
- @return the status
- */
- public synchronized int getStatus()
- {
- return status;
- }
-
- /**
- Return width of pixel region
-
- @return width of region
- */
- public synchronized int getWidth()
- {
- return width;
- }
-
- /**
- Return height of pixel region
-
- @return height of region
- */
- public synchronized int getHeight()
- {
- return height;
- }
-
- /**
- Returns the grabbed pixel buffer
-
- @return a byte or int array
- */
- public synchronized Object getPixels()
- {
- if( pixel_bufferi != null )
- return pixel_bufferi;
- return pixel_bufferb;
- }
-
- /**
- Get the ColorModel of the image
-
- @return the ColorModel
- */
- public synchronized ColorModel getColorModel()
- {
- return model;
- }
-
- /**
- * An <code>ImageProducer</code> indicates the size of the image
- * being produced using this method.
- *
- * @param width the width of the image
- * @param height the height of the image
- */
- public void setDimensions(int width, int height)
- {
- }
-
- /**
- * An <code>ImageProducer</code> can set a list of properties
- * associated with this image by using this method.
- *
- * @param props the list of properties associated with this image
- */
- public void setProperties(Hashtable props)
- {
- //this.props = props; //FIXME - DO WE NEED THIS
- }
-
- /**
- * This <code>ColorModel</code> should indicate the model used by
- * the majority of calls to <code>setPixels</code>. Each call to
- * <code>setPixels</code> could however indicate a different
- * <code>ColorModel</code>.
- *
- * @param model the color model to be used most often by setPixels
- * @see ColorModel
- */
- public void setColorModel(ColorModel model)
- {
- this.model = model;
- }
-
- /**
- * The <code>ImageProducer</code> should call this method with a
- * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
- * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
- * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code>.
- *
- * @param flags a bit mask of hints
- */
- public void setHints(int flags)
- {
- //hints = flags; // FIXME - DO NOT KNOW WHAT TO DO WITH THE HINTS
- }
-
- /**
- * This function delivers a rectangle of pixels where any
- * pixel(m,n) is stored in the array as a <code>byte</code> at
- * index (n * scansize + m + offset).
- */
- public void setPixels(int x, int y, int w, int h,
- ColorModel model, byte[] pixels, int offset, int scansize)
- {
- //FIXME - I hate bytes
- int xp, yp;
- for( xp = x; xp < ( x + w); xp++ )
- for( yp = y; yp < (y + h); yp++ )
- if( xp >= this.x &&
- yp >= this.y &&
- xp <= ( this.x + this.width ) &&
- yp <= ( this.y + this.height ) ) {
- pixel_bufferb[(yp - this.y) * this.scansize + (xp - this.x) + this.offset] =
- pixels[ offset + yp * scansize + xp ];
- }
-
- }
-
- /**
- * This function delivers a rectangle of pixels where any
- * pixel(m,n) is stored in the array as an <code>int</code> at
- * index (n * scansize + m + offset).
- */
- public void setPixels(int x, int y, int w, int h,
- ColorModel model, int[] pixels, int offset, int scansize)
- {
- int xp, yp;
- for( xp = x; xp < ( x + w); xp++ )
- for( yp = y; yp < (y + h); yp++ )
- if( xp >= this.x &&
- yp >= this.y &&
- xp <= ( this.x + this.width ) &&
- yp <= ( this.y + this.height ) ) {
- pixel_bufferi[(yp - this.y) * this.scansize + (xp - this.x) + this.offset] =
- pixels[ offset + yp * scansize + xp ];
- }
- }
-
- /**
- * The <code>ImageProducer</code> calls this method to indicate a
- * single frame or the entire image is complete. The method is
- * also used to indicate an error in loading or producing the
- * image.
- */
- public synchronized void imageComplete(int status)
- {
- this.status = status;
- }
-
- /**
- Get the status of the pixel grabbing representing by ImageObserver flags
-
- @return the status
-
- @specnote This method is not deprecated but getStatus is preferred to use
- */
- public synchronized int status()
- {
- return getStatus();
- }
-
+ };
+ grabberThread.start ();
+ }
+ }
+
+ /**
+ * Abort pixel grabbing.
+ */
+ public synchronized void abortGrabbing()
+ {
+ if (grabbing)
+ {
+ // Interrupt the grabbing thread.
+ Thread moribund = grabberThread;
+ grabberThread = null;
+ moribund.interrupt();
+
+ imageComplete (ImageConsumer.IMAGEABORTED);
+ }
+ }
+
+ /**
+ * Have our Image or ImageProducer start sending us pixels via our
+ * ImageConsumer methods and wait for all pixels in the grab
+ * rectangle to be delivered.
+ *
+ * @return true if successful, false on abort or error
+ *
+ * @throws InterruptedException if interrupted by another thread.
+ */
+ public synchronized boolean grabPixels() throws InterruptedException
+ {
+ return grabPixels(0);
+ }
+
+ /**
+ * grabPixels's behavior depends on the value of <code>ms</code>.
+ *
+ * If ms < 0, return true if all pixels from the source image have
+ * been delivered, false otherwise. Do not wait.
+ *
+ * If ms >= 0 then we request that our Image or ImageProducer start
+ * delivering pixels to us via our ImageConsumer methods.
+ *
+ * If ms > 0, wait at most <code>ms</code> milliseconds for
+ * delivery of all pixels within the grab rectangle.
+ *
+ * If ms == 0, wait until all pixels have been delivered.
+ *
+ * @return true if all pixels from the source image have been
+ * delivered, false otherwise
+ *
+ * @throws InterruptedException if this thread is interrupted while
+ * we are waiting for pixels to be delivered
+ */
+ public synchronized boolean grabPixels(long ms) throws InterruptedException
+ {
+ if (ms < 0)
+ return ((observerStatus & (ImageObserver.FRAMEBITS
+ | ImageObserver.ALLBITS)) != 0);
+
+ // Spawn a new ImageProducer thread to send us the image data via
+ // our ImageConsumer methods.
+ startGrabbing();
+
+ if (ms > 0)
+ {
+ long stop_time = System.currentTimeMillis() + ms;
+ long time_remaining;
+ while (grabbing)
+ {
+ time_remaining = stop_time - System.currentTimeMillis();
+ if (time_remaining <= 0)
+ break;
+ wait (time_remaining);
+ }
+ abortGrabbing ();
+ }
+ else
+ wait ();
+
+ // If consumerStatus is non-zero then the image is done loading or
+ // an error has occurred.
+ if (consumerStatus != 0)
+ return setObserverStatus ();
+
+ return ((observerStatus & (ImageObserver.FRAMEBITS
+ | ImageObserver.ALLBITS)) != 0);
+ }
+
+ // Set observer status flags based on the current consumer status
+ // flags. Return true if the consumer flags indicate that the
+ // image was loaded successfully, or false otherwise.
+ private synchronized boolean setObserverStatus ()
+ {
+ boolean retval = false;
+
+ if ((consumerStatus & IMAGEERROR) != 0)
+ observerStatus |= ImageObserver.ERROR;
+
+ if ((consumerStatus & IMAGEABORTED) != 0)
+ observerStatus |= ImageObserver.ABORT;
+
+ if ((consumerStatus & STATICIMAGEDONE) != 0)
+ {
+ observerStatus |= ImageObserver.ALLBITS;
+ retval = true;
+ }
+
+ if ((consumerStatus & SINGLEFRAMEDONE) != 0)
+ {
+ observerStatus |= ImageObserver.FRAMEBITS;
+ retval = true;
+ }
+
+ return retval;
+ }
+
+ /**
+ * @return the status of the pixel grabbing thread, represented by a
+ * bitwise OR of ImageObserver flags
+ */
+ public synchronized int getStatus()
+ {
+ return observerStatus;
+ }
+
+ /**
+ * @return the width of the grab rectangle in pixels, or a negative
+ * number if the ImageProducer has not yet called our setDimensions
+ * method
+ */
+ public synchronized int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * @return the height of the grab rectangle in pixels, or a negative
+ * number if the ImageProducer has not yet called our setDimensions
+ * method
+ */
+ public synchronized int getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * @return a byte array of pixel data if ImageProducer delivered
+ * pixel data using the byte[] variant of setPixels, or an int array
+ * otherwise
+ */
+ public synchronized Object getPixels()
+ {
+ if (ints_delivered)
+ return int_pixel_buffer;
+ else if (bytes_delivered)
+ return byte_pixel_buffer;
+ else
+ return null;
+ }
+
+ /**
+ * @return the ColorModel currently being used for the majority of
+ * pixel data conversions
+ */
+ public synchronized ColorModel getColorModel()
+ {
+ return model;
+ }
+
+ /**
+ * Our <code>ImageProducer</code> calls this method to indicate the
+ * size of the image being produced.
+ *
+ * setDimensions is an ImageConsumer method. None of PixelGrabber's
+ * ImageConsumer methods should be called by code that instantiates
+ * a PixelGrabber. They are only made public so they can be called
+ * by the PixelGrabber's ImageProducer.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ public synchronized void setDimensions(int width, int height)
+ {
+ // Our width wasn't set when we were constructed. Set our width
+ // so that the grab region includes all pixels from x to the right
+ // edge of the source image.
+ if (this.width < 0)
+ this.width = width - x;
+
+ // Our height wasn't set when we were constructed. Set our height
+ // so that the grab region includes all pixels from y to the
+ // bottom edge of the source image.
+ if (this.height < 0)
+ this.height = height - y;
+
+ if (scansize < 0)
+ scansize = this.width;
+
+ if (int_pixel_buffer == null)
+ int_pixel_buffer = new int[this.width * this.height];
+
+ if (byte_pixel_buffer == null)
+ byte_pixel_buffer = new byte[this.width * this.height];
+ }
+
+ /**
+ * Our <code>ImageProducer</code> may call this method to send us a
+ * list of its image's properties.
+ *
+ * setProperties is an ImageConsumer method. None of PixelGrabber's
+ * ImageConsumer methods should be called by code that instantiates
+ * a PixelGrabber. They are only made public so they can be called
+ * by the PixelGrabber's ImageProducer.
+ *
+ * @param props a list of properties associated with the image being
+ * produced
+ */
+ public synchronized void setProperties(Hashtable props)
+ {
+ this.props = props;
+ }
+
+ /**
+ * Our ImageProducer will call <code>setColorModel</code> to
+ * indicate the model used by the majority of calls to
+ * <code>setPixels</code>. Each call to <code>setPixels</code>
+ * could however indicate a different <code>ColorModel</code>.
+ *
+ * setColorModel is an ImageConsumer method. None of PixelGrabber's
+ * ImageConsumer methods should be called by code that instantiates
+ * a PixelGrabber. They are only made public so they can be called
+ * by the PixelGrabber's ImageProducer.
+ *
+ * @param model the color model to be used most often by setPixels
+ *
+ * @see ColorModel
+ */
+ public synchronized void setColorModel(ColorModel model)
+ {
+ this.model = model;
+ }
+
+ /**
+ * Our <code>ImageProducer</code> may call this method with a
+ * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
+ * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
+ * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code>.
+ *
+ * setHints is an ImageConsumer method. None of PixelGrabber's
+ * ImageConsumer methods should be called by code that instantiates
+ * a PixelGrabber. They are only made public so they can be called
+ * by the PixelGrabber's ImageProducer.
+ *
+ * @param flags a bit mask of hints
+ */
+ public synchronized void setHints(int flags)
+ {
+ hints = flags;
+ }
+
+ /**
+ * Our ImageProducer calls setPixels to deliver a subset of its
+ * pixels.
+ *
+ * Each element of the pixels array represents one pixel. The
+ * pixel data is formatted according to the color model model.
+ * The x and y parameters are the coordinates of the rectangular
+ * region of pixels being delivered to this ImageConsumer,
+ * specified relative to the top left corner of the image being
+ * produced. Likewise, w and h are the pixel region's dimensions.
+ *
+ * @param x x coordinate of pixel block
+ * @param y y coordinate of pixel block
+ * @param w width of pixel block
+ * @param h height of pixel block
+ * @param model color model used to interpret pixel data
+ * @param pixels pixel block data
+ * @param offset offset into pixels array
+ * @param scansize width of one row in the pixel block
+ */
+ public synchronized void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels,
+ int offset, int scansize)
+ {
+ ColorModel currentModel;
+ if (model != null)
+ currentModel = model;
+ else
+ currentModel = this.model;
+
+ for(int yp = y; yp < (y + h); yp++)
+ {
+ for(int xp = x; xp < (x + w); xp++)
+ {
+ // Check if the coordinates (xp, yp) are within the
+ // pixel block that we are grabbing.
+ if(xp >= this.x
+ && yp >= this.y
+ && xp < (this.x + this.width)
+ && yp < (this.y + this.height))
+ {
+ int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset;
+ int p = (yp - y) * scansize + (xp - x) + offset;
+ if (forceRGB)
+ {
+ ints_delivered = true;
+
+ assert (i >= 0 && i < int_pixel_buffer.length);
+ assert (p >= 0 && p < pixels.length);
+ int_pixel_buffer[i] = currentModel.getRGB (pixels[p]);
+ }
+ else
+ {
+ bytes_delivered = true;
+
+ assert (i >= 0 && i < byte_pixel_buffer.length);
+ assert (p >= 0 && p < pixels.length);
+ byte_pixel_buffer[i] = pixels[p];
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Our ImageProducer calls setPixels to deliver a subset of its
+ * pixels.
+ *
+ * Each element of the pixels array represents one pixel. The
+ * pixel data is formatted according to the color model model.
+ * The x and y parameters are the coordinates of the rectangular
+ * region of pixels being delivered to this ImageConsumer,
+ * specified relative to the top left corner of the image being
+ * produced. Likewise, w and h are the pixel region's dimensions.
+ *
+ * @param x x coordinate of pixel block
+ * @param y y coordinate of pixel block
+ * @param w width of pixel block
+ * @param h height of pixel block
+ * @param model color model used to interpret pixel data
+ * @param pixels pixel block data
+ * @param offset offset into pixels array
+ * @param scansize width of one row in the pixel block
+ */
+ public synchronized void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels,
+ int offset, int scansize)
+ {
+ ColorModel currentModel;
+ if (model != null)
+ currentModel = model;
+ else
+ currentModel = this.model;
+
+ ints_delivered = true;
+
+ for(int yp = y; yp < (y + h); yp++)
+ {
+ for(int xp = x; xp < (x + w); xp++)
+ {
+ // Check if the coordinates (xp, yp) are within the
+ // pixel block that we are grabbing.
+ if(xp >= this.x
+ && yp >= this.y
+ && xp < (this.x + this.width)
+ && yp < (this.y + this.height))
+ {
+ int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset;
+ int p = (yp - y) * scansize + (xp - x) + offset;
+ assert (i >= 0 && i < int_pixel_buffer.length);
+ assert (p >= 0 && p < pixels.length);
+ if (forceRGB)
+ int_pixel_buffer[i] = currentModel.getRGB (pixels[p]);
+ else
+ int_pixel_buffer[i] = pixels[p];
+ }
+ }
+ }
+ }
+
+ /**
+ * Our <code>ImageProducer</code> calls this method to inform us
+ * that a single frame or the entire image is complete. The method
+ * is also used to inform us of an error in loading or producing the
+ * image.
+ *
+ * @param status the status of image production, represented by a
+ * bitwise OR of ImageConsumer flags
+ */
+ public synchronized void imageComplete(int status)
+ {
+ consumerStatus = status;
+ setObserverStatus ();
+ grabbing = false;
+ ip.removeConsumer (this);
+
+ notifyAll ();
+ }
+
+ /**
+ * @return the return value of getStatus
+ *
+ * @specnote The newer getStatus should be used in place of status.
+ */
+ public synchronized int status()
+ {
+ return getStatus();
+ }
}
// Tags: JDK1.0
/* SimpleGrabber.java
Copyright (C) 2003 Red Hat, Inc.
This file is part of Mauve.
Mauve is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Mauve is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mauve; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
package gnu.testlet.java.awt.image.PixelGrabber;
import gnu.testlet.Testlet;
import gnu.testlet.TestHarness;
import java.awt.*;
import java.awt.image.*;
public class SimpleGrabber implements Testlet
{
TestHarness harness;
public void test (TestHarness harness)
{
this.harness = harness;
Image i = null;
try
{
String f = "gnu#testlet#java#awt#image#PixelGrabber#lena1.jpg";
i = Toolkit.getDefaultToolkit().getImage (harness.getResourceFile (f).getAbsolutePath ());
}
catch (Exception e)
{
harness.fail ("lena1.jpg not found.");
}
String str = getPixels (i, 0, 0, 6, 12);
harness.check (str,
"Pixel (0, 0)\n"
+ " R: 98 G: 31 B: 82\n"
+ "Pixel (1, 0)\n"
+ " R: 79 G: 12 B: 63\n"
+ "Pixel (2, 0)\n"
+ " R: 76 G: 9 B: 60\n"
+ "Pixel (3, 0)\n"
+ " R: 152 G: 85 B: 136\n"
+ "Pixel (4, 0)\n"
+ " R: 132 G: 66 B: 114\n"
+ "Pixel (5, 0)\n"
+ " R: 95 G: 29 B: 77\n"
+ "Pixel (0, 1)\n"
+ " R: 86 G: 19 B: 70\n"
+ "Pixel (1, 1)\n"
+ " R: 75 G: 8 B: 59\n"
+ "Pixel (2, 1)\n"
+ " R: 81 G: 14 B: 65\n"
+ "Pixel (3, 1)\n"
+ " R: 150 G: 83 B: 134\n"
+ "Pixel (4, 1)\n"
+ " R: 121 G: 55 B: 103\n"
+ "Pixel (5, 1)\n"
+ " R: 85 G: 19 B: 67\n"
+ "Pixel (0, 2)\n"
+ " R: 75 G: 11 B: 61\n"
+ "Pixel (1, 2)\n"
+ " R: 79 G: 15 B: 65\n"
+ "Pixel (2, 2)\n"
+ " R: 100 G: 36 B: 86\n"
+ "Pixel (3, 2)\n"
+ " R: 155 G: 91 B: 141\n"
+ "Pixel (4, 2)\n"
+ " R: 115 G: 52 B: 99\n"
+ "Pixel (5, 2)\n"
+ " R: 76 G: 13 B: 60\n"
+ "Pixel (0, 3)\n"
+ " R: 70 G: 8 B: 57\n"
+ "Pixel (1, 3)\n"
+ " R: 91 G: 29 B: 78\n"
+ "Pixel (2, 3)\n"
+ " R: 122 G: 60 B: 109\n"
+ "Pixel (3, 3)\n"
+ " R: 162 G: 100 B: 149\n"
+ "Pixel (4, 3)\n"
+ " R: 116 G: 53 B: 100\n"
+ "Pixel (5, 3)\n"
+ " R: 69 G: 6 B: 53\n"
+ "Pixel (0, 4)\n"
+ " R: 72 G: 13 B: 61\n"
+ "Pixel (1, 4)\n"
+ " R: 102 G: 43 B: 91\n"
+ "Pixel (2, 4)\n"
+ " R: 128 G: 69 B: 117\n"
+ "Pixel (3, 4)\n"
+ " R: 154 G: 95 B: 143\n"
+ "Pixel (4, 4)\n"
+ " R: 120 G: 58 B: 105\n"
+ "Pixel (5, 4)\n"
+ " R: 64 G: 2 B: 49\n"
+ "Pixel (0, 5)\n"
+ " R: 95 G: 36 B: 84\n"
+ "Pixel (1, 5)\n"
+ " R: 117 G: 58 B: 106\n"
+ "Pixel (2, 5)\n"
+ " R: 119 G: 60 B: 108\n"
+ "Pixel (3, 5)\n"
+ " R: 136 G: 77 B: 125\n"
+ "Pixel (4, 5)\n"
+ " R: 133 G: 74 B: 120\n"
+ "Pixel (5, 5)\n"
+ " R: 73 G: 14 B: 60\n"
+ "Pixel (0, 6)\n"
+ " R: 123 G: 65 B: 113\n"
+ "Pixel (1, 6)\n"
+ " R: 125 G: 67 B: 115\n"
+ "Pixel (2, 6)\n"
+ " R: 93 G: 35 B: 83\n"
+ "Pixel (3, 6)\n"
+ " R: 106 G: 48 B: 96\n"
+ "Pixel (4, 6)\n"
+ " R: 146 G: 89 B: 134\n"
+ "Pixel (5, 6)\n"
+ " R: 88 G: 31 B: 76\n"
+ "Pixel (0, 7)\n"
+ " R: 137 G: 79 B: 127\n"
+ "Pixel (1, 7)\n"
+ " R: 123 G: 65 B: 113\n"
+ "Pixel (2, 7)\n"
+ " R: 65 G: 7 B: 55\n"
+ "Pixel (3, 7)\n"
+ " R: 78 G: 20 B: 68\n"
+ "Pixel (4, 7)\n"
+ " R: 149 G: 92 B: 137\n"
+ "Pixel (5, 7)\n"
+ " R: 95 G: 38 B: 83\n"
+ "Pixel (0, 8)\n"
+ " R: 138 G: 80 B: 128\n"
+ "Pixel (1, 8)\n"
+ " R: 96 G: 38 B: 86\n"
+ "Pixel (2, 8)\n"
+ " R: 78 G: 20 B: 68\n"
+ "Pixel (3, 8)\n"
+ " R: 76 G: 18 B: 66\n"
+ "Pixel (4, 8)\n"
+ " R: 106 G: 49 B: 94\n"
+ "Pixel (5, 8)\n"
+ " R: 122 G: 65 B: 110\n"
+ "Pixel (0, 9)\n"
+ " R: 155 G: 97 B: 145\n"
+ "Pixel (1, 9)\n"
+ " R: 99 G: 41 B: 89\n"
+ "Pixel (2, 9)\n"
+ " R: 73 G: 15 B: 63\n"
+ "Pixel (3, 9)\n"
+ " R: 80 G: 22 B: 70\n"
+ "Pixel (4, 9)\n"
+ " R: 115 G: 58 B: 103\n"
+ "Pixel (5, 9)\n"
+ " R: 107 G: 50 B: 95\n"
+ "Pixel (0, 10)\n"
+ " R: 165 G: 106 B: 154\n"
+ "Pixel (1, 10)\n"
+ " R: 99 G: 40 B: 88\n"
+ "Pixel (2, 10)\n"
+ " R: 68 G: 9 B: 57\n"
+ "Pixel (3, 10)\n"
+ " R: 83 G: 24 B: 72\n"
+ "Pixel (4, 10)\n"
+ " R: 123 G: 64 B: 110\n"
+ "Pixel (5, 10)\n"
+ " R: 88 G: 29 B: 75\n"
+ "Pixel (0, 11)\n"
+ " R: 151 G: 92 B: 140\n"
+ "Pixel (1, 11)\n"
+ " R: 93 G: 34 B: 82\n"
+ "Pixel (2, 11)\n"
+ " R: 68 G: 9 B: 57\n"
+ "Pixel (3, 11)\n"
+ " R: 81 G: 22 B: 70\n"
+ "Pixel (4, 11)\n"
+ " R: 120 G: 58 B: 105\n"
+ "Pixel (5, 11)\n"
+ " R: 74 G: 12 B: 59\n");
}
// Test eight-parameter constructor.
public String getPixels(Image img, int x, int y, int w, int h)
{
int[] pix = new int[w * h];
PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pix, 0, w);
try
{
pg.grabPixels(5000);
}
catch (InterruptedException e)
{
harness.fail ("image production interrupted.");
return "";
}
if ((pg.getStatus() & ImageObserver.ABORT) != 0)
{
harness.fail ("image production aborted.");
return "";
}
String result = "";
for (int j = 0; j < h; j++)
{
for (int i = 0; i < w; i++)
{
int p = j * w + i;
result = result + getPixel (x + i, y + j, pix[p]);
}
}
return result;
}
public String getPixel (int x, int y, int pixel)
{
ColorModel model = ColorModel.getRGBdefault();
return "Pixel (" + x + ", " + y + ")\n "
+ " R: " + model.getRed (pixel)
+ " G: " + model.getGreen (pixel)
+ " B: " + model.getBlue (pixel) + "\n";
}
}
_______________________________________________
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath