summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/ui/BoxBlurFilter.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/ui/BoxBlurFilter.java')
-rw-r--r--src/com/android/gallery3d/ui/BoxBlurFilter.java100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/ui/BoxBlurFilter.java b/src/com/android/gallery3d/ui/BoxBlurFilter.java
new file mode 100644
index 000000000..0497a61fa
--- /dev/null
+++ b/src/com/android/gallery3d/ui/BoxBlurFilter.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.ui;
+
+import android.graphics.Bitmap;
+
+
+public class BoxBlurFilter {
+ private static final int RED_MASK = 0xff0000;
+ private static final int RED_MASK_SHIFT = 16;
+ private static final int GREEN_MASK = 0x00ff00;
+ private static final int GREEN_MASK_SHIFT = 8;
+ private static final int BLUE_MASK = 0x0000ff;
+ private static final int RADIUS = 4;
+ private static final int KERNEL_SIZE = RADIUS * 2 + 1;
+ private static final int NUM_COLORS = 256;
+ private static final int[] KERNEL_NORM = new int[KERNEL_SIZE * NUM_COLORS];
+
+ public static final int MODE_REPEAT = 1;
+ public static final int MODE_CLAMP = 2;
+
+ static {
+ int index = 0;
+ // Build a lookup table from summed to normalized kernel values.
+ // The formula: KERNAL_NORM[value] = value / KERNEL_SIZE
+ for (int i = 0; i < NUM_COLORS; ++i) {
+ for (int j = 0; j < KERNEL_SIZE; ++j) {
+ KERNEL_NORM[index++] = i;
+ }
+ }
+ }
+
+ private BoxBlurFilter() {
+ }
+
+ private static int sample(int x, int width, int mode) {
+ if (x >= 0 && x < width) return x;
+ return mode == MODE_REPEAT
+ ? x < 0 ? x + width : x - width
+ : x < 0 ? 0 : width - 1;
+ }
+
+ public static void apply(
+ Bitmap bitmap, int horizontalMode, int verticalMode) {
+
+ int width = bitmap.getWidth();
+ int height = bitmap.getHeight();
+ int data[] = new int[width * height];
+ bitmap.getPixels(data, 0, width, 0, 0, width, height);
+ int temp[] = new int[width * height];
+ applyOneDimension(data, temp, width, height, horizontalMode);
+ applyOneDimension(temp, data, height, width, verticalMode);
+ bitmap.setPixels(data, 0, width, 0, 0, width, height);
+ }
+
+ private static void applyOneDimension(
+ int[] in, int[] out, int width, int height, int mode) {
+ for (int y = 0, read = 0; y < height; ++y, read += width) {
+ // Evaluate the kernel for the first pixel in the row.
+ int red = 0;
+ int green = 0;
+ int blue = 0;
+ for (int i = -RADIUS; i <= RADIUS; ++i) {
+ int argb = in[read + sample(i, width, mode)];
+ red += (argb & RED_MASK) >> RED_MASK_SHIFT;
+ green += (argb & GREEN_MASK) >> GREEN_MASK_SHIFT;
+ blue += argb & BLUE_MASK;
+ }
+ for (int x = 0, write = y; x < width; ++x, write += height) {
+ // Output the current pixel.
+ out[write] = 0xFF000000
+ | (KERNEL_NORM[red] << RED_MASK_SHIFT)
+ | (KERNEL_NORM[green] << GREEN_MASK_SHIFT)
+ | KERNEL_NORM[blue];
+
+ // Slide to the next pixel, adding the new rightmost pixel and
+ // subtracting the former leftmost.
+ int prev = in[read + sample(x - RADIUS, width, mode)];
+ int next = in[read + sample(x + RADIUS + 1, width, mode)];
+ red += ((next & RED_MASK) - (prev & RED_MASK)) >> RED_MASK_SHIFT;
+ green += ((next & GREEN_MASK) - (prev & GREEN_MASK)) >> GREEN_MASK_SHIFT;
+ blue += (next & BLUE_MASK) - (prev & BLUE_MASK);
+ }
+ }
+ }
+}