/** * Create possibly volatile scratch image for fast painting. A scratch image can become * invalidated, when this happens any actions involving it are ignored, and it needs to be * recreated. Use isScratchImageValid() to check this. */ public static Image createScratchImage(int width, int height) { try { Image img = (Image) tryMethod( output_comp, "createVolatileImage", new Object[] {new Integer(width), new Integer(height)}); if (img == null) { // no such method -> create regular image return output_comp.createImage(width, height); } // if (img.validate(output_comp.getGraphicsConfiguration()) // == VolatileImage.IMAGE_INCOMPATIBLE) { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gs = ge.getDefaultScreenDevice(); GraphicsConfiguration gc = gs.getDefaultConfiguration(); Integer valid = (Integer) tryMethod(img, "validate", new Object[] {gc}); // output_comp.getGraphicsConfiguration() }); if (valid.intValue() == 2) { // I checked, IMAGE_INCOMPATIBLE=2 // Hmm, somehow it didn't work. Create regular image. return output_comp.createImage(width, height); } return img; } catch (java.security.AccessControlException e) { // we're not allowed to do this (we're probably an applet) return output_comp.createImage(width, height); } }
public JGImage crop(int x, int y, int width, int height) { @SuppressWarnings("unused") JGPoint size = getSize(); int[] buffer = getPixels(x, y, width, height); return new JREImage( output_comp.createImage(new MemoryImageSource(width, height, buffer, 0, width))); }
public JGImage flip(boolean horiz, boolean vert) { @SuppressWarnings("unused") Image flipped = null; JGPoint size = getSize(); int[] buffer = getPixels(); int[] flipbuf = new int[size.x * size.y]; if (vert && !horiz) { for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { flipbuf[(size.y - y - 1) * size.x + x] = buffer[(y * size.x) + x]; } } } else if (horiz && !vert) { for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { flipbuf[y * size.x + (size.x - x - 1)] = buffer[(y * size.x) + x]; } } } else if (horiz && vert) { for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { flipbuf[(size.y - y - 1) * size.x + (size.x - x - 1)] = buffer[(y * size.x) + x]; } } } return new JREImage( output_comp.createImage(new MemoryImageSource(size.x, size.y, flipbuf, 0, size.x))); }
private void newImage(Buffer buffer) { Object data = buffer.getData(); if (!(data instanceof int[])) return; RGBFormat format = (RGBFormat) buffer.getFormat(); DirectColorModel dcm = new DirectColorModel( format.getBitsPerPixel(), format.getRedMask(), format.getGreenMask(), format.getBlueMask()); sourceImage = new MemoryImageSource( format.getLineStride(), format.getSize().height, dcm, (int[]) data, 0, format.getLineStride()); sourceImage.setAnimated(true); sourceImage.setFullBufferUpdates(true); if (component != null) { destImage = component.createImage(sourceImage); component.prepareImage(destImage, component); } }
/** for angle, only increments of 90 are allowed */ public JGImage rotate(int angle) { @SuppressWarnings("unused") Image rot = null; JGPoint size = getSize(); int[] buffer = getPixels(); int[] rotate = new int[size.x * size.y]; int angletype = (angle / 90) & 3; if (angletype == 0) return this; if (angletype == 1) { /* 1 2 3 4 9 5 1 * 5 6 7 8 => a 6 2 * 9 a b c b 7 3 * c 8 4 */ for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { rotate[x * size.y + (size.y - 1 - y)] = buffer[(y * size.x) + x]; } } return new JREImage( output_comp.createImage(new MemoryImageSource(size.y, size.x, rotate, 0, size.y))); } if (angletype == 3) { /* 1 2 3 4 4 8 c * 5 6 7 8 => 3 7 b * 9 a b c 2 6 a * 1 5 9 */ for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { rotate[(size.x - x - 1) * size.y + y] = buffer[(y * size.x) + x]; } } return new JREImage( output_comp.createImage(new MemoryImageSource(size.y, size.x, rotate, 0, size.y))); } if (angletype == 2) { /* 1 2 3 4 c b a 9 * 5 6 7 8 => 8 7 6 5 * 9 a b c 4 3 2 1 */ for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { rotate[((size.y - y - 1) * size.x) + (size.x - x - 1)] = buffer[(y * size.x) + x]; } } } return new JREImage( output_comp.createImage(new MemoryImageSource(size.x, size.y, rotate, 0, size.x))); }
/** * Turn a (possibly) translucent or indexed image into a display-compatible bitmask image using * the given alpha threshold and render-to-background colour, or display-compatible translucent * image. The alpha values in the image are set to either 0 (below threshold) or 255 (above * threshold). The render-to-background colour bg_col is used to determine how the pixels * overlapping transparent pixels should be rendered. The fast algorithm just sets the colour * behind the transparent pixels in the image (for bitmask source images); the slow algorithm * actually renders the image to a background of bg_col (for translucent sources). * * @param thresh alpha threshold between 0 and 255 * @param fast use fast algorithm (only set bg_col behind transp. pixels) * @param bitmask true=use bitmask, false=use translucent */ public JGImage toDisplayCompatible(int thresh, JGColor bg_col, boolean fast, boolean bitmask) { Color bgcol = new Color(bg_col.r, bg_col.g, bg_col.b); int bgcol_rgb = (bgcol.getRed() << 16) | (bgcol.getGreen() << 8) | bgcol.getBlue(); JGPoint size = getSize(); int[] buffer = getPixels(); // render image to bg depending on bgcol BufferedImage img_bg; if (bitmask) { img_bg = createCompatibleImage(size.x, size.y, Transparency.BITMASK); } else { img_bg = createCompatibleImage(size.x, size.y, Transparency.TRANSLUCENT); } int[] bg_buf; if (!fast) { Graphics g = img_bg.getGraphics(); g.setColor(bgcol); // the docs say I could use bgcol in the drawImage as an // equivalent to the following two lines, but this // doesn't handle translucency properly and is _slower_ g.fillRect(0, 0, size.x, size.y); g.drawImage(img, 0, 0, null); bg_buf = new JREImage(img_bg).getPixels(); } else { bg_buf = buffer; } // g.dispose(); // ColorModel rgb_bitmask = ColorModel.getRGBdefault(); // rgb_bitmask = new PackedColorModel( // rgb_bitmask.getColorSpace(),25,0xff0000,0x00ff00,0x0000ff, // 0x1000000, false, Transparency.BITMASK, DataBuffer.TYPE_INT); // ColorSpace space, int bits, int rmask, int gmask, int bmask, int amask, boolean // isAlphaPremultiplied, int trans, int transferType) int[] thrsbuf = new int[size.x * size.y]; for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { if (((buffer[y * size.x + x] >> 24) & 0xff) >= thresh) { thrsbuf[y * size.x + x] = bg_buf[y * size.x + x] | (0xff << 24); } else { // explicitly set the colour of the transparent pixel. // This makes a difference when scaling! // thrsbuf[y*size.x+x]=bg_buf[y*size.x+x]&~(0xff<<24); thrsbuf[y * size.x + x] = bgcol_rgb; } } } return new JREImage( output_comp.createImage( new MemoryImageSource( size.x, size.y, // rgb_bitmask, img_bg.getColorModel(), // display compatible bitmask bitmask ? thrsbuf : bg_buf, 0, size.x))); }
/** Prepare ball images with different sizes */ private void makeBalls() { balls = new Image[nBalls]; byte red[] = new byte[256]; byte green[] = new byte[256]; byte blue[] = new byte[256]; for (int id = 0; id < nBalls; id++) { // smaller `b' means closer to black // if id == 0 (fartherest from the viewer) // b = 1/(1 + zContrast) // the outer blend() gives a color close to bgGrey // if id == nBalls - 1 (closest to the viewer), // b = 1, the outer blend() gives the color of // the inner blend() double b = (zContrast * id / (nBalls - 1) + 1) / (zContrast + 1); for (int i = maxr; i >= 0; --i) { // closeness to the spotlight double q = 1 - 1. * i / maxr; // dampness of the color along the radius double p = 1 - rContrast * i / maxr; // contrast of the spotlight // if i == 0 (closest to the spotlight), // d = 1.0 - spotlightAmp, the inner // blend() gives a color close to 255 // (if spotlightAmp == 1). // if i == maxr (fartherest from the spotlight), // d = 1.0, the inner blend() gives // the foreground color, i.e., Rl, Gl, Bl // Thus, the inner blend() depends on the distance // from the spotlight, i == 0 means to be closest // to the spotlight double d = 1 - q * spotlightAmp; red[i] = (byte) blend(blend(Rl * p, 255, d), 0, b); green[i] = (byte) blend(blend(Gl * p, 255, d), 0, b); blue[i] = (byte) blend(blend(Bl * p, 255, d), 0, b); } // 256 color model IndexColorModel model = new IndexColorModel(8, maxr + 1, red, green, blue, 0); balls[id] = component.createImage(new MemoryImageSource(R * 2, R * 2, model, data, 0, R * 2)); } }