/** * 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))); }
public JGImage rotateAny(double angle) { JGPoint size = getSize(); int sw = size.x; int sh = size.y; // destination size is upper bound size. Upper bound is the max // of the longest dimension and the figure's dimension at 45 degrees // = sw*sin(45)+sh*cos(45) ~= 1.5*(sw+sh) int dw = (int) Math.max(Math.max(sw, sh), 0.75 * (sw + sh)); int dh = dw; int xtrans = (dw - sw) / 2; int ytrans = (dh - sh) / 2; BufferedImage dst = createCompatibleImage(dw, dh, Transparency.BITMASK); Graphics2D g = (Graphics2D) dst.getGraphics(); AffineTransform tt = AffineTransform.getTranslateInstance(xtrans, ytrans); AffineTransform tr = AffineTransform.getRotateInstance(angle, sw / 2, sh / 2); tt.concatenate(tr); g.drawImage(img, tt, null); return new JREImage(dst); }
/** * Create RGBA-8 image from ints (each int = AABBGGRR). why isn't there a built in method to do * this? */ public static BufferedImage createRGBA8Image(int[] pix, int width, int height) { BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); img.setRGB(0, 0, width, height, pix, 0, width); return img; }