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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user