From ba8175a4ab682d334aef0a2af11240ecc9e9be81 Mon Sep 17 00:00:00 2001 From: Ruben Brunk Date: Mon, 10 Dec 2012 18:50:10 -0800 Subject: Added sobel filter for edge function. Change-Id: I4d59a96585f4902cd01d26ff68c777b542041132 --- jni/Android.mk | 1 + jni/filters/edge.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 jni/filters/edge.c (limited to 'jni') diff --git a/jni/Android.mk b/jni/Android.mk index 8a2fc9e18..6f12b3ef4 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -29,6 +29,7 @@ LOCAL_SRC_FILES := filters/bw.c \ filters/gradient.c \ filters/saturated.c \ filters/exposure.c \ + filters/edge.c \ filters/contrast.c \ filters/hue.c \ filters/shadows.c \ diff --git a/jni/filters/edge.c b/jni/filters/edge.c new file mode 100644 index 000000000..9f5d88f77 --- /dev/null +++ b/jni/filters/edge.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2012 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. + */ + +#include +#include "filters.h" + +void JNIFUNCF(ImageFilterEdge, nativeApplyFilter, jobject bitmap, jint width, jint height, jfloat p) +{ + char* destination = 0; + AndroidBitmap_lockPixels(env, bitmap, (void**) &destination); + + // using contrast function: + // f(v) = exp(-alpha * v^beta) + // use beta ~ 1 + + float const alpha = 5.0f; + float const beta = p; + float const c_min = 100.0f; + float const c_max = 500.0f; + + // pixels must be 4 bytes + char * dst = destination; + + int j, k; + char * ptr = destination; + int row_stride = 4 * width; + + // set 2 row buffer (avoids bitmap copy) + int buf_len = 2 * row_stride; + char buf[buf_len]; + int buf_row_ring = 0; + + // set initial buffer to black + memset(buf, 0, buf_len * sizeof(char)); + for (j = 3; j < buf_len; j+=4) { + *(buf + j) = 255; // set initial alphas + } + + // apply sobel filter + for (j = 1; j < height - 1; j++) { + + for (k = 1; k < width - 1; k++){ + int loc = j * row_stride + k * 4; + + float bestx = 0.0f; + int l; + for (l = 0; l < 3; l++) { + float tmp = 0.0f; + tmp += *(ptr + (loc - row_stride + 4 + l)); + tmp += *(ptr + (loc + 4 + l)) * 2.0f; + tmp += *(ptr + (loc + row_stride + 4 + l)); + tmp -= *(ptr + (loc - row_stride - 4 + l)); + tmp -= *(ptr + (loc - 4 + l)) * 2.0f; + tmp -= *(ptr + (loc + row_stride - 4 + l)); + if (fabs(tmp) > fabs(bestx)) { + bestx = tmp; + } + } + + float besty = 0.0f; + for (l = 0; l < 3; l++) { + float tmp = 0.0f; + tmp -= *(ptr + (loc - row_stride - 4 + l)); + tmp -= *(ptr + (loc - row_stride + l)) * 2.0f; + tmp -= *(ptr + (loc - row_stride + 4 + l)); + tmp += *(ptr + (loc + row_stride - 4 + l)); + tmp += *(ptr + (loc + row_stride + l)) * 2.0f; + tmp += *(ptr + (loc + row_stride + 4 + l)); + if (fabs(tmp) > fabs(besty)) { + besty = tmp; + } + } + + // compute gradient magnitude + float mag = sqrt(bestx * bestx + besty * besty); + + // clamp + mag = MIN(MAX(c_min, mag), c_max); + + // scale to [0, 1] + mag = (mag - c_min) / (c_max - c_min); + + float ret = 1.0f - exp (- alpha * pow(mag, beta)); + ret = 255 * ret; + + int off = k * 4; + *(buf + buf_row_ring + off) = ret; + *(buf + buf_row_ring + off + 1) = ret; + *(buf + buf_row_ring + off + 2) = ret; + *(buf + buf_row_ring + off + 3) = *(ptr + loc + 3); + } + + buf_row_ring += row_stride; + buf_row_ring %= buf_len; + + if (j - 1 >= 0) { + memcpy((dst + row_stride * (j - 1)), (buf + buf_row_ring), row_stride * sizeof(char)); + } + + } + buf_row_ring += row_stride; + buf_row_ring %= buf_len; + int second_last_row = row_stride * (height - 2); + memcpy((dst + second_last_row), (buf + buf_row_ring), row_stride * sizeof(char)); + + // set last row to black + int last_row = row_stride * (height - 1); + memset((dst + last_row), 0, row_stride * sizeof(char)); + for (j = 3; j < row_stride; j+=4) { + *(dst + last_row + j) = 255; // set alphas + } + AndroidBitmap_unlockPixels(env, bitmap); +} -- cgit v1.2.3