Home | History | Annotate | Download | only in filters
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <math.h>
     18 #include "filters.h"
     19 
     20 void JNIFUNCF(ImageFilterEdge, nativeApplyFilter, jobject bitmap, jint width, jint height, jfloat p)
     21 {
     22     char* destination = 0;
     23     AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
     24 
     25     // using contrast function:
     26     // f(v) = exp(-alpha * v^beta)
     27     // use beta ~ 1
     28 
     29     float const alpha = 5.0f;
     30     float const beta = p;
     31     float const c_min = 100.0f;
     32     float const c_max = 500.0f;
     33 
     34     // pixels must be 4 bytes
     35     char * dst = destination;
     36 
     37     int j, k;
     38     char * ptr = destination;
     39     int row_stride = 4 * width;
     40 
     41     // set 2 row buffer (avoids bitmap copy)
     42     int buf_len = 2 * row_stride;
     43     char buf[buf_len];
     44     int buf_row_ring = 0;
     45 
     46     // set initial buffer to black
     47     memset(buf, 0, buf_len * sizeof(char));
     48     for (j = 3; j < buf_len; j+=4) {
     49         *(buf + j) = 255;  // set initial alphas
     50     }
     51 
     52     // apply sobel filter
     53     for (j = 1; j < height - 1; j++) {
     54 
     55         for (k = 1; k < width - 1; k++){
     56             int loc = j * row_stride + k * 4;
     57 
     58             float bestx = 0.0f;
     59             int l;
     60             for (l = 0; l < 3; l++) {
     61                 float tmp = 0.0f;
     62                 tmp += *(ptr + (loc - row_stride + 4 + l));
     63                 tmp += *(ptr + (loc + 4 + l)) * 2.0f;
     64                 tmp += *(ptr + (loc + row_stride + 4 + l));
     65                 tmp -= *(ptr + (loc - row_stride - 4 + l));
     66                 tmp -= *(ptr + (loc - 4 + l)) * 2.0f;
     67                 tmp -= *(ptr + (loc + row_stride - 4 + l));
     68                 if (fabs(tmp) > fabs(bestx)) {
     69                     bestx = tmp;
     70                 }
     71             }
     72 
     73             float besty = 0.0f;
     74             for (l = 0; l < 3; l++) {
     75                 float tmp = 0.0f;
     76                 tmp -= *(ptr + (loc - row_stride - 4 + l));
     77                 tmp -= *(ptr + (loc - row_stride + l)) * 2.0f;
     78                 tmp -= *(ptr + (loc - row_stride + 4 + l));
     79                 tmp += *(ptr + (loc + row_stride - 4 + l));
     80                 tmp += *(ptr + (loc + row_stride + l)) * 2.0f;
     81                 tmp += *(ptr + (loc + row_stride + 4 + l));
     82                 if (fabs(tmp) > fabs(besty)) {
     83                     besty = tmp;
     84                 }
     85             }
     86 
     87             // compute gradient magnitude
     88             float mag = sqrt(bestx * bestx + besty * besty);
     89 
     90             // clamp
     91             mag = MIN(MAX(c_min, mag), c_max);
     92 
     93             // scale to [0, 1]
     94             mag = (mag - c_min) / (c_max - c_min);
     95 
     96             float ret = 1.0f - exp (- alpha * pow(mag, beta));
     97             ret = 255 * ret;
     98 
     99             int off = k * 4;
    100             *(buf + buf_row_ring + off) = ret;
    101             *(buf + buf_row_ring + off + 1) = ret;
    102             *(buf + buf_row_ring + off + 2) = ret;
    103             *(buf + buf_row_ring + off + 3) = *(ptr + loc + 3);
    104         }
    105 
    106         buf_row_ring += row_stride;
    107         buf_row_ring %= buf_len;
    108 
    109         if (j - 1 >= 0) {
    110             memcpy((dst + row_stride * (j - 1)), (buf + buf_row_ring), row_stride * sizeof(char));
    111         }
    112 
    113     }
    114     buf_row_ring += row_stride;
    115     buf_row_ring %= buf_len;
    116     int second_last_row = row_stride * (height - 2);
    117     memcpy((dst + second_last_row), (buf + buf_row_ring), row_stride * sizeof(char));
    118 
    119     // set last row to black
    120     int last_row = row_stride * (height - 1);
    121     memset((dst + last_row), 0, row_stride * sizeof(char));
    122     for (j = 3; j < row_stride; j+=4) {
    123         *(dst + last_row + j) = 255;  // set alphas
    124     }
    125     AndroidBitmap_unlockPixels(env, bitmap);
    126 }
    127