• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cstring>
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   // Array of approximated CDF of normal distribution.
35   // 1024 Entries in total. The array is approximated by sigmoid function and
36   // the exact command in "octave" is:
37   // x = [2/1029:1/1029:1025/1029];
38   // y = (-1/11.5*log(1./x-0.9999)+0.5)*766*0.9+766*0.05;
39   const int kCDFEntries = 1024;
40   const uint32_t normal_cdf[] = {
41     9, 33, 50, 64, 75, 84, 92, 99, 106, 112, 117, 122, 126, 130, 134, 138, 142,
42     145, 148, 150, 154, 157, 159, 162, 164, 166, 169, 170, 173, 175, 177, 179,
43     180, 182, 184, 186, 188, 189, 190, 192, 194, 195, 197, 198, 199, 200, 202,
44     203, 205, 206, 207, 208, 209, 210, 212, 213, 214, 215, 216, 217, 218, 219,
45     220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 229, 230, 231, 232, 233,
46     234, 235, 236, 236, 237, 238, 239, 239, 240, 240, 242, 242, 243, 244, 245,
47     245, 246, 247, 247, 248, 249, 249, 250, 250, 251, 252, 253, 253, 254, 255,
48     255, 256, 256, 257, 258, 258, 259, 259, 259, 260, 261, 262, 262, 263, 263,
49     264, 264, 265, 265, 266, 267, 267, 268, 268, 269, 269, 269, 270, 270, 271,
50     272, 272, 273, 273, 274, 274, 275, 275, 276, 276, 277, 277, 277, 278, 278,
51     279, 279, 279, 280, 280, 281, 282, 282, 282, 283, 283, 284, 284, 285, 285,
52     285, 286, 286, 287, 287, 288, 288, 288, 289, 289, 289, 290, 290, 290, 291,
53     292, 292, 292, 293, 293, 294, 294, 294, 295, 295, 296, 296, 296, 297, 297,
54     297, 298, 298, 298, 299, 299, 299, 299, 300, 300, 301, 301, 302, 302, 302,
55     303, 303, 304, 304, 304, 305, 305, 305, 306, 306, 306, 307, 307, 307, 308,
56     308, 308, 309, 309, 309, 309, 310, 310, 310, 310, 311, 312, 312, 312, 313,
57     313, 313, 314, 314, 314, 315, 315, 315, 315, 316, 316, 316, 317, 317, 317,
58     318, 318, 318, 319, 319, 319, 319, 319, 320, 320, 320, 321, 321, 322, 322,
59     322, 323, 323, 323, 323, 324, 324, 324, 325, 325, 325, 325, 326, 326, 326,
60     327, 327, 327, 327, 328, 328, 328, 329, 329, 329, 329, 329, 330, 330, 330,
61     330, 331, 331, 332, 332, 332, 333, 333, 333, 333, 334, 334, 334, 334, 335,
62     335, 335, 336, 336, 336, 336, 337, 337, 337, 337, 338, 338, 338, 339, 339,
63     339, 339, 339, 339, 340, 340, 340, 340, 341, 341, 342, 342, 342, 342, 343,
64     343, 343, 344, 344, 344, 344, 345, 345, 345, 345, 346, 346, 346, 346, 347,
65     347, 347, 347, 348, 348, 348, 348, 349, 349, 349, 349, 349, 349, 350, 350,
66     350, 350, 351, 351, 352, 352, 352, 352, 353, 353, 353, 353, 354, 354, 354,
67     354, 355, 355, 355, 355, 356, 356, 356, 356, 357, 357, 357, 357, 358, 358,
68     358, 358, 359, 359, 359, 359, 359, 359, 359, 360, 360, 360, 360, 361, 361,
69     362, 362, 362, 362, 363, 363, 363, 363, 364, 364, 364, 364, 365, 365, 365,
70     365, 366, 366, 366, 366, 366, 367, 367, 367, 367, 368, 368, 368, 368, 369,
71     369, 369, 369, 369, 369, 370, 370, 370, 370, 370, 371, 371, 372, 372, 372,
72     372, 373, 373, 373, 373, 374, 374, 374, 374, 374, 375, 375, 375, 375, 376,
73     376, 376, 376, 377, 377, 377, 377, 378, 378, 378, 378, 378, 379, 379, 379,
74     379, 379, 379, 380, 380, 380, 380, 381, 381, 381, 382, 382, 382, 382, 383,
75     383, 383, 383, 384, 384, 384, 384, 385, 385, 385, 385, 385, 386, 386, 386,
76     386, 387, 387, 387, 387, 388, 388, 388, 388, 388, 389, 389, 389, 389, 389,
77     389, 390, 390, 390, 390, 391, 391, 392, 392, 392, 392, 392, 393, 393, 393,
78     393, 394, 394, 394, 394, 395, 395, 395, 395, 396, 396, 396, 396, 396, 397,
79     397, 397, 397, 398, 398, 398, 398, 399, 399, 399, 399, 399, 399, 400, 400,
80     400, 400, 400, 401, 401, 402, 402, 402, 402, 403, 403, 403, 403, 404, 404,
81     404, 404, 405, 405, 405, 405, 406, 406, 406, 406, 406, 407, 407, 407, 407,
82     408, 408, 408, 408, 409, 409, 409, 409, 409, 409, 410, 410, 410, 410, 411,
83     411, 412, 412, 412, 412, 413, 413, 413, 413, 414, 414, 414, 414, 415, 415,
84     415, 415, 416, 416, 416, 416, 417, 417, 417, 417, 418, 418, 418, 418, 419,
85     419, 419, 419, 419, 419, 420, 420, 420, 420, 421, 421, 422, 422, 422, 422,
86     423, 423, 423, 423, 424, 424, 424, 425, 425, 425, 425, 426, 426, 426, 426,
87     427, 427, 427, 427, 428, 428, 428, 429, 429, 429, 429, 429, 429, 430, 430,
88     430, 430, 431, 431, 432, 432, 432, 433, 433, 433, 433, 434, 434, 434, 435,
89     435, 435, 435, 436, 436, 436, 436, 437, 437, 437, 438, 438, 438, 438, 439,
90     439, 439, 439, 439, 440, 440, 440, 441, 441, 442, 442, 442, 443, 443, 443,
91     443, 444, 444, 444, 445, 445, 445, 446, 446, 446, 446, 447, 447, 447, 448,
92     448, 448, 449, 449, 449, 449, 449, 450, 450, 450, 451, 451, 452, 452, 452,
93     453, 453, 453, 454, 454, 454, 455, 455, 455, 456, 456, 456, 457, 457, 457,
94     458, 458, 458, 459, 459, 459, 459, 460, 460, 460, 461, 461, 462, 462, 462,
95     463, 463, 463, 464, 464, 465, 465, 465, 466, 466, 466, 467, 467, 467, 468,
96     468, 469, 469, 469, 469, 470, 470, 470, 471, 472, 472, 472, 473, 473, 474,
97     474, 474, 475, 475, 476, 476, 476, 477, 477, 478, 478, 478, 479, 479, 479,
98     480, 480, 480, 481, 482, 482, 483, 483, 484, 484, 484, 485, 485, 486, 486,
99     487, 487, 488, 488, 488, 489, 489, 489, 490, 490, 491, 492, 492, 493, 493,
100     494, 494, 495, 495, 496, 496, 497, 497, 498, 498, 499, 499, 499, 500, 501,
101     502, 502, 503, 503, 504, 504, 505, 505, 506, 507, 507, 508, 508, 509, 509,
102     510, 510, 511, 512, 513, 513, 514, 515, 515, 516, 517, 517, 518, 519, 519,
103     519, 520, 521, 522, 523, 524, 524, 525, 526, 526, 527, 528, 529, 529, 530,
104     531, 532, 533, 534, 535, 535, 536, 537, 538, 539, 539, 540, 542, 543, 544,
105     545, 546, 547, 548, 549, 549, 550, 552, 553, 554, 555, 556, 558, 559, 559,
106     561, 562, 564, 565, 566, 568, 569, 570, 572, 574, 575, 577, 578, 579, 582,
107     583, 585, 587, 589, 590, 593, 595, 597, 599, 602, 604, 607, 609, 612, 615,
108     618, 620, 624, 628, 631, 635, 639, 644, 649, 654, 659, 666, 673, 680, 690,
109     700, 714};
110 
Java_com_android_photoeditor_filters_ImageUtils_nativeHEQ(JNIEnv * env,jobject obj,jobject src_bitmap,jobject dst_bitmap,jfloat scale)111 extern "C" JNIEXPORT void JNICALL Java_com_android_photoeditor_filters_ImageUtils_nativeHEQ(
112     JNIEnv *env, jobject obj, jobject src_bitmap, jobject dst_bitmap, jfloat scale) {
113    pHEQType f = (pHEQType)JNIFunc[JNI_HEQ].func_ptr;
114    return f(env, obj, src_bitmap, dst_bitmap, scale);
115 }
116 
HEQ(JNIEnv * env,jobject obj,jobject src_bitmap,jobject dst_bitmap,jfloat scale)117 extern "C" void HEQ(
118     JNIEnv *env, jobject obj, jobject src_bitmap, jobject dst_bitmap, jfloat scale) {
119   AndroidBitmapInfo src_info;
120   AndroidBitmapInfo dst_info;
121   void* src_pixels;
122   void* dst_pixels;
123 
124   int ret = LockBitmaps(
125       env, src_bitmap, dst_bitmap, &src_info, &dst_info, &src_pixels, &dst_pixels);
126   if (ret < 0) {
127     LOGE("LockBitmaps in HEQ failed, error=%d", ret);
128     return;
129   }
130 
131   const int kEnergyLevels = 766;  // 255 * 3 + 1
132 
133   // The energy has the range of [0, kEnergyLevels]
134   int accumulated_histogram[kEnergyLevels];
135   memset(accumulated_histogram, 0, sizeof(accumulated_histogram));
136 
137   // Store all the energy in the dst_pixels
138   pixel32_t* dst = reinterpret_cast<pixel32_t*>(dst_pixels);
139   pixel32_t const* src = reinterpret_cast<pixel32_t const*>(src_pixels);
140   pixel32_t const* src_end = reinterpret_cast<pixel32_t const*>(
141       reinterpret_cast<char const*>(src) + src_info.stride * src_info.height);
142   while (src < src_end) {
143     dst->rgba32 = src->rgba8[0] + src->rgba8[1] + src->rgba8[2];
144     ++src;
145     ++dst;
146   }
147 
148   // Build up the accumulated histogram table by ignoring borders (1/20 = 5% width).
149   float border_thickness_ratio = 0.05;
150   int y_border_thickness = dst_info.height * border_thickness_ratio;
151   pixel32_t* dst_line = reinterpret_cast<pixel32_t*>(
152       reinterpret_cast<char*>(dst_pixels) + dst_info.stride * y_border_thickness);
153   pixel32_t* dst_line_end = reinterpret_cast<pixel32_t*>(
154       reinterpret_cast<char*>(dst_pixels) + dst_info.stride *
155       (dst_info.height - y_border_thickness));
156   int x_border_thickness = dst_info.width * border_thickness_ratio;
157   int x_border_end = dst_info.width - x_border_thickness;
158   while (dst_line < dst_line_end) {
159     pixel32_t* dp = dst_line + x_border_thickness;
160     pixel32_t* dp_end = dst_line + x_border_end;
161     while (dp < dp_end) {
162       ++accumulated_histogram[dp->rgba32];
163       ++dp;
164     }
165     dst_line = reinterpret_cast<pixel32_t*>(
166         reinterpret_cast<char*>(dst_line) + dst_info.stride);
167   }
168 
169   for (int i = 1; i < kEnergyLevels; i++) {
170     accumulated_histogram[i] += accumulated_histogram[i - 1];
171   }
172 
173   uint32_t const* src_line =
174       reinterpret_cast<uint32_t const*>(src_pixels);
175   dst_line = reinterpret_cast<pixel32_t*>(dst_pixels);
176   dst_line_end = reinterpret_cast<pixel32_t*>(reinterpret_cast<char*>(dst_line) +
177       dst_info.height * dst_info.stride);
178   // The whole process is done by apply the HEQ result with a mask.
179   // The mask is a curve segmented by the energy_middle which could be tuned
180   // based on each bitmap. For the lower part, the mask tries to make the change
181   // significant for greater energy. For the smaller part, the mask does the
182   // contrary. The two curve should be continuous on the energy_middle so the
183   // final result is more natural. In this implementation, what I defined is two
184   // curve based on the energy 'e', for the smaller part, e^2 is used. For the
185   // greater part, e^1.5 is used. That is, for pixel with energy 'e', the mask
186   // is obtained by:
187   // if e > energy_middle
188   //     (e - energy_middle)^1.5 / (765 - energy_middle)^1.5
189   // else
190   //     (e - energy_middle)^2 / (energy_middle)^2
191   const int kShiftBits = 10;
192   const int kShiftValue = (1 << kShiftBits);
193   const int scale_shifted = scale * kShiftValue;
194   const int normalization_scale_shifted = (1.0 - scale) * kShiftValue;
195   const int energy_middle = 382;  // 765 / 2 = 382.5
196   const int normalization_low = 7481;  // (765 - 382.5)^1.5
197   const int normalization_high = 146307;  // 382.5^2
198   int total_pixels = accumulated_histogram[kEnergyLevels - 1];
199   while (dst_line < dst_line_end) {
200     pixel32_t const* sp = reinterpret_cast<pixel32_t const*>(src_line);
201     pixel32_t* dp = dst_line;
202     pixel32_t* dp_end = dp + dst_info.width;
203     while (dp < dp_end) {
204       if (!dp->rgba32) {  // the energy is 0, no changes will be made.
205         dp->rgba32 = sp->rgba32;
206       } else {
207         uint32_t energy = dp->rgba32;
208         int mask_normalization;
209         int mask_value = energy - energy_middle;
210 
211         if (mask_value > 0) {
212           mask_value = mask_value * sqrt(mask_value);
213           mask_normalization = normalization_low;
214         } else {
215           mask_value *= mask_value;
216           mask_normalization = normalization_high;
217         }
218         mask_value = ((mask_value * scale_shifted) +
219             (mask_normalization * (normalization_scale_shifted))) >> kShiftBits;
220         // The final picture is masked by the original energy.
221         // Assumption: Lower energy can result in low-confidence information and
222         // higher energy indicates good confidence.
223         // Therefore, pixels with low and high confidence should not be changed
224         // greatly.
225         uint32_t dst_energy = normal_cdf[
226             kCDFEntries * accumulated_histogram[energy] / total_pixels];
227         dst_energy = (energy * mask_value + dst_energy * (mask_normalization - mask_value)) /
228             mask_normalization;
229 
230         // Ensure there is no RGB value will be greater than 255.
231         uint32_t max_energy = energy * 255 / MAX3(sp->rgba8[0], sp->rgba8[1], sp->rgba8[2]);
232         if (dst_energy > max_energy) {
233           dst_energy = max_energy;
234         }
235 
236         dst_energy = (dst_energy << kShiftBits) / energy;
237         uint32_t dst_red = (sp->rgba8[0] * dst_energy) >> kShiftBits;
238         uint32_t dst_green = (sp->rgba8[1] * dst_energy) >> kShiftBits;
239         uint32_t dst_blue = (sp->rgba8[2] * dst_energy) >> kShiftBits;
240         dp->rgba32 = (sp->rgba8[3] << 24) | (dst_blue << 16) | (dst_green << 8) | dst_red;
241       }
242       dp++;
243       sp++;
244     }
245     src_line = reinterpret_cast<uint32_t const*>(
246         reinterpret_cast<char const*>(src_line) + src_info.stride);
247     dst_line = reinterpret_cast<pixel32_t*>(
248         reinterpret_cast<char*>(dst_line) + dst_info.stride);
249   }
250 
251   UnlockBitmaps(env, src_bitmap, dst_bitmap);
252 }
253 
254 }  // namespace
255