OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [awt/] [image/] [PixelGrabber.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* PixelGrabber.java -- retrieve a subset of an image's data
2
   Copyright (C) 1999, 2003, 2004  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package java.awt.image;
40
 
41
import java.awt.Image;
42
import java.util.Hashtable;
43
 
44
/**
45
 * PixelGrabber is an ImageConsumer that extracts a rectangular region
46
 * of pixels from an Image.
47
 */
48
public class PixelGrabber implements ImageConsumer
49
{
50
  int x, y, offset;
51
  int width = -1;
52
  int height = -1;
53
  int scansize = -1;
54
  boolean forceRGB = true;
55
 
56
  ColorModel model = ColorModel.getRGBdefault();
57
  int hints;
58
  Hashtable props;
59
 
60
  int int_pixel_buffer[];
61
  boolean ints_delivered = false;
62
  byte byte_pixel_buffer[];
63
  boolean bytes_delivered = false;
64
 
65
  ImageProducer ip;
66
  int observerStatus;
67
  int consumerStatus;
68
 
69
  private Thread grabberThread;
70
  boolean grabbing = false;
71
 
72
  /**
73
   * Construct a PixelGrabber that will retrieve RGB data from a given
74
   * Image.
75
   *
76
   * The RGB data will be retrieved from a rectangular region
77
   * <code>(x, y, w, h)</code> within the image.  The data will be
78
   * stored in the provided <code>pix</code> array, which must have
79
   * been initialized to a size of at least <code>w * h</code>.  The
80
   * data for a pixel (m, n) in the grab rectangle will be stored at
81
   * <code>pix[(n - y) * scansize + (m - x) + off]</code>.
82
   *
83
   * @param img the Image from which to grab pixels
84
   * @param x the x coordinate, relative to <code>img</code>'s
85
   * top-left corner, of the grab rectangle's top-left pixel
86
   * @param y the y coordinate, relative to <code>img</code>'s
87
   * top-left corner, of the grab rectangle's top-left pixel
88
   * @param w the width of the grab rectangle, in pixels
89
   * @param h the height of the grab rectangle, in pixels
90
   * @param pix the array in which to store grabbed RGB pixel data
91
   * @param off the offset into the <code>pix</code> array at which to
92
   * start storing RGB data
93
   * @param scansize a set of <code>scansize</code> consecutive
94
   * elements in the <code>pix</code> array represents one row of
95
   * pixels in the grab rectangle
96
   */
97
  public PixelGrabber(Image img, int x, int y, int w, int h,
98
                      int pix[], int off, int scansize)
99
  {
100
    this (img.getSource(), x, y, w, h, pix, off, scansize);
101
  }
102
 
103
  /**
104
   * Construct a PixelGrabber that will retrieve RGB data from a given
105
   * ImageProducer.
106
   *
107
   * The RGB data will be retrieved from a rectangular region
108
   * <code>(x, y, w, h)</code> within the image produced by
109
   * <code>ip</code>.  The data will be stored in the provided
110
   * <code>pix</code> array, which must have been initialized to a
111
   * size of at least <code>w * h</code>.  The data for a pixel (m, n)
112
   * in the grab rectangle will be stored at
113
   * <code>pix[(n - y) * scansize + (m - x) + off]</code>.
114
   *
115
   * @param ip the ImageProducer from which to grab pixels
116
   * @param x the x coordinate of the grab rectangle's top-left pixel,
117
   * specified relative to the top-left corner of the image produced
118
   * by <code>ip</code>
119
   * @param y the y coordinate of the grab rectangle's top-left pixel,
120
   * specified relative to the top-left corner of the image produced
121
   * by <code>ip</code>
122
   * @param w the width of the grab rectangle, in pixels
123
   * @param h the height of the grab rectangle, in pixels
124
   * @param pix the array in which to store grabbed RGB pixel data
125
   * @param off the offset into the <code>pix</code> array at which to
126
   * start storing RGB data
127
   * @param scansize a set of <code>scansize</code> consecutive
128
   * elements in the <code>pix</code> array represents one row of
129
   * pixels in the grab rectangle
130
   */
131
  public PixelGrabber(ImageProducer ip, int x, int y, int w, int h,
132
                      int pix[], int off, int scansize)
133
  {
134
    if (ip == null)
135
      throw new NullPointerException("The ImageProducer must not be null.");
136
 
137
    this.ip = ip;
138
    this.x = x;
139
    this.y = y;
140
    this.width = w;
141
    this.height = h;
142
    this.offset = off;
143
    this.scansize = scansize;
144
 
145
    int_pixel_buffer = pix;
146
    // Initialize the byte array in case ip sends us byte-formatted
147
    // pixel data.
148
    byte_pixel_buffer = new byte[pix.length * 4];
149
  }
150
 
151
  /**
152
   * Construct a PixelGrabber that will retrieve data from a given
153
   * Image.
154
   *
155
   * The RGB data will be retrieved from a rectangular region
156
   * <code>(x, y, w, h)</code> within the image.  The data will be
157
   * stored in an internal array which can be accessed by calling
158
   * <code>getPixels</code>.  The data for a pixel (m, n) in the grab
159
   * rectangle will be stored in the returned array at index
160
   * <code>(n - y) * scansize + (m - x) + off</code>.
161
   * If forceRGB is false, then the returned data will be not be
162
   * converted to RGB from its format in <code>img</code>.
163
   *
164
   * If <code>w</code> is negative, the width of the grab region will
165
   * be from x to the right edge of the image.  Likewise, if
166
   * <code>h</code> is negative, the height of the grab region will be
167
   * from y to the bottom edge of the image.
168
   *
169
   * @param img the Image from which to grab pixels
170
   * @param x the x coordinate, relative to <code>img</code>'s
171
   * top-left corner, of the grab rectangle's top-left pixel
172
   * @param y the y coordinate, relative to <code>img</code>'s
173
   * top-left corner, of the grab rectangle's top-left pixel
174
   * @param w the width of the grab rectangle, in pixels
175
   * @param h the height of the grab rectangle, in pixels
176
   * @param forceRGB true to force conversion of the rectangular
177
   * region's pixel data to RGB
178
   */
179
  public PixelGrabber(Image img,
180
                      int x, int y,
181
                      int w, int h,
182
                      boolean forceRGB)
183
  {
184
    this.ip = img.getSource();
185
 
186
    if (this.ip == null)
187
      throw new NullPointerException("The ImageProducer must not be null.");
188
 
189
    this.x = x;
190
    this.y = y;
191
    width = w;
192
    height = h;
193
    // If width or height is negative, postpone pixel buffer
194
    // initialization until setDimensions is called back by ip.
195
    if (width >= 0 && height >= 0)
196
      {
197
        int_pixel_buffer = new int[width * height];
198
        byte_pixel_buffer = new byte[width * height];
199
      }
200
    this.forceRGB = forceRGB;
201
  }
202
 
203
  /**
204
   * Start grabbing pixels.
205
   *
206
   * Spawns an image production thread that calls back to this
207
   * PixelGrabber's ImageConsumer methods.
208
   */
209
  public synchronized void startGrabbing()
210
  {
211
    // Make sure we're not already grabbing.
212
    if (grabbing == false)
213
      {
214
        grabbing = true;
215
        grabberThread = new Thread ()
216
          {
217
            public void run ()
218
            {
219
              try
220
                {
221
                  ip.startProduction (PixelGrabber.this);
222
                }
223
              catch (Exception ex)
224
                {
225
                  ex.printStackTrace();
226
                  imageComplete(ImageConsumer.IMAGEABORTED);
227
                }
228
            }
229
          };
230
        grabberThread.start ();
231
      }
232
  }
233
 
234
  /**
235
   * Abort pixel grabbing.
236
   */
237
  public synchronized void abortGrabbing()
238
  {
239
    if (grabbing)
240
      {
241
        // Interrupt the grabbing thread.
242
        Thread moribund = grabberThread;
243
        grabberThread = null;
244
        moribund.interrupt();
245
 
246
        imageComplete (ImageConsumer.IMAGEABORTED);
247
      }
248
  }
249
 
250
  /**
251
   * Have our Image or ImageProducer start sending us pixels via our
252
   * ImageConsumer methods and wait for all pixels in the grab
253
   * rectangle to be delivered.
254
   *
255
   * @return true if successful, false on abort or error
256
   *
257
   * @throws InterruptedException if interrupted by another thread.
258
   */
259
  public synchronized boolean grabPixels() throws InterruptedException
260
  {
261
    return grabPixels(0);
262
  }
263
 
264
  /**
265
   * grabPixels's behavior depends on the value of <code>ms</code>.
266
   *
267
   * If ms < 0, return true if all pixels from the source image have
268
   * been delivered, false otherwise.  Do not wait.
269
   *
270
   * If ms >= 0 then we request that our Image or ImageProducer start
271
   * delivering pixels to us via our ImageConsumer methods.
272
   *
273
   * If ms > 0, wait at most <code>ms</code> milliseconds for
274
   * delivery of all pixels within the grab rectangle.
275
   *
276
   * If ms == 0, wait until all pixels have been delivered.
277
   *
278
   * @return true if all pixels from the source image have been
279
   * delivered, false otherwise
280
   *
281
   * @throws InterruptedException if this thread is interrupted while
282
   * we are waiting for pixels to be delivered
283
   */
284
  public synchronized boolean grabPixels(long ms) throws InterruptedException
285
  {
286
    if (ms < 0)
287
      return ((observerStatus & (ImageObserver.FRAMEBITS
288
                                 | ImageObserver.ALLBITS)) != 0);
289
 
290
    // Spawn a new ImageProducer thread to send us the image data via
291
    // our ImageConsumer methods.
292
    startGrabbing();
293
 
294
    if (ms > 0)
295
      {
296
        long stop_time = System.currentTimeMillis() + ms;
297
        long time_remaining;
298
        while (grabbing)
299
          {
300
            time_remaining = stop_time - System.currentTimeMillis();
301
            if (time_remaining <= 0)
302
              break;
303
            wait (time_remaining);
304
          }
305
        abortGrabbing ();
306
      }
307
    else
308
      wait ();
309
 
310
    // If consumerStatus is non-zero then the image is done loading or
311
    // an error has occurred.
312
    if (consumerStatus != 0)
313
      return setObserverStatus ();
314
 
315
    return ((observerStatus & (ImageObserver.FRAMEBITS
316
                               | ImageObserver.ALLBITS)) != 0);
317
  }
318
 
319
  // Set observer status flags based on the current consumer status
320
  // flags.  Return true if the consumer flags indicate that the
321
  // image was loaded successfully, or false otherwise.
322
  private synchronized boolean setObserverStatus ()
323
  {
324
    boolean retval = false;
325
 
326
    if ((consumerStatus & IMAGEERROR) != 0)
327
      observerStatus |= ImageObserver.ERROR;
328
 
329
    if ((consumerStatus & IMAGEABORTED) != 0)
330
      observerStatus |= ImageObserver.ABORT;
331
 
332
    if ((consumerStatus & STATICIMAGEDONE) != 0)
333
      {
334
        observerStatus |= ImageObserver.ALLBITS;
335
        retval = true;
336
      }
337
 
338
    if ((consumerStatus & SINGLEFRAMEDONE) != 0)
339
      {
340
        observerStatus |= ImageObserver.FRAMEBITS;
341
        retval = true;
342
      }
343
 
344
    return retval;
345
  }
346
 
347
  /**
348
   * @return the status of the pixel grabbing thread, represented by a
349
   * bitwise OR of ImageObserver flags
350
   */
351
  public synchronized int getStatus()
352
  {
353
    return observerStatus;
354
  }
355
 
356
  /**
357
   * @return the width of the grab rectangle in pixels, or a negative
358
   * number if the ImageProducer has not yet called our setDimensions
359
   * method
360
   */
361
  public synchronized int getWidth()
362
  {
363
    return width;
364
  }
365
 
366
  /**
367
   * @return the height of the grab rectangle in pixels, or a negative
368
   * number if the ImageProducer has not yet called our setDimensions
369
   * method
370
   */
371
  public synchronized int getHeight()
372
  {
373
    return height;
374
  }
375
 
376
  /**
377
   * @return a byte array of pixel data if ImageProducer delivered
378
   * pixel data using the byte[] variant of setPixels, or an int array
379
   * otherwise
380
   */
381
  public synchronized Object getPixels()
382
  {
383
    if (ints_delivered)
384
      return int_pixel_buffer;
385
    else if (bytes_delivered)
386
      return byte_pixel_buffer;
387
    else
388
      return null;
389
  }
390
 
391
  /**
392
   * @return the ColorModel currently being used for the majority of
393
   * pixel data conversions
394
   */
395
  public synchronized ColorModel getColorModel()
396
  {
397
    return model;
398
  }
399
 
400
  /**
401
   * Our <code>ImageProducer</code> calls this method to indicate the
402
   * size of the image being produced.
403
   *
404
   * setDimensions is an ImageConsumer method.  None of PixelGrabber's
405
   * ImageConsumer methods should be called by code that instantiates
406
   * a PixelGrabber.  They are only made public so they can be called
407
   * by the PixelGrabber's ImageProducer.
408
   *
409
   * @param width the width of the image
410
   * @param height the height of the image
411
   */
412
  public synchronized void setDimensions(int width, int height)
413
  {
414
    // Our width wasn't set when we were constructed.  Set our width
415
    // so that the grab region includes all pixels from x to the right
416
    // edge of the source image.
417
    if (this.width < 0)
418
      this.width = width - x;
419
 
420
    // Our height wasn't set when we were constructed.  Set our height
421
    // so that the grab region includes all pixels from y to the
422
    // bottom edge of the source image.
423
    if (this.height < 0)
424
      this.height = height - y;
425
 
426
    if (scansize < 0)
427
      scansize = this.width;
428
 
429
    if (int_pixel_buffer == null)
430
      int_pixel_buffer = new int[this.width * this.height];
431
 
432
    if (byte_pixel_buffer == null)
433
      byte_pixel_buffer = new byte[this.width * this.height];
434
  }
435
 
436
  /**
437
   * Our <code>ImageProducer</code> may call this method to send us a
438
   * list of its image's properties.
439
   *
440
   * setProperties is an ImageConsumer method.  None of PixelGrabber's
441
   * ImageConsumer methods should be called by code that instantiates
442
   * a PixelGrabber.  They are only made public so they can be called
443
   * by the PixelGrabber's ImageProducer.
444
   *
445
   * @param props a list of properties associated with the image being
446
   * produced
447
   */
448
  public synchronized void setProperties(Hashtable props)
449
  {
450
    this.props = props;
451
  }
452
 
453
  /**
454
   * Our ImageProducer will call <code>setColorModel</code> to
455
   * indicate the model used by the majority of calls to
456
   * <code>setPixels</code>.  Each call to <code>setPixels</code>
457
   * could however indicate a different <code>ColorModel</code>.
458
   *
459
   * setColorModel is an ImageConsumer method.  None of PixelGrabber's
460
   * ImageConsumer methods should be called by code that instantiates
461
   * a PixelGrabber.  They are only made public so they can be called
462
   * by the PixelGrabber's ImageProducer.
463
   *
464
   * @param model the color model to be used most often by setPixels
465
   *
466
   * @see ColorModel
467
   */
468
  public synchronized void setColorModel(ColorModel model)
469
  {
470
    this.model = model;
471
  }
472
 
473
  /**
474
   * Our <code>ImageProducer</code> may call this method with a
475
   * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
476
   * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
477
   * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code>.
478
   *
479
   * setHints is an ImageConsumer method.  None of PixelGrabber's
480
   * ImageConsumer methods should be called by code that instantiates
481
   * a PixelGrabber.  They are only made public so they can be called
482
   * by the PixelGrabber's ImageProducer.
483
   *
484
   * @param flags a bit mask of hints
485
   */
486
  public synchronized void setHints(int flags)
487
  {
488
    hints = flags;
489
  }
490
 
491
  /**
492
   * Our ImageProducer calls setPixels to deliver a subset of its
493
   * pixels.
494
   *
495
   * Each element of the pixels array represents one pixel.  The
496
   * pixel data is formatted according to the color model model.
497
   * The x and y parameters are the coordinates of the rectangular
498
   * region of pixels being delivered to this ImageConsumer,
499
   * specified relative to the top left corner of the image being
500
   * produced.  Likewise, w and h are the pixel region's dimensions.
501
   *
502
   * @param x x coordinate of pixel block
503
   * @param y y coordinate of pixel block
504
   * @param w width of pixel block
505
   * @param h height of pixel block
506
   * @param model color model used to interpret pixel data
507
   * @param pixels pixel block data
508
   * @param offset offset into pixels array
509
   * @param scansize width of one row in the pixel block
510
   */
511
  public synchronized void setPixels(int x, int y, int w, int h,
512
                                     ColorModel model, byte[] pixels,
513
                                     int offset, int scansize)
514
  {
515
    ColorModel currentModel;
516
    if (model != null)
517
      currentModel = model;
518
    else
519
      currentModel = this.model;
520
 
521
    for(int yp = y; yp < (y + h); yp++)
522
      {
523
        for(int xp = x; xp < (x + w); xp++)
524
          {
525
            // Check if the coordinates (xp, yp) are within the
526
            // pixel block that we are grabbing.
527
            if(xp >= this.x
528
               && yp >= this.y
529
               && xp < (this.x + this.width)
530
               && yp < (this.y + this.height))
531
              {
532
                int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset;
533
                int p = (yp - y) * scansize + (xp - x) + offset;
534
                if (forceRGB)
535
                  {
536
                    ints_delivered = true;
537
 
538
                    int_pixel_buffer[i] = currentModel.getRGB (pixels[p] & 0xFF);
539
                  }
540
                else
541
                  {
542
                    bytes_delivered = true;
543
 
544
                    byte_pixel_buffer[i] = pixels[p];
545
                  }
546
              }
547
          }
548
      }
549
  }
550
 
551
  /**
552
   * Our ImageProducer calls setPixels to deliver a subset of its
553
   * pixels.
554
   *
555
   * Each element of the pixels array represents one pixel.  The
556
   * pixel data is formatted according to the color model model.
557
   * The x and y parameters are the coordinates of the rectangular
558
   * region of pixels being delivered to this ImageConsumer,
559
   * specified relative to the top left corner of the image being
560
   * produced.  Likewise, w and h are the pixel region's dimensions.
561
   *
562
   * @param x x coordinate of pixel block
563
   * @param y y coordinate of pixel block
564
   * @param w width of pixel block
565
   * @param h height of pixel block
566
   * @param model color model used to interpret pixel data
567
   * @param pixels pixel block data
568
   * @param offset offset into pixels array
569
   * @param scansize width of one row in the pixel block
570
   */
571
  public synchronized void setPixels(int x, int y, int w, int h,
572
                                     ColorModel model, int[] pixels,
573
                                     int offset, int scansize)
574
  {
575
    ColorModel currentModel;
576
    if (model != null)
577
      currentModel = model;
578
    else
579
      currentModel = this.model;
580
 
581
    ints_delivered = true;
582
 
583
    for(int yp = y; yp < (y + h); yp++)
584
      {
585
        for(int xp = x; xp < (x + w); xp++)
586
          {
587
            // Check if the coordinates (xp, yp) are within the
588
            // pixel block that we are grabbing.
589
            if(xp >= this.x
590
               && yp >= this.y
591
               && xp < (this.x + this.width)
592
               && yp < (this.y + this.height))
593
              {
594
                int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset;
595
                int p = (yp - y) * scansize + (xp - x) + offset;
596
                if (forceRGB)
597
                  int_pixel_buffer[i] = currentModel.getRGB (pixels[p]);
598
                else
599
                  int_pixel_buffer[i] = pixels[p];
600
              }
601
          }
602
      }
603
  }
604
 
605
  /**
606
   * Our <code>ImageProducer</code> calls this method to inform us
607
   * that a single frame or the entire image is complete.  The method
608
   * is also used to inform us of an error in loading or producing the
609
   * image.
610
   *
611
   * @param status the status of image production, represented by a
612
   * bitwise OR of ImageConsumer flags
613
   */
614
  public synchronized void imageComplete(int status)
615
  {
616
    consumerStatus = status;
617
    setObserverStatus ();
618
    grabbing = false;
619
    if (ip != null)
620
      ip.removeConsumer (this);
621
 
622
    notifyAll ();
623
  }
624
 
625
  /**
626
   * @return the return value of getStatus
627
   *
628
   * @specnote The newer getStatus should be used in place of status.
629
   */
630
  public synchronized int status()
631
  {
632
    return getStatus();
633
  }
634
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.