/* * Copyright (C) 2012 Unknown * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma version(1) #pragma rs java_package_name(com.android.gallery3d.filtershow.filters) #define MAX_CHANELS 7 #define MAX_HUE 4096 static const int ABITS = 4; static const int HSCALE = 256; static const int k1=255 << ABITS; static const int k2=HSCALE << ABITS; static const float Rf = 0.2999f; static const float Gf = 0.587f; static const float Bf = 0.114f; rs_matrix3x3 colorMatrix_min; rs_matrix3x3 colorMatrix_max; int mNumberOfLines; // input data int saturation[MAX_CHANELS]; float sat[MAX_CHANELS]; float satLut[MAX_HUE]; // generated data void setupGradParams() { int master = saturation[0]; int max = master+saturation[1]; int min = max; // calculate the minimum and maximum saturation for (int i = 1; i < MAX_CHANELS; i++) { int v = master+saturation[i]; if (max < v) { max = v; } else if (min > v) { min = v; } } // generate a lookup table for all hue 0 to 4K which goes from 0 to 1 0=min sat 1 = max sat min = min - 1; for(int i = 0; i < MAX_HUE ; i++) { float p = i * 6 / (float)MAX_HUE; int ip = ((int)(p + .5f)) % 6; int v = master + saturation[ip + 1]; satLut[i] = (v - min)/(float)(max - min); } float S = 1 + max / 100.f; float MS = 1 - S; float Rt = Rf * MS; float Gt = Gf * MS; float Bt = Bf * MS; float b = 1.f; // Generate 2 color matrix one at min sat and one at max rsMatrixSet(&colorMatrix_max, 0, 0, b * (Rt + S)); rsMatrixSet(&colorMatrix_max, 1, 0, b * Gt); rsMatrixSet(&colorMatrix_max, 2, 0, b * Bt); rsMatrixSet(&colorMatrix_max, 0, 1, b * Rt); rsMatrixSet(&colorMatrix_max, 1, 1, b * (Gt + S)); rsMatrixSet(&colorMatrix_max, 2, 1, b * Bt); rsMatrixSet(&colorMatrix_max, 0, 2, b * Rt); rsMatrixSet(&colorMatrix_max, 1, 2, b * Gt); rsMatrixSet(&colorMatrix_max, 2, 2, b * (Bt + S)); S = 1 + min / 100.f; MS = 1-S; Rt = Rf * MS; Gt = Gf * MS; Bt = Bf * MS; b = 1; rsMatrixSet(&colorMatrix_min, 0, 0, b * (Rt + S)); rsMatrixSet(&colorMatrix_min, 1, 0, b * Gt); rsMatrixSet(&colorMatrix_min, 2, 0, b * Bt); rsMatrixSet(&colorMatrix_min, 0, 1, b * Rt); rsMatrixSet(&colorMatrix_min, 1, 1, b * (Gt + S)); rsMatrixSet(&colorMatrix_min, 2, 1, b * Bt); rsMatrixSet(&colorMatrix_min, 0, 2, b * Rt); rsMatrixSet(&colorMatrix_min, 1, 2, b * Gt); rsMatrixSet(&colorMatrix_min, 2, 2, b * (Bt + S)); } static ushort rgb2hue( uchar4 rgb) { int iMin,iMax,chroma; int ri = rgb.r; int gi = rgb.g; int bi = rgb.b; short rv,rs,rh; if (ri > gi) { iMax = max (ri, bi); iMin = min (gi, bi); } else { iMax = max (gi, bi); iMin = min (ri, bi); } rv = (short) (iMax << ABITS); if (rv == 0) { return 0; } chroma = iMax - iMin; rs = (short) ((k1 * chroma) / iMax); if (rs == 0) { return 0; } if ( ri == iMax ) { rh = (short) ((k2 * (6 * chroma + gi - bi))/(6 * chroma)); if (rh >= k2) { rh -= k2; } return rh; } if (gi == iMax) { return(short) ((k2 * (2 * chroma + bi - ri)) / (6 * chroma)); } return (short) ((k2 * (4 * chroma + ri - gi)) / (6 * chroma)); } uchar4 __attribute__((kernel)) selectiveAdjust(const uchar4 in, uint32_t x, uint32_t y) { float4 pixel = rsUnpackColor8888(in); int hue = rgb2hue(in); float t = satLut[hue]; pixel.xyz = rsMatrixMultiply(&colorMatrix_min ,pixel.xyz) * (1 - t) + t * (rsMatrixMultiply(&colorMatrix_max ,pixel.xyz)); pixel.a = 1.0f; return rsPackColorTo8888(clamp(pixel, 0.f, 1.0f)); }