Modified image tracing not to depend on band format but to have the image

convert whatever its internal format is into ARGB for our inspection. It's
arguably a smidge slower (though we eliminated the multiple method calls
per pixel to determine whether it is non-transparent), but will work with
any source and destination image format.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2220 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2003-01-24 22:54:08 +00:00
parent 347a070e6a
commit 412c7701c3
@@ -1,5 +1,5 @@
// //
// $Id: ImageUtil.java,v 1.28 2003/01/24 21:48:14 mdb Exp $ // $Id: ImageUtil.java,v 1.29 2003/01/24 22:54:08 mdb Exp $
package com.threerings.media.image; package com.threerings.media.image;
@@ -258,21 +258,15 @@ public class ImageUtil
ImageManager imgr, BufferedImage src, Color tcolor, int thickness, ImageManager imgr, BufferedImage src, Color tcolor, int thickness,
float startAlpha, float endAlpha) float startAlpha, float endAlpha)
{ {
Raster srcdata = src.getData();
int wid = src.getWidth(), hei = src.getHeight();
// create the destination image // create the destination image
int wid = src.getWidth(), hei = src.getHeight();
BufferedImage dest = imgr.createImage( BufferedImage dest = imgr.createImage(
wid, hei, Transparency.TRANSLUCENT); wid, hei, Transparency.TRANSLUCENT);
// prepare various bits of working data // prepare various bits of working data
int srcTrans = src.getColorModel().getTransparency(); int spixel = (tcolor.getRGB() & RGB_MASK);
int[] tpixel = new int[] { int salpha = (int)(startAlpha * 255);
tcolor.getRed(), tcolor.getGreen(), tcolor.getBlue(), int tpixel = (spixel | (salpha << 24));
(int)(startAlpha * 255)};
int[] curpixel = new int[4];
int[] workpixel = new int[4];
WritableRaster destdata = dest.getRaster();
boolean[] traced = new boolean[wid * hei]; boolean[] traced = new boolean[wid * hei];
int stepAlpha = (thickness <= 1) ? 0 : int stepAlpha = (thickness <= 1) ? 0 :
(int)(((startAlpha - endAlpha) * 255) / (thickness - 1)); (int)(((startAlpha - endAlpha) * 255) / (thickness - 1));
@@ -290,28 +284,24 @@ public class ImageUtil
// clear out the array of pixels traced this go-around // clear out the array of pixels traced this go-around
Arrays.fill(traced, false); Arrays.fill(traced, false);
// use the destination image as our new source // use the destination image as our new source
srcdata = dest.getData(); src = dest;
// decrement the trace pixel alpha-level // decrement the trace pixel alpha-level
tpixel[3] = Math.max(0, tpixel[3] - stepAlpha); salpha -= Math.max(0, stepAlpha);
tpixel = (spixel | (salpha << 24));
} }
for (int yy = 0; yy < hei; yy++) { for (int yy = 0; yy < hei; yy++) {
for (int xx = 0; xx < wid; xx++) { for (int xx = 0; xx < wid; xx++) {
// get the pixel we're checking // get the pixel we're checking
srcdata.getPixel(xx, yy, curpixel); int argb = src.getRGB(xx, yy);
if (!isTransparentPixel(curpixel)) { if ((argb & TRANS_MASK) != 0) {
// copy any pixel that isn't transparent // copy any pixel that isn't transparent
if (tt == 0 && srcTrans == Transparency.BITMASK) { dest.setRGB(xx, yy, argb);
// give any non-transparent pixel full opacity
curpixel[3] = 255;
}
destdata.setPixel(xx, yy, curpixel);
} else if (bordersNonTransparentPixel( } else if (bordersNonTransparentPixel(
srcdata, wid, hei, traced, src, wid, hei, traced, xx, yy)) {
xx, yy, workpixel)) { dest.setRGB(xx, yy, tpixel);
destdata.setPixel(xx, yy, tpixel);
// note that we traced this pixel this pass so // note that we traced this pixel this pass so
// that it doesn't impact other-pixel borderedness // that it doesn't impact other-pixel borderedness
traced[(yy*wid)+xx] = true; traced[(yy*wid)+xx] = true;
@@ -328,8 +318,7 @@ public class ImageUtil
* pixel. * pixel.
*/ */
protected static boolean bordersNonTransparentPixel ( protected static boolean bordersNonTransparentPixel (
Raster data, int wid, int hei, boolean[] traced, BufferedImage data, int wid, int hei, boolean[] traced, int x, int y)
int x, int y, int[] workpixel)
{ {
// check the three-pixel row above the pixel // check the three-pixel row above the pixel
if (y > 0) { if (y > 0) {
@@ -338,8 +327,7 @@ public class ImageUtil
continue; continue;
} }
data.getPixel(rxx, y - 1, workpixel); if ((data.getRGB(rxx, y - 1) & TRANS_MASK) != 0) {
if (!isTransparentPixel(workpixel)) {
return true; return true;
} }
} }
@@ -347,16 +335,14 @@ public class ImageUtil
// check the pixel to the left // check the pixel to the left
if (x > 0 && !traced[(y*wid)+(x-1)]) { if (x > 0 && !traced[(y*wid)+(x-1)]) {
data.getPixel(x - 1, y, workpixel); if ((data.getRGB(x - 1, y) & TRANS_MASK) != 0) {
if (!isTransparentPixel(workpixel)) {
return true; return true;
} }
} }
// check the pixel to the right // check the pixel to the right
if (x < wid - 1 && !traced[(y*wid)+(x+1)]) { if (x < wid - 1 && !traced[(y*wid)+(x+1)]) {
data.getPixel(x + 1, y, workpixel); if ((data.getRGB(x + 1, y) & TRANS_MASK) != 0) {
if (!isTransparentPixel(workpixel)) {
return true; return true;
} }
} }
@@ -368,8 +354,7 @@ public class ImageUtil
continue; continue;
} }
data.getPixel(rxx, y + 1, workpixel); if ((data.getRGB(rxx, y + 1) & TRANS_MASK) != 0) {
if (!isTransparentPixel(workpixel)) {
return true; return true;
} }
} }
@@ -378,14 +363,6 @@ public class ImageUtil
return false; return false;
} }
/**
* Returns whether the given pixel is completely transparent.
*/
protected static boolean isTransparentPixel (int[] pixel)
{
return (pixel[3] == 0);
}
/** /**
* Create an image using the alpha channel from the first and the RGB * Create an image using the alpha channel from the first and the RGB
* values from the second. * values from the second.
@@ -595,4 +572,10 @@ public class ImageUtil
/** The graphics configuration for the default screen device. */ /** The graphics configuration for the default screen device. */
protected static GraphicsConfiguration _gc; protected static GraphicsConfiguration _gc;
/** Used when seeking fully transparent pixels for outlining. */
protected static final int TRANS_MASK = (0xFF << 24);
/** Used when outlining. */
protected static final int RGB_MASK = 0x00FFFFFF;
} }