aboutsummaryrefslogtreecommitdiff
path: root/dropShadow/ShadowRenderer.java
diff options
context:
space:
mode:
Diffstat (limited to 'dropShadow/ShadowRenderer.java')
-rw-r--r--dropShadow/ShadowRenderer.java185
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;
+ }
+}