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
22 #include "utils.h"
23 #include "_jni.h"
24
25 using android::apps::photoeditor::utils::LockBitmaps;
26 using android::apps::photoeditor::utils::pixel32_t;
27 using android::apps::photoeditor::utils::UnlockBitmaps;
28
29 namespace {
30
Java_com_android_photoeditor_filters_ImageUtils_nativeBacklight(JNIEnv * env,jobject obj,jobject src_bitmap,jobject dst_bitmap,jfloat backlight)31 extern "C" JNIEXPORT void JNICALL Java_com_android_photoeditor_filters_ImageUtils_nativeBacklight(
32 JNIEnv *env, jobject obj, jobject src_bitmap, jobject dst_bitmap, jfloat backlight) {
33 pBacklightType f = (pBacklightType)JNIFunc[JNI_Backlight].func_ptr;
34 return f(env, obj, src_bitmap, dst_bitmap, backlight);
35 }
36
Backlight(JNIEnv * env,jobject obj,jobject src_bitmap,jobject dst_bitmap,jfloat backlight)37 extern "C" void Backlight(JNIEnv *env, jobject obj, jobject src_bitmap, jobject dst_bitmap, jfloat backlight) {
38 AndroidBitmapInfo src_info;
39 AndroidBitmapInfo dst_info;
40 void* src_pixels;
41 void* dst_pixels;
42
43 int ret = LockBitmaps(
44 env, src_bitmap, dst_bitmap, &src_info, &dst_info, &src_pixels, &dst_pixels);
45 if (ret < 0) {
46 LOGE("LockBitmaps in Backlight failed, error=%d", ret);
47 return;
48 }
49
50 const float fade_gamma = 0.3f;
51 const float amt = 1.0f - backlight;
52 const float mult = 1.0f / (amt * 0.7f + 0.3f);
53 const float faded = fade_gamma + (1.0f - fade_gamma) * mult;
54 const float igamma = 1.0f / faded;
55
56 int lookup[256];
57 for (int i = 0; i < 256; i++) {
58 float value = static_cast<float>(pow(mult * i / 255.0f, igamma));
59 if (value > 256.0f) {
60 value = 256.0f;
61 }
62 lookup[i] = floor(255.0f * value) - i;
63 }
64
65 for (uint32_t scan_line = 0; scan_line < dst_info.height; scan_line++) {
66 uint32_t* dst = reinterpret_cast<uint32_t*>(dst_pixels);
67 pixel32_t* src = reinterpret_cast<pixel32_t*>(src_pixels);
68 pixel32_t* src_line_end = src + src_info.width;
69 while (src < src_line_end) {
70 int32_t src_red = src->rgba8[0];
71 int32_t src_green = src->rgba8[1];
72 int32_t src_blue = src->rgba8[2];
73 int32_t src_alpha = src->rgba8[3];
74
75 int32_t lightmask = (src_red + src_green * 2 + src_blue) >> 2;
76 int32_t backmask = 256 * (255 - lightmask);
77
78 int32_t diff_red = lookup[src_red] * backmask;
79 int32_t diff_green = lookup[src_green] * backmask;
80 int32_t diff_blue = lookup[src_blue] * backmask;
81
82 int32_t dst_red = src_red + (diff_red >> 16);
83 int32_t dst_green = src_green + (diff_green >> 16);
84 int32_t dst_blue = src_blue + (diff_blue >> 16);
85
86 if (dst_red > 255) {
87 dst_red = 255;
88 }
89 if (dst_green > 255) {
90 dst_green = 255;
91 }
92 if (dst_blue > 255) {
93 dst_blue = 255;
94 }
95
96 *dst = (src_alpha << 24) | (dst_blue << 16) | (dst_green << 8) | dst_red;
97 dst++;
98 src++;
99 }
100 dst_pixels = reinterpret_cast<char*>(dst_pixels) + dst_info.stride;
101 src_pixels = reinterpret_cast<char*>(src_pixels) + src_info.stride;
102 }
103
104 UnlockBitmaps(env, src_bitmap, dst_bitmap);
105 }
106
107 } // namespace
108