Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2010 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 <android/bitmap.h>
     18 #include <jni.h>
     19 
     20 #include <cmath>
     21 #include <cstdlib>
     22 #include <ctime>
     23 
     24 #include "utils.h"
     25 #include "_jni.h"
     26 
     27 using android::apps::photoeditor::utils::clamp;
     28 using android::apps::photoeditor::utils::LockBitmaps;
     29 using android::apps::photoeditor::utils::pixel32_t;
     30 using android::apps::photoeditor::utils::UnlockBitmaps;
     31 
     32 namespace {
     33 
     34 const int k256Multiply255 = 65280;
     35 
     36 void WhiteblackXF(float white, float black, int xform[]) {
     37   float scale = (black != white) ? 1.0f / (white - black) : 2000.0f;
     38   float offset = k256Multiply255 * black;
     39   for (int i = 0; i < 256; i++) {
     40     float vgamma = (256.0f * i - offset) * scale;
     41     xform[i] = clamp(floor(vgamma), 0, k256Multiply255);
     42   }
     43   xform[256] = xform[255];
     44 }
     45 
     46 extern "C" JNIEXPORT void JNICALL Java_com_android_photoeditor_filters_ImageUtils_nativeWhiteBlack(
     47     JNIEnv *env, jobject obj, jobject src_bitmap, jobject dst_bitmap, jfloat white, jfloat black) {
     48    pWhiteBlackType f = (pWhiteBlackType)JNIFunc[JNI_WhiteBlack].func_ptr;
     49    return f(env, obj, src_bitmap, dst_bitmap, white, black);
     50 }
     51 
     52 extern "C" void WhiteBlack(
     53     JNIEnv *env, jobject obj, jobject src_bitmap, jobject dst_bitmap, jfloat white, jfloat black) {
     54   AndroidBitmapInfo src_info;
     55   AndroidBitmapInfo dst_info;
     56   void* src_pixels;
     57   void* dst_pixels;
     58 
     59   int ret = LockBitmaps(
     60       env, src_bitmap, dst_bitmap, &src_info, &dst_info, &src_pixels, &dst_pixels);
     61   if (ret < 0) {
     62     LOGE("LockBitmaps in WhiteBlack failed, error=%d", ret);
     63     return;
     64   }
     65 
     66   srandom(time(NULL));
     67 
     68   int xform[257];
     69   WhiteblackXF(white, black, xform);
     70 
     71   for (uint32_t scan_line = 0; scan_line < src_info.height; scan_line++) {
     72     pixel32_t* src = reinterpret_cast<pixel32_t*>(src_pixels);
     73     uint32_t* dst = reinterpret_cast<uint32_t*>(dst_pixels);
     74     pixel32_t* src_line_end = src + src_info.width;
     75     while (src < src_line_end) {
     76       int32_t red = src->rgba8[0];
     77       int32_t green = src->rgba8[1];
     78       int32_t blue = src->rgba8[2];
     79       int32_t alpha = src->rgba8[3];
     80 
     81       int32_t xform_red = xform[red];
     82       int32_t xform_green = xform[green];
     83       int32_t xform_blue = xform[blue];
     84 
     85       red = xform[red + 1] - xform_red;
     86       green = xform[green + 1] - xform_green;
     87       blue = xform[blue + 1] - xform_blue;
     88 
     89       int32_t dither = random() % 256;
     90       int32_t diff_red = red * dither >> 8;
     91       int32_t diff_green = green * dither >> 8;
     92       int32_t diff_blue = blue * dither >> 8;
     93 
     94       red = (xform_red + diff_red - (red >> 1)) >> 8;
     95       green = (xform_green + diff_green - (green >> 1)) >> 8;
     96       blue = (xform_blue + diff_blue - (blue >> 1)) >> 8;
     97 
     98       red = clamp(red, 0, 255);
     99       green = clamp(green, 0, 255);
    100       blue = clamp(blue, 0, 255);
    101 
    102       *dst = (alpha << 24) | (blue << 16) | (green << 8) | red;
    103       src++;
    104       dst++;
    105     }
    106     src_pixels = reinterpret_cast<char*>(src_pixels) + src_info.stride;
    107     dst_pixels = reinterpret_cast<char*>(dst_pixels) + dst_info.stride;
    108   }
    109 
    110   UnlockBitmaps(env, src_bitmap, dst_bitmap);
    111 }
    112 
    113 }  // namespace
    114