1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.ui; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class BoxBlurFilter { 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int RED_MASK = 0xff0000; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int RED_MASK_SHIFT = 16; 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int GREEN_MASK = 0x00ff00; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int GREEN_MASK_SHIFT = 8; 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int BLUE_MASK = 0x0000ff; 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int RADIUS = 4; 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int KERNEL_SIZE = RADIUS * 2 + 1; 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int NUM_COLORS = 256; 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int[] KERNEL_NORM = new int[KERNEL_SIZE * NUM_COLORS]; 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int MODE_REPEAT = 1; 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int MODE_CLAMP = 2; 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin static { 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int index = 0; 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Build a lookup table from summed to normalized kernel values. 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The formula: KERNAL_NORM[value] = value / KERNEL_SIZE 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0; i < NUM_COLORS; ++i) { 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int j = 0; j < KERNEL_SIZE; ++j) { 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin KERNEL_NORM[index++] = i; 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private BoxBlurFilter() { 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static int sample(int x, int width, int mode) { 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (x >= 0 && x < width) return x; 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mode == MODE_REPEAT 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ? x < 0 ? x + width : x - width 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin : x < 0 ? 0 : width - 1; 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static void apply( 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Bitmap bitmap, int horizontalMode, int verticalMode) { 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int width = bitmap.getWidth(); 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int height = bitmap.getHeight(); 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int data[] = new int[width * height]; 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin bitmap.getPixels(data, 0, width, 0, 0, width, height); 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int temp[] = new int[width * height]; 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin applyOneDimension(data, temp, width, height, horizontalMode); 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin applyOneDimension(temp, data, height, width, verticalMode); 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin bitmap.setPixels(data, 0, width, 0, 0, width, height); 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static void applyOneDimension( 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int[] in, int[] out, int width, int height, int mode) { 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int y = 0, read = 0; y < height; ++y, read += width) { 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Evaluate the kernel for the first pixel in the row. 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int red = 0; 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int green = 0; 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int blue = 0; 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = -RADIUS; i <= RADIUS; ++i) { 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int argb = in[read + sample(i, width, mode)]; 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin red += (argb & RED_MASK) >> RED_MASK_SHIFT; 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin green += (argb & GREEN_MASK) >> GREEN_MASK_SHIFT; 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin blue += argb & BLUE_MASK; 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int x = 0, write = y; x < width; ++x, write += height) { 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Output the current pixel. 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin out[write] = 0xFF000000 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin | (KERNEL_NORM[red] << RED_MASK_SHIFT) 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin | (KERNEL_NORM[green] << GREEN_MASK_SHIFT) 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin | KERNEL_NORM[blue]; 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Slide to the next pixel, adding the new rightmost pixel and 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // subtracting the former leftmost. 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int prev = in[read + sample(x - RADIUS, width, mode)]; 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int next = in[read + sample(x + RADIUS + 1, width, mode)]; 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin red += ((next & RED_MASK) - (prev & RED_MASK)) >> RED_MASK_SHIFT; 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin green += ((next & GREEN_MASK) - (prev & GREEN_MASK)) >> GREEN_MASK_SHIFT; 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin blue += (next & BLUE_MASK) - (prev & BLUE_MASK); 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 101