[2028] in java-interest
Re: new Image classes
daemon@ATHENA.MIT.EDU (Jim Graham)
Fri Sep 22 04:13:16 1995
Date: Thu, 21 Sep 1995 17:02:37 -0700
From: flar@bendenweyr.Eng.Sun.COM (Jim Graham)
To: java-interest@java.Eng.Sun.COM, jmorgan@x.co.uk
----------
X-Sun-Data-Type: text
X-Sun-Data-Description: text
X-Sun-Data-Name: text
X-Sun-Charset: us-ascii
X-Sun-Content-Lines: 68
> I'm tyring to convert my applets from alpha3 to beta, but I'm stuck on how
> to replace my use of DIBitmaps. I just want to get at the raw data of an
> image - I don't want to filter it or produce a new image, I just want to know
> the pixel value at a given coordinate. Can anyone show me a simple way of
> doing this?
There is no direct API for doing this since we don't necessarily have the
pixels for the image loaded into memory at any given time for two reasons:
1) We wanted to have the image data loaded asynchronously so
that Applets wouldn't get stuck waiting for image data to
come over the network while we were busy trying to layout
or paint the document (busy running their init() method when
we had other things to get done). This philosophy was carried
out to the extreme to the point that we don't provide any
synchronous methods to get information about an Image...
2) We may not have enough unfragmented memory laying around to
store all of the pixels for the image. Many of you may remember
that the Alpha 3 browser often failed to load large images
after running for a while since the heap could get fragmented
and there wouldn't be enough contiguous space to put the
array of pixels - thus pixel data is now only ever delivered
piecemeal and should be digested, put to use, and then dropped
on the floor (the image loaders save the data in special pixel
buffers that use "Ref" objects which allow asynchronous
reclamation of the space that they use and will avoid having
to refetch the image if their pixel buffer hasn't been freed,
so Applet programmers should not hold onto the image data
themselves if at all possible).
The idea behind the ImageFilter objects was that if you filter an
image, then you should filter it as the data is delivered rather than
to grab a buffer of pixels for the image, modify the pixels, and then
turn around and make a new image from that buffer. This doesn't work
when you need to filter lots of large images. The beta version of the
Sun home page now loads much more frequently in a lot less memory since
the ImageMap applet now uses dynamic filters rather than getDIBitmap
and createImage to make its button highlight areas...
For those cases when you need to query the contents of an image for
other purposes, then all you need to do is to create an object which
implements the ImageConsumer interface and attach it to the image's
ImageProducer. The ImageConsumer object will then have the image's
data fed to it asynchronously - when it gets what it wants, it can then
remove itself and return the information.
I wrote an example of this kind of class, which is attached below. To
use it you would write:
int[] pix = new int[w * h];
PixelGrabber pg = new PixelGrabber(img.getSource(),
x, y, w, h,
pix, 0, w);
pg.grabPixels();
When that method returns, the pix array will contain the data for the
specified subrectangle of the image in the default RGB format (see
ColorModel.getRGBdefault()). Note that since the grabPixels method
can take an arbitrarily large amount of time to complete, you should
not call it during any of an applet's methods that may be called by
a system thread (such as init(), paint(), or update()). Instead, call
it from a helper thread you create to do asynchronous setup.
Hope this helps!
...jim
----------
X-Sun-Data-Type: default
X-Sun-Data-Description: default
X-Sun-Data-Name: PixelGrabber.java
X-Sun-Charset: us-ascii
X-Sun-Content-Lines: 144
import java.util.Hashtable;
import java.awt.image.ImageProducer;
import java.awt.image.ImageConsumer;
import java.awt.image.ColorModel;
public class PixelGrabber implements ImageConsumer {
ImageProducer producer;
int dstX;
int dstY;
int dstW;
int dstH;
int[] pixelbuf;
int dstOff;
int dstScan;
public PixelGrabber(ImageProducer ip, int x, int y, int w, int h,
int[] pix, int off, int scansize) {
producer = ip;
dstX = x;
dstY = y;
dstW = w;
dstH = h;
dstOff = off;
dstScan = scansize;
pixelbuf = pix;
}
public synchronized void grabPixels() throws InterruptedException {
producer.startProduction(this);
wait();
}
public void setDimensions(int width, int height) {
return;
}
public void setHints(int hints) {
return;
}
public void setProperties(Hashtable props) {
return;
}
public void setColorModel(ColorModel model) {
return;
}
public void setPixels(int srcX, int srcY, int srcW, int srcH,
ColorModel model,
byte pixels[], int srcOff, int srcScan) {
if (srcY < dstY) {
int diff = dstY - srcY;
if (diff >= srcH) {
return;
}
srcOff += srcScan * diff;
srcY += diff;
srcH -= diff;
}
if (srcY + srcH > dstY + dstH) {
srcH = (dstY + dstH) - srcY;
if (srcH <= 0) {
return;
}
}
if (srcX < dstX) {
int diff = dstX - srcX;
if (diff >= srcW) {
return;
}
srcOff += diff;
srcX += diff;
srcW -= diff;
}
if (srcX + srcW > dstX + dstW) {
srcW = (dstX + dstW) - srcX;
if (srcW <= 0) {
return;
}
}
int dstOff = this.dstOff + (srcY - dstY) * dstW + (srcX - dstX);
int dstRem = dstScan - srcW;
int srcRem = srcScan - srcW;
for (int h = srcH; h > 0; h--) {
for (int w = srcW; w > 0; w--) {
pixelbuf[dstOff++] = model.getRGB(pixels[srcOff++] & 0xff);
}
srcOff += srcRem;
dstOff += dstRem;
}
}
public void setPixels(int srcX, int srcY, int srcW, int srcH,
ColorModel model,
int pixels[], int srcOff, int srcScan) {
if (srcY < dstY) {
int diff = dstY - srcY;
if (diff >= srcH) {
return;
}
srcOff += srcScan * diff;
srcY += diff;
srcH -= diff;
}
if (srcY + srcH > dstY + dstH) {
srcH = (dstY + dstH) - srcY;
if (srcH <= 0) {
return;
}
}
if (srcX < dstX) {
int diff = dstX - srcX;
if (diff >= srcW) {
return;
}
srcOff += diff;
srcX += diff;
srcW -= diff;
}
if (srcX + srcW > dstX + dstW) {
srcW = (dstX + dstW) - srcX;
if (srcW <= 0) {
return;
}
}
int dstOff = (srcY - dstY) * dstW + (srcX - dstX);
int dstRem = dstScan - dstW;
int srcRem = srcScan - srcW;
for (int h = srcH; h > 0; h--) {
for (int w = srcW; w > 0; w--) {
pixelbuf[dstOff++] = model.getRGB(pixels[srcOff++]);
}
srcOff += srcRem;
dstOff += dstRem;
}
}
public synchronized void imageComplete(int flags) {
notifyAll();
}
}
-
Note to Sun employees: this is an EXTERNAL mailing list!
Info: send 'help' to java-interest-request@java.sun.com