165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/*
265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project
365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License");
565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License.
665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at
765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *      http://www.apache.org/licenses/LICENSE-2.0
965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software
1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS,
1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and
1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License.
1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpackage android.filterpacks.imageproc;
1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.Filter;
2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.FilterContext;
2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.Frame;
2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.FrameFormat;
2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.GenerateFieldPort;
2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.NativeProgram;
2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.Program;
2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.ShaderProgram;
2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.format.ImageFormat;
2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.util.Log;
3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic class AutoFixFilter extends Filter {
3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @GenerateFieldPort(name = "tile_size", hasDefault = true)
3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private int mTileSize = 640;
3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @GenerateFieldPort(name = "scale")
3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private float mScale;
3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private static final int normal_cdf[] = {
4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        9, 33, 50, 64, 75, 84, 92, 99, 106, 112, 117, 122, 126, 130, 134, 138, 142,
4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        145, 148, 150, 154, 157, 159, 162, 164, 166, 169, 170, 173, 175, 177, 179,
4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        180, 182, 184, 186, 188, 189, 190, 192, 194, 195, 197, 198, 199, 200, 202,
4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        203, 205, 206, 207, 208, 209, 210, 212, 213, 214, 215, 216, 217, 218, 219,
4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 229, 230, 231, 232, 233,
4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        234, 235, 236, 236, 237, 238, 239, 239, 240, 240, 242, 242, 243, 244, 245,
4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        245, 246, 247, 247, 248, 249, 249, 250, 250, 251, 252, 253, 253, 254, 255,
4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        255, 256, 256, 257, 258, 258, 259, 259, 259, 260, 261, 262, 262, 263, 263,
4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        264, 264, 265, 265, 266, 267, 267, 268, 268, 269, 269, 269, 270, 270, 271,
4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        272, 272, 273, 273, 274, 274, 275, 275, 276, 276, 277, 277, 277, 278, 278,
5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        279, 279, 279, 280, 280, 281, 282, 282, 282, 283, 283, 284, 284, 285, 285,
5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        285, 286, 286, 287, 287, 288, 288, 288, 289, 289, 289, 290, 290, 290, 291,
5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        292, 292, 292, 293, 293, 294, 294, 294, 295, 295, 296, 296, 296, 297, 297,
5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        297, 298, 298, 298, 299, 299, 299, 299, 300, 300, 301, 301, 302, 302, 302,
5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        303, 303, 304, 304, 304, 305, 305, 305, 306, 306, 306, 307, 307, 307, 308,
5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        308, 308, 309, 309, 309, 309, 310, 310, 310, 310, 311, 312, 312, 312, 313,
5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        313, 313, 314, 314, 314, 315, 315, 315, 315, 316, 316, 316, 317, 317, 317,
5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        318, 318, 318, 319, 319, 319, 319, 319, 320, 320, 320, 321, 321, 322, 322,
5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        322, 323, 323, 323, 323, 324, 324, 324, 325, 325, 325, 325, 326, 326, 326,
5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        327, 327, 327, 327, 328, 328, 328, 329, 329, 329, 329, 329, 330, 330, 330,
6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        330, 331, 331, 332, 332, 332, 333, 333, 333, 333, 334, 334, 334, 334, 335,
6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        335, 335, 336, 336, 336, 336, 337, 337, 337, 337, 338, 338, 338, 339, 339,
6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        339, 339, 339, 339, 340, 340, 340, 340, 341, 341, 342, 342, 342, 342, 343,
6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        343, 343, 344, 344, 344, 344, 345, 345, 345, 345, 346, 346, 346, 346, 347,
6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        347, 347, 347, 348, 348, 348, 348, 349, 349, 349, 349, 349, 349, 350, 350,
6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        350, 350, 351, 351, 352, 352, 352, 352, 353, 353, 353, 353, 354, 354, 354,
6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        354, 355, 355, 355, 355, 356, 356, 356, 356, 357, 357, 357, 357, 358, 358,
6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        358, 358, 359, 359, 359, 359, 359, 359, 359, 360, 360, 360, 360, 361, 361,
6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        362, 362, 362, 362, 363, 363, 363, 363, 364, 364, 364, 364, 365, 365, 365,
6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        365, 366, 366, 366, 366, 366, 367, 367, 367, 367, 368, 368, 368, 368, 369,
7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        369, 369, 369, 369, 369, 370, 370, 370, 370, 370, 371, 371, 372, 372, 372,
7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        372, 373, 373, 373, 373, 374, 374, 374, 374, 374, 375, 375, 375, 375, 376,
7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        376, 376, 376, 377, 377, 377, 377, 378, 378, 378, 378, 378, 379, 379, 379,
7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        379, 379, 379, 380, 380, 380, 380, 381, 381, 381, 382, 382, 382, 382, 383,
7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        383, 383, 383, 384, 384, 384, 384, 385, 385, 385, 385, 385, 386, 386, 386,
7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        386, 387, 387, 387, 387, 388, 388, 388, 388, 388, 389, 389, 389, 389, 389,
7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        389, 390, 390, 390, 390, 391, 391, 392, 392, 392, 392, 392, 393, 393, 393,
7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        393, 394, 394, 394, 394, 395, 395, 395, 395, 396, 396, 396, 396, 396, 397,
7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        397, 397, 397, 398, 398, 398, 398, 399, 399, 399, 399, 399, 399, 400, 400,
7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        400, 400, 400, 401, 401, 402, 402, 402, 402, 403, 403, 403, 403, 404, 404,
8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        404, 404, 405, 405, 405, 405, 406, 406, 406, 406, 406, 407, 407, 407, 407,
8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        408, 408, 408, 408, 409, 409, 409, 409, 409, 409, 410, 410, 410, 410, 411,
8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        411, 412, 412, 412, 412, 413, 413, 413, 413, 414, 414, 414, 414, 415, 415,
8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        415, 415, 416, 416, 416, 416, 417, 417, 417, 417, 418, 418, 418, 418, 419,
8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        419, 419, 419, 419, 419, 420, 420, 420, 420, 421, 421, 422, 422, 422, 422,
8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        423, 423, 423, 423, 424, 424, 424, 425, 425, 425, 425, 426, 426, 426, 426,
8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        427, 427, 427, 427, 428, 428, 428, 429, 429, 429, 429, 429, 429, 430, 430,
8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        430, 430, 431, 431, 432, 432, 432, 433, 433, 433, 433, 434, 434, 434, 435,
8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        435, 435, 435, 436, 436, 436, 436, 437, 437, 437, 438, 438, 438, 438, 439,
8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        439, 439, 439, 439, 440, 440, 440, 441, 441, 442, 442, 442, 443, 443, 443,
9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        443, 444, 444, 444, 445, 445, 445, 446, 446, 446, 446, 447, 447, 447, 448,
9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        448, 448, 449, 449, 449, 449, 449, 450, 450, 450, 451, 451, 452, 452, 452,
9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        453, 453, 453, 454, 454, 454, 455, 455, 455, 456, 456, 456, 457, 457, 457,
9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        458, 458, 458, 459, 459, 459, 459, 460, 460, 460, 461, 461, 462, 462, 462,
9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        463, 463, 463, 464, 464, 465, 465, 465, 466, 466, 466, 467, 467, 467, 468,
9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        468, 469, 469, 469, 469, 470, 470, 470, 471, 472, 472, 472, 473, 473, 474,
9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        474, 474, 475, 475, 476, 476, 476, 477, 477, 478, 478, 478, 479, 479, 479,
9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        480, 480, 480, 481, 482, 482, 483, 483, 484, 484, 484, 485, 485, 486, 486,
9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        487, 487, 488, 488, 488, 489, 489, 489, 490, 490, 491, 492, 492, 493, 493,
9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        494, 494, 495, 495, 496, 496, 497, 497, 498, 498, 499, 499, 499, 500, 501,
10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        502, 502, 503, 503, 504, 504, 505, 505, 506, 507, 507, 508, 508, 509, 509,
10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        510, 510, 511, 512, 513, 513, 514, 515, 515, 516, 517, 517, 518, 519, 519,
10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        519, 520, 521, 522, 523, 524, 524, 525, 526, 526, 527, 528, 529, 529, 530,
10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        531, 532, 533, 534, 535, 535, 536, 537, 538, 539, 539, 540, 542, 543, 544,
10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        545, 546, 547, 548, 549, 549, 550, 552, 553, 554, 555, 556, 558, 559, 559,
10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        561, 562, 564, 565, 566, 568, 569, 570, 572, 574, 575, 577, 578, 579, 582,
10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        583, 585, 587, 589, 590, 593, 595, 597, 599, 602, 604, 607, 609, 612, 615,
10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        618, 620, 624, 628, 631, 635, 639, 644, 649, 654, 659, 666, 673, 680, 690,
10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        700, 714 };
10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private final String mAutoFixShader =
11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "precision mediump float;\n" +
11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "uniform sampler2D tex_sampler_0;\n" +
11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "uniform sampler2D tex_sampler_1;\n" +
11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "uniform sampler2D tex_sampler_2;\n" +
11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "uniform float scale;\n" +
11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "uniform float shift_scale;\n" +
11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "uniform float hist_offset;\n" +
11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "uniform float hist_scale;\n" +
11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "uniform float density_offset;\n" +
12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "uniform float density_scale;\n" +
12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "varying vec2 v_texcoord;\n" +
12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "void main() {\n" +
12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  const vec3 weights = vec3(0.33333, 0.33333, 0.33333);\n" +
12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  vec4 color = texture2D(tex_sampler_0, v_texcoord);\n" +
12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  float energy = dot(color.rgb, weights);\n" +
12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  float mask_value = energy - 0.5;\n" +
12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  float alpha;\n" +
12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  if (mask_value > 0.0) {\n" +
12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "    alpha = (pow(2.0 * mask_value, 1.5) - 1.0) * scale + 1.0;\n" +
13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  } else { \n" +
13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "    alpha = (pow(2.0 * mask_value, 2.0) - 1.0) * scale + 1.0;\n" +
13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  }\n" +
13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  float index = energy * hist_scale + hist_offset;\n" +
13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  vec4 temp = texture2D(tex_sampler_1, vec2(index, 0.5));\n" +
13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  float value = temp.g + temp.r * shift_scale;\n" +
13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  index = value * density_scale + density_offset;\n" +
13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  temp = texture2D(tex_sampler_2, vec2(index, 0.5));\n" +
13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  value = temp.g + temp.r * shift_scale;\n" +
13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  float dst_energy = energy * alpha + value * (1.0 - alpha);\n" +
14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  float max_energy = energy / max(color.r, max(color.g, color.b));\n" +
14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  if (dst_energy > max_energy) {\n" +
14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "    dst_energy = max_energy;\n" +
14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  }\n" +
14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  if (energy == 0.0) {\n" +
14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "    gl_FragColor = color;\n" +
14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  } else {\n" +
14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "    gl_FragColor = vec4(color.rgb * dst_energy / energy, color.a);\n" +
14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "  }\n" +
14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            "}\n";
15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private Program mShaderProgram;
15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private Program mNativeProgram;
15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private int mWidth = 0;
15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private int mHeight = 0;
15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private int mTarget = FrameFormat.TARGET_UNSPECIFIED;
15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private Frame mHistFrame;
15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private Frame mDensityFrame;
16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public AutoFixFilter(String name) {
16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        super(name);
16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setupPorts() {
16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        addMaskedInputPort("image", ImageFormat.create(ImageFormat.COLORSPACE_RGBA));
16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        addOutputBasedOnInput("image", "image");
16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public FrameFormat getOutputFormat(String portName, FrameFormat inputFormat) {
17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return inputFormat;
17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void initProgram(FilterContext context, int target) {
17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        switch (target) {
17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            case FrameFormat.TARGET_GPU:
17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                ShaderProgram shaderProgram = new ShaderProgram(context, mAutoFixShader);
18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                shaderProgram.setMaximumTileSize(mTileSize);
18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                mShaderProgram = shaderProgram;
18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                break;
18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            default:
18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                throw new RuntimeException("Filter Sharpen does not support frames of " +
18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    "target " + target + "!");
18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mTarget = target;
18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private void initParameters() {
19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mShaderProgram.setHostValue("shift_scale", 1.0f / 256f);
19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mShaderProgram.setHostValue("hist_offset", 0.5f / 766f);
19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mShaderProgram.setHostValue("hist_scale", 765f / 766f);
19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mShaderProgram.setHostValue("density_offset", 0.5f / 1024f);
19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mShaderProgram.setHostValue("density_scale", 1023f / 1024f);
19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mShaderProgram.setHostValue("scale", mScale);
19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    protected void prepare(FilterContext context) {
20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        int densityDim = 1024;
20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        int histDim = 255 * 3 + 1;
20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        long precision = (256l * 256l - 1l);
20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        int[] densityTable = new int[densityDim];
20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        for (int i = 0; i < densityDim; ++i) {
20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            long temp = normal_cdf[i] * precision / histDim;
20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            densityTable[i] = (int) temp;
21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        FrameFormat densityFormat = ImageFormat.create(densityDim, 1,
21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                       ImageFormat.COLORSPACE_RGBA,
21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                       FrameFormat.TARGET_GPU);
21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mDensityFrame = context.getFrameManager().newFrame(densityFormat);
21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mDensityFrame.setInts(densityTable);
21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void tearDown(FilterContext context) {
22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mDensityFrame != null) {
22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mDensityFrame.release();
22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mDensityFrame = null;
22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mHistFrame != null) {
22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mHistFrame.release();
22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mHistFrame = null;
22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void fieldPortValueUpdated(String name, FilterContext context) {
23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mShaderProgram != null) {
23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mShaderProgram.setHostValue("scale", mScale);
23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
24065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void process(FilterContext context) {
24165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Get input frame
24265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        Frame input = pullInput("image");
24365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        FrameFormat inputFormat = input.getFormat();
24465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Create program if not created already
24665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mShaderProgram == null || inputFormat.getTarget() != mTarget) {
24765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            initProgram(context, inputFormat.getTarget());
24865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            initParameters();
24965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
25065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Check if the frame size has changed
25265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (inputFormat.getWidth() != mWidth || inputFormat.getHeight() != mHeight) {
25365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mWidth = inputFormat.getWidth();
25465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mHeight = inputFormat.getHeight();
25565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            createHistogramFrame(context, mWidth, mHeight, input.getInts());
25665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
25765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Create output frame
25965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        Frame output = context.getFrameManager().newFrame(inputFormat);
26065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
26165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Process
26265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        Frame[] inputs = {input, mHistFrame, mDensityFrame};
26365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mShaderProgram.process(inputs, output);
26465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
26565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Push output
26665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        pushOutput("image", output);
26765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
26865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Release pushed frame
26965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        output.release();
27065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
27165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
27265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private void createHistogramFrame(FilterContext context, int width, int height, int[] data) {
27365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        int histDims = 255 * 3 + 1;
27465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        int[] histArray = new int[histDims];
27565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
27665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        float border_thickness_ratio = 0.05f;
27765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        int y_border_thickness = (int) (height * border_thickness_ratio);
27865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        int x_border_thickness = (int) (width * border_thickness_ratio);
27965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        int pixels = (width - 2 * x_border_thickness) * (height - 2 * y_border_thickness);
28065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
28165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        float count = 0f;
28265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        for (int y = y_border_thickness; y < height - y_border_thickness; ++y) {
28365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            for (int x = x_border_thickness; x < width - x_border_thickness; ++x) {
28465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                int index = y * width + x;
28565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                int energy = (data[index] & 0xFF) + ((data[index] >> 8) & 0xFF) +
28665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    ((data[index] >> 16) & 0xFF);
28765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                histArray[energy] ++;
28865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
28965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
29065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
29165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        for (int i = 1; i < histDims; i++) {
29265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            histArray[i] += histArray[i-1];
29365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
29465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
29565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        for (int i = 0; i < histDims; i++) {
29665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            long temp = (256 * 256 - 1l) * histArray[i] / pixels;
29765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            histArray[i] =  (int) temp;
29865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
29965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
30065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        FrameFormat shaderHistFormat = ImageFormat.create(histDims, 1,
30165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                          ImageFormat.COLORSPACE_RGBA,
30265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                          FrameFormat.TARGET_GPU);
30365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mHistFrame != null)
30465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mHistFrame.release();
30565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
30665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mHistFrame = context.getFrameManager().newFrame(shaderHistFormat);
30765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mHistFrame.setInts(histArray);
30865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
30965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
310