diff options
author | sowgro <tpoke.ferrari@gmail.com> | 2023-05-05 08:18:31 -0400 |
---|---|---|
committer | sowgro <tpoke.ferrari@gmail.com> | 2023-05-05 08:18:31 -0400 |
commit | 9e9e1a5a1b43c50e7ce962e7be734c958cc67cf2 (patch) | |
tree | 1e3f088dd223310fc08f0ed0a0336a9143c93df3 /dropShadow/ShadowRenderer.java | |
parent | a36ff772f5c180030f25883f7a63307a66bdb838 (diff) | |
download | NPEhero-9e9e1a5a1b43c50e7ce962e7be734c958cc67cf2.tar.gz NPEhero-9e9e1a5a1b43c50e7ce962e7be734c958cc67cf2.tar.bz2 NPEhero-9e9e1a5a1b43c50e7ce962e7be734c958cc67cf2.zip |
lots of methods to try to get a drop shadow
Diffstat (limited to 'dropShadow/ShadowRenderer.java')
-rw-r--r-- | dropShadow/ShadowRenderer.java | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/dropShadow/ShadowRenderer.java b/dropShadow/ShadowRenderer.java new file mode 100644 index 0000000..d80d2c8 --- /dev/null +++ b/dropShadow/ShadowRenderer.java @@ -0,0 +1,185 @@ +package dropShadow; + +import java.awt.Color; +import java.awt.image.BufferedImage; + +public class ShadowRenderer { + + // size of the shadow in pixels (defines the fuzziness) + private int size = 5; + + // opacity of the shadow + private float opacity = 0.5f; + + // color of the shadow + private Color color = Color.BLACK; + + public ShadowRenderer() { + this(5, 0.5f, Color.BLACK); + } + + public ShadowRenderer(final int size, final float opacity, final Color color) { + this.size = size; + this.opacity = opacity; + this.color = color; + } + + public Color getColor() { + return color; + } + + public float getOpacity() { + return opacity; + } + + public int getSize() { + return size; + } + + public BufferedImage createShadow(final BufferedImage image) { + // Written by Sesbastien Petrucci + int shadowSize = size * 2; + + int srcWidth = image.getWidth(); + int srcHeight = image.getHeight(); + + int dstWidth = srcWidth + shadowSize; + int dstHeight = srcHeight + shadowSize; + + int left = size; + int right = shadowSize - left; + + int yStop = dstHeight - right; + + int shadowRgb = color.getRGB() & 0x00FFFFFF; + int[] aHistory = new int[shadowSize]; + int historyIdx; + + int aSum; + + BufferedImage dst = new BufferedImage(dstWidth, dstHeight, + BufferedImage.TYPE_INT_ARGB); + + int[] dstBuffer = new int[dstWidth * dstHeight]; + int[] srcBuffer = new int[srcWidth * srcHeight]; + + GraphicsUtilities.getPixels(image, 0, 0, srcWidth, srcHeight, srcBuffer); + + int lastPixelOffset = right * dstWidth; + float hSumDivider = 1.0f / shadowSize; + float vSumDivider = opacity / shadowSize; + + int[] hSumLookup = new int[256 * shadowSize]; + for (int i = 0; i < hSumLookup.length; i++) { + hSumLookup[i] = (int) (i * hSumDivider); + } + + int[] vSumLookup = new int[256 * shadowSize]; + for (int i = 0; i < vSumLookup.length; i++) { + vSumLookup[i] = (int) (i * vSumDivider); + } + + int srcOffset; + + // horizontal pass : extract the alpha mask from the source picture and + // blur it into the destination picture + for (int srcY = 0, dstOffset = left * dstWidth; srcY < srcHeight; srcY++) { + + // first pixels are empty + for (historyIdx = 0; historyIdx < shadowSize;) { + aHistory[historyIdx++] = 0; + } + + aSum = 0; + historyIdx = 0; + srcOffset = srcY * srcWidth; + + // compute the blur average with pixels from the source image + for (int srcX = 0; srcX < srcWidth; srcX++) { + + int a = hSumLookup[aSum]; + dstBuffer[dstOffset++] = a << 24; // store the alpha value only + // the shadow color will be added in the next pass + + aSum -= aHistory[historyIdx]; // substract the oldest pixel from the sum + + // extract the new pixel ... + a = srcBuffer[srcOffset + srcX] >>> 24; + aHistory[historyIdx] = a; // ... and store its value into history + aSum += a; // ... and add its value to the sum + + if (++historyIdx >= shadowSize) { + historyIdx -= shadowSize; + } + } + + // blur the end of the row - no new pixels to grab + for (int i = 0; i < shadowSize; i++) { + + int a = hSumLookup[aSum]; + dstBuffer[dstOffset++] = a << 24; + + // substract the oldest pixel from the sum ... and nothing new to add ! + aSum -= aHistory[historyIdx]; + + if (++historyIdx >= shadowSize) { + historyIdx -= shadowSize; + } + } + } + + // vertical pass + for (int x = 0, bufferOffset = 0; x < dstWidth; x++, bufferOffset = x) { + + aSum = 0; + + // first pixels are empty + for (historyIdx = 0; historyIdx < left;) { + aHistory[historyIdx++] = 0; + } + + // and then they come from the dstBuffer + for (int y = 0; y < right; y++, bufferOffset += dstWidth) { + int a = dstBuffer[bufferOffset] >>> 24; // extract alpha + aHistory[historyIdx++] = a; // store into history + aSum += a; // and add to sum + } + + bufferOffset = x; + historyIdx = 0; + + // compute the blur avera`ge with pixels from the previous pass + for (int y = 0; y < yStop; y++, bufferOffset += dstWidth) { + + int a = vSumLookup[aSum]; + dstBuffer[bufferOffset] = a << 24 | shadowRgb; // store alpha value + shadow color + + aSum -= aHistory[historyIdx]; // substract the oldest pixel from the sum + + a = dstBuffer[bufferOffset + lastPixelOffset] >>> 24; // extract the new pixel ... + aHistory[historyIdx] = a; // ... and store its value into history + aSum += a; // ... and add its value to the sum + + if (++historyIdx >= shadowSize) { + historyIdx -= shadowSize; + } + } + + // blur the end of the column - no pixels to grab anymore + for (int y = yStop; y < dstHeight; y++, bufferOffset += dstWidth) { + + int a = vSumLookup[aSum]; + dstBuffer[bufferOffset] = a << 24 | shadowRgb; + + aSum -= aHistory[historyIdx]; // substract the oldest pixel from the sum + + if (++historyIdx >= shadowSize) { + historyIdx -= shadowSize; + } + } + } + + GraphicsUtilities.setPixels(dst, 0, 0, dstWidth, dstHeight, dstBuffer); + return dst; + } +} |