NekoX/TMessagesProj/src/main/java/org/telegram/ui/Components/FilterShaders.java

1404 lines
73 KiB
Java

package org.telegram.ui.Components;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.MediaController;
import org.telegram.messenger.Utilities;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
public class FilterShaders {
private static final String radialBlurFragmentShaderCode =
"varying highp vec2 texCoord;" +
"uniform sampler2D sourceImage;" +
"uniform sampler2D inputImageTexture2;" +
"uniform lowp float excludeSize;" +
"uniform lowp vec2 excludePoint;" +
"uniform lowp float excludeBlurSize;" +
"uniform highp float aspectRatio;" +
"void main() {" +
"lowp vec4 sharpImageColor = texture2D(sourceImage, texCoord);" +
"lowp vec4 blurredImageColor = texture2D(inputImageTexture2, texCoord);" +
"highp vec2 texCoordToUse = vec2(texCoord.x, (texCoord.y * aspectRatio + 0.5 - 0.5 * aspectRatio));" +
"highp float distanceFromCenter = distance(excludePoint, texCoordToUse);" +
"gl_FragColor = mix(sharpImageColor, blurredImageColor, smoothstep(excludeSize - excludeBlurSize, excludeSize, distanceFromCenter));" +
"}";
private static final String linearBlurFragmentShaderCode =
"varying highp vec2 texCoord;" +
"uniform sampler2D sourceImage;" +
"uniform sampler2D inputImageTexture2;" +
"uniform lowp float excludeSize;" +
"uniform lowp vec2 excludePoint;" +
"uniform lowp float excludeBlurSize;" +
"uniform highp float angle;" +
"uniform highp float aspectRatio;" +
"void main() {" +
"lowp vec4 sharpImageColor = texture2D(sourceImage, texCoord);" +
"lowp vec4 blurredImageColor = texture2D(inputImageTexture2, texCoord);" +
"highp vec2 texCoordToUse = vec2(texCoord.x, (texCoord.y * aspectRatio + 0.5 - 0.5 * aspectRatio));" +
"highp float distanceFromCenter = abs((texCoordToUse.x - excludePoint.x) * aspectRatio * cos(angle) + (texCoordToUse.y - excludePoint.y) * sin(angle));" +
"gl_FragColor = mix(sharpImageColor, blurredImageColor, smoothstep(excludeSize - excludeBlurSize, excludeSize, distanceFromCenter));" +
"}";
private static final String blurVertexShaderCode =
"attribute vec4 position;" +
"attribute vec4 inputTexCoord;" +
"uniform highp float texelWidthOffset;" +
"uniform highp float texelHeightOffset;" +
"varying vec2 blurCoordinates[9];" +
"void main() {" +
"gl_Position = position;" +
"vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);" +
"blurCoordinates[0] = inputTexCoord.xy;" +
"blurCoordinates[1] = inputTexCoord.xy + singleStepOffset * 1.458430;" +
"blurCoordinates[2] = inputTexCoord.xy - singleStepOffset * 1.458430;" +
"blurCoordinates[3] = inputTexCoord.xy + singleStepOffset * 3.403985;" +
"blurCoordinates[4] = inputTexCoord.xy - singleStepOffset * 3.403985;" +
"blurCoordinates[5] = inputTexCoord.xy + singleStepOffset * 5.351806;" +
"blurCoordinates[6] = inputTexCoord.xy - singleStepOffset * 5.351806;" +
"blurCoordinates[7] = inputTexCoord.xy + singleStepOffset * 7.302940;" +
"blurCoordinates[8] = inputTexCoord.xy - singleStepOffset * 7.302940;" +
"}";
private static final String blurFragmentShaderCode =
"uniform sampler2D sourceImage;" +
"varying highp vec2 blurCoordinates[9];" +
"void main() {" +
"lowp vec4 sum = vec4(0.0);" +
"sum += texture2D(sourceImage, blurCoordinates[0]) * 0.133571;" +
"sum += texture2D(sourceImage, blurCoordinates[1]) * 0.233308;" +
"sum += texture2D(sourceImage, blurCoordinates[2]) * 0.233308;" +
"sum += texture2D(sourceImage, blurCoordinates[3]) * 0.135928;" +
"sum += texture2D(sourceImage, blurCoordinates[4]) * 0.135928;" +
"sum += texture2D(sourceImage, blurCoordinates[5]) * 0.051383;" +
"sum += texture2D(sourceImage, blurCoordinates[6]) * 0.051383;" +
"sum += texture2D(sourceImage, blurCoordinates[7]) * 0.012595;" +
"sum += texture2D(sourceImage, blurCoordinates[8]) * 0.012595;" +
"gl_FragColor = sum;" +
"}";
private static final String simpleVertexVideoShaderCode =
"attribute vec4 position;" +
"uniform mat4 videoMatrix;" +
"attribute vec4 inputTexCoord;" +
"varying vec2 texCoord;" +
"void main() {" +
"gl_Position = position;" +
"texCoord = vec2(videoMatrix * inputTexCoord).xy;" +
"}";
private static final String rgbToHsvFragmentVideoShaderCode =
"#extension GL_OES_EGL_image_external : require\n" +
"precision highp float;" +
"varying vec2 texCoord;" +
"uniform samplerExternalOES sourceImage;" +
"vec3 rgb_to_hsv(vec3 c) {" +
"vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);" +
"vec4 p = c.g < c.b ? vec4(c.bg, K.wz) : vec4(c.gb, K.xy);" +
"vec4 q = c.r < p.x ? vec4(p.xyw, c.r) : vec4(c.r, p.yzx);" +
"float d = q.x - min(q.w, q.y);" +
"float e = 1.0e-10;" +
"return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);" +
"}" +
"void main() {" +
"vec4 texel = texture2D(sourceImage, texCoord);" +
"gl_FragColor = vec4(rgb_to_hsv(texel.rgb), texel.a);" +
"}";
private static final String rgbToHsvFragmentShaderCode =
"precision highp float;" +
"varying vec2 texCoord;" +
"uniform sampler2D sourceImage;" +
"vec3 rgb_to_hsv(vec3 c) {" +
"vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);" +
"vec4 p = c.g < c.b ? vec4(c.bg, K.wz) : vec4(c.gb, K.xy);" +
"vec4 q = c.r < p.x ? vec4(p.xyw, c.r) : vec4(c.r, p.yzx);" +
"float d = q.x - min(q.w, q.y);" +
"float e = 1.0e-10;" +
"return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);" +
"}" +
"void main() {" +
"vec4 texel = texture2D(sourceImage, texCoord);" +
"gl_FragColor = vec4(rgb_to_hsv(texel.rgb), texel.a);" +
"}";
private static final String enhanceFragmentShaderCode =
"precision highp float;" +
"varying vec2 texCoord;" +
"uniform sampler2D sourceImage;" +
"uniform sampler2D inputImageTexture2;" +
"uniform float intensity;" +
"float enhance(float value) {" +
"const vec2 offset = vec2(0.001953125, 0.03125);" +
"value = value + offset.x;" +
"vec2 coord = (clamp(texCoord, 0.125, 1.0 - 0.125001) - 0.125) * 4.0;" +
"vec2 frac = fract(coord);" +
"coord = floor(coord);" +
"float p00 = float(coord.y * 4.0 + coord.x) * 0.0625 + offset.y;" +
"float p01 = float(coord.y * 4.0 + coord.x + 1.0) * 0.0625 + offset.y;" +
"float p10 = float((coord.y + 1.0) * 4.0 + coord.x) * 0.0625 + offset.y;" +
"float p11 = float((coord.y + 1.0) * 4.0 + coord.x + 1.0) * 0.0625 + offset.y;" +
"vec3 c00 = texture2D(inputImageTexture2, vec2(value, p00)).rgb;" +
"vec3 c01 = texture2D(inputImageTexture2, vec2(value, p01)).rgb;" +
"vec3 c10 = texture2D(inputImageTexture2, vec2(value, p10)).rgb;" +
"vec3 c11 = texture2D(inputImageTexture2, vec2(value, p11)).rgb;" +
"float c1 = ((c00.r - c00.g) / (c00.b - c00.g));" +
"float c2 = ((c01.r - c01.g) / (c01.b - c01.g));" +
"float c3 = ((c10.r - c10.g) / (c10.b - c10.g));" +
"float c4 = ((c11.r - c11.g) / (c11.b - c11.g));" +
"float c1_2 = mix(c1, c2, frac.x);" +
"float c3_4 = mix(c3, c4, frac.x);" +
"return mix(c1_2, c3_4, frac.y);" +
"}" +
"vec3 hsv_to_rgb(vec3 c) {" +
"vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);" +
"vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);" +
"return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);" +
"}" +
"void main() {" +
"vec4 texel = texture2D(sourceImage, texCoord);" +
"vec4 hsv = texel;" +
"hsv.y = min(1.0, hsv.y * 1.2);" +
"hsv.z = min(1.0, enhance(hsv.z) * 1.1);" +
"gl_FragColor = vec4(hsv_to_rgb(mix(texel.xyz, hsv.xyz, intensity)), texel.w);" +
"}";
public static final String simpleVertexShaderCode =
"attribute vec4 position;" +
"attribute vec2 inputTexCoord;" +
"varying vec2 texCoord;" +
"void main() {" +
"gl_Position = position;" +
"texCoord = inputTexCoord;" +
"}";
public static final String simpleFragmentShaderCode =
"varying highp vec2 texCoord;" +
"uniform sampler2D sourceImage;" +
"void main() {" +
"gl_FragColor = texture2D(sourceImage, texCoord);" +
"}";
private static final String sharpenVertexShaderCode =
"attribute vec4 position;" +
"attribute vec2 inputTexCoord;" +
"varying vec2 texCoord;" +
"uniform highp float inputWidth;" +
"uniform highp float inputHeight;" +
"varying vec2 leftTexCoord;" +
"varying vec2 rightTexCoord;" +
"varying vec2 topTexCoord;" +
"varying vec2 bottomTexCoord;" +
"void main() {" +
"gl_Position = position;" +
"texCoord = inputTexCoord;" +
"highp vec2 widthStep = vec2(1.0 / inputWidth, 0.0);" +
"highp vec2 heightStep = vec2(0.0, 1.0 / inputHeight);" +
"leftTexCoord = inputTexCoord - widthStep;" +
"rightTexCoord = inputTexCoord + widthStep;" +
"topTexCoord = inputTexCoord + heightStep;" +
"bottomTexCoord = inputTexCoord - heightStep;" +
"}";
private static final String sharpenFragmentShaderCode =
"precision highp float;" +
"varying vec2 texCoord;" +
"varying vec2 leftTexCoord;" +
"varying vec2 rightTexCoord;" +
"varying vec2 topTexCoord;" +
"varying vec2 bottomTexCoord;" +
"uniform sampler2D sourceImage;" +
"uniform float sharpen;" +
"void main() {" +
"vec4 result = texture2D(sourceImage, texCoord);" +
"vec3 leftTextureColor = texture2D(sourceImage, leftTexCoord).rgb;" +
"vec3 rightTextureColor = texture2D(sourceImage, rightTexCoord).rgb;" +
"vec3 topTextureColor = texture2D(sourceImage, topTexCoord).rgb;" +
"vec3 bottomTextureColor = texture2D(sourceImage, bottomTexCoord).rgb;" +
"result.rgb = result.rgb * (1.0 + 4.0 * sharpen) - (leftTextureColor + rightTextureColor + topTextureColor + bottomTextureColor) * sharpen;" +
"gl_FragColor = result;" +
"}";
private static final String toolsFragmentShaderCode =
"varying highp vec2 texCoord;" +
"uniform sampler2D sourceImage;" +
"uniform highp float width;" +
"uniform highp float height;" +
"uniform sampler2D curvesImage;" +
"uniform lowp float skipTone;" +
"uniform lowp float shadows;" +
"const mediump vec3 hsLuminanceWeighting = vec3(0.3, 0.3, 0.3);" +
"uniform lowp float highlights;" +
"uniform lowp float contrast;" +
"uniform lowp float fadeAmount;" +
"const mediump vec3 satLuminanceWeighting = vec3(0.2126, 0.7152, 0.0722);" +
"uniform lowp float saturation;" +
"uniform lowp float shadowsTintIntensity;" +
"uniform lowp float highlightsTintIntensity;" +
"uniform lowp vec3 shadowsTintColor;" +
"uniform lowp vec3 highlightsTintColor;" +
"uniform lowp float exposure;" +
"uniform lowp float warmth;" +
"uniform lowp float grain;" +
"const lowp float permTexUnit = 1.0 / 256.0;" +
"const lowp float permTexUnitHalf = 0.5 / 256.0;" +
"const lowp float grainsize = 2.3;" +
"uniform lowp float vignette;" +
"highp float getLuma(highp vec3 rgbP) {" +
"return (0.299 * rgbP.r) + (0.587 * rgbP.g) + (0.114 * rgbP.b);" +
"}" +
"lowp vec3 rgbToHsv(lowp vec3 c) {" +
"highp vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);" +
"highp vec4 p = c.g < c.b ? vec4(c.bg, K.wz) : vec4(c.gb, K.xy);" +
"highp vec4 q = c.r < p.x ? vec4(p.xyw, c.r) : vec4(c.r, p.yzx);" +
"highp float d = q.x - min(q.w, q.y);" +
"highp float e = 1.0e-10;" +
"return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);" +
"}" +
"lowp vec3 hsvToRgb(lowp vec3 c) {" +
"highp vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);" +
"highp vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);" +
"return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);" +
"}" +
"highp vec3 rgbToHsl(highp vec3 color) {" +
"highp vec3 hsl;" +
"highp float fmin = min(min(color.r, color.g), color.b);" +
"highp float fmax = max(max(color.r, color.g), color.b);" +
"highp float delta = fmax - fmin;" +
"hsl.z = (fmax + fmin) / 2.0;" +
"if (delta == 0.0) {" +
"hsl.x = 0.0;" +
"hsl.y = 0.0;" +
"} else {" +
"if (hsl.z < 0.5) {" +
"hsl.y = delta / (fmax + fmin);" +
"} else {" +
"hsl.y = delta / (2.0 - fmax - fmin);" +
"}" +
"highp float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;" +
"highp float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;" +
"highp float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;" +
"if (color.r == fmax) {" +
"hsl.x = deltaB - deltaG;" +
"} else if (color.g == fmax) {" +
"hsl.x = (1.0 / 3.0) + deltaR - deltaB;" +
"} else if (color.b == fmax) {" +
"hsl.x = (2.0 / 3.0) + deltaG - deltaR;" +
"}" +
"if (hsl.x < 0.0) {" +
"hsl.x += 1.0;" +
"} else if (hsl.x > 1.0) {" +
"hsl.x -= 1.0;" +
"}" +
"}" +
"return hsl;" +
"}" +
"highp float hueToRgb(highp float f1, highp float f2, highp float hue) {" +
"if (hue < 0.0) {" +
"hue += 1.0;" +
"} else if (hue > 1.0) {" +
"hue -= 1.0;" +
"}" +
"highp float res;" +
"if ((6.0 * hue) < 1.0) {" +
"res = f1 + (f2 - f1) * 6.0 * hue;" +
"} else if ((2.0 * hue) < 1.0) {" +
"res = f2;" +
"} else if ((3.0 * hue) < 2.0) {" +
"res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;" +
"} else {" +
"res = f1;" +
"} return res;" +
"}" +
"highp vec3 hslToRgb(highp vec3 hsl) {" +
"if (hsl.y == 0.0) {" +
"return vec3(hsl.z);" +
"} else {" +
"highp float f2;" +
"if (hsl.z < 0.5) {" +
"f2 = hsl.z * (1.0 + hsl.y);" +
"} else {" +
"f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z);" +
"}" +
"highp float f1 = 2.0 * hsl.z - f2;" +
"return vec3(hueToRgb(f1, f2, hsl.x + (1.0/3.0)), hueToRgb(f1, f2, hsl.x), hueToRgb(f1, f2, hsl.x - (1.0/3.0)));" +
"}" +
"}" +
"highp vec3 rgbToYuv(highp vec3 inP) {" +
"highp float luma = getLuma(inP);" +
"return vec3(luma, (1.0 / 1.772) * (inP.b - luma), (1.0 / 1.402) * (inP.r - luma));" +
"}" +
"lowp vec3 yuvToRgb(highp vec3 inP) {" +
"return vec3(1.402 * inP.b + inP.r, (inP.r - (0.299 * 1.402 / 0.587) * inP.b - (0.114 * 1.772 / 0.587) * inP.g), 1.772 * inP.g + inP.r);" +
"}" +
"lowp float easeInOutSigmoid(lowp float value, lowp float strength) {" +
"if (value > 0.5) {" +
"return 1.0 - pow(2.0 - 2.0 * value, 1.0 / (1.0 - strength)) * 0.5;" +
"} else {" +
"return pow(2.0 * value, 1.0 / (1.0 - strength)) * 0.5;" +
"}" +
"}" +
"lowp vec3 applyLuminanceCurve(lowp vec3 pixel) {" +
"highp float index = floor(clamp(pixel.z / (1.0 / 200.0), 0.0, 199.0));" +
"pixel.y = mix(0.0, pixel.y, smoothstep(0.0, 0.1, pixel.z) * (1.0 - smoothstep(0.8, 1.0, pixel.z)));" +
"pixel.z = texture2D(curvesImage, vec2(1.0 / 200.0 * index, 0)).a;" +
"return pixel;" +
"}" +
"lowp vec3 applyRGBCurve(lowp vec3 pixel) {" +
"highp float index = floor(clamp(pixel.r / (1.0 / 200.0), 0.0, 199.0));" +
"pixel.r = texture2D(curvesImage, vec2(1.0 / 200.0 * index, 0)).r;" +
"index = floor(clamp(pixel.g / (1.0 / 200.0), 0.0, 199.0));" +
"pixel.g = clamp(texture2D(curvesImage, vec2(1.0 / 200.0 * index, 0)).g, 0.0, 1.0);" +
"index = floor(clamp(pixel.b / (1.0 / 200.0), 0.0, 199.0));" +
"pixel.b = clamp(texture2D(curvesImage, vec2(1.0 / 200.0 * index, 0)).b, 0.0, 1.0);" +
"return pixel;" +
"}" +
"highp vec3 fadeAdjust(highp vec3 color, highp float fadeVal) {" +
"return (color * (1.0 - fadeVal)) + ((color + (vec3(-0.9772) * pow(vec3(color), vec3(3.0)) + vec3(1.708) * pow(vec3(color), vec3(2.0)) + vec3(-0.1603) * vec3(color) + vec3(0.2878) - color * vec3(0.9))) * fadeVal);" +
"}" +
"lowp vec3 tintRaiseShadowsCurve(lowp vec3 color) {" +
"return vec3(-0.003671) * pow(color, vec3(3.0)) + vec3(0.3842) * pow(color, vec3(2.0)) + vec3(0.3764) * color + vec3(0.2515);" +
"}" +
"lowp vec3 tintShadows(lowp vec3 texel, lowp vec3 tintColor, lowp float tintAmount) {" +
"return clamp(mix(texel, mix(texel, tintRaiseShadowsCurve(texel), tintColor), tintAmount), 0.0, 1.0);" +
"} " +
"lowp vec3 tintHighlights(lowp vec3 texel, lowp vec3 tintColor, lowp float tintAmount) {" +
"return clamp(mix(texel, mix(texel, vec3(1.0) - tintRaiseShadowsCurve(vec3(1.0) - texel), (vec3(1.0) - tintColor)), tintAmount), 0.0, 1.0);" +
"}" +
"highp vec4 rnm(in highp vec2 tc) {" +
"highp float noise = sin(dot(tc, vec2(12.9898, 78.233))) * 43758.5453;" +
"return vec4(fract(noise), fract(noise * 1.2154), fract(noise * 1.3453), fract(noise * 1.3647)) * 2.0 - 1.0;" +
"}" +
"highp float fade(in highp float t) {" +
"return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);" +
"}" +
"highp float pnoise3D(in highp vec3 p) {" +
"highp vec3 pi = permTexUnit * floor(p) + permTexUnitHalf;" +
"highp vec3 pf = fract(p);" +
"highp float perm = rnm(pi.xy).a;" +
"highp float n000 = dot(rnm(vec2(perm, pi.z)).rgb * 4.0 - 1.0, pf);" +
"highp float n001 = dot(rnm(vec2(perm, pi.z + permTexUnit)).rgb * 4.0 - 1.0, pf - vec3(0.0, 0.0, 1.0));" +
"perm = rnm(pi.xy + vec2(0.0, permTexUnit)).a;" +
"highp float n010 = dot(rnm(vec2(perm, pi.z)).rgb * 4.0 - 1.0, pf - vec3(0.0, 1.0, 0.0));" +
"highp float n011 = dot(rnm(vec2(perm, pi.z + permTexUnit)).rgb * 4.0 - 1.0, pf - vec3(0.0, 1.0, 1.0));" +
"perm = rnm(pi.xy + vec2(permTexUnit, 0.0)).a;" +
"highp float n100 = dot(rnm(vec2(perm, pi.z)).rgb * 4.0 - 1.0, pf - vec3(1.0, 0.0, 0.0));" +
"highp float n101 = dot(rnm(vec2(perm, pi.z + permTexUnit)).rgb * 4.0 - 1.0, pf - vec3(1.0, 0.0, 1.0));" +
"perm = rnm(pi.xy + vec2(permTexUnit, permTexUnit)).a;" +
"highp float n110 = dot(rnm(vec2(perm, pi.z)).rgb * 4.0 - 1.0, pf - vec3(1.0, 1.0, 0.0));" +
"highp float n111 = dot(rnm(vec2(perm, pi.z + permTexUnit)).rgb * 4.0 - 1.0, pf - vec3(1.0, 1.0, 1.0));" +
"highp vec4 n_x = mix(vec4(n000, n001, n010, n011), vec4(n100, n101, n110, n111), fade(pf.x));" +
"highp vec2 n_xy = mix(n_x.xy, n_x.zw, fade(pf.y));" +
"return mix(n_xy.x, n_xy.y, fade(pf.z));" +
"}" +
"lowp vec2 coordRot(in lowp vec2 tc, in lowp float angle) {" +
"return vec2(((tc.x * 2.0 - 1.0) * cos(angle) - (tc.y * 2.0 - 1.0) * sin(angle)) * 0.5 + 0.5, ((tc.y * 2.0 - 1.0) * cos(angle) + (tc.x * 2.0 - 1.0) * sin(angle)) * 0.5 + 0.5);" +
"}" +
"void main() {" +
"lowp vec4 source = texture2D(sourceImage, texCoord);" +
"lowp vec4 result = source;" +
"const lowp float toolEpsilon = 0.005;" +
"if (skipTone < toolEpsilon) {" +
"result = vec4(applyRGBCurve(hslToRgb(applyLuminanceCurve(rgbToHsl(result.rgb)))), result.a);" +
"}" +
"mediump float hsLuminance = dot(result.rgb, hsLuminanceWeighting);" +
"mediump float shadow = clamp((pow(hsLuminance, 1.0 / shadows) + (-0.76) * pow(hsLuminance, 2.0 / shadows)) - hsLuminance, 0.0, 1.0);" +
"mediump float highlight = clamp((1.0 - (pow(1.0 - hsLuminance, 1.0 / (2.0 - highlights)) + (-0.8) * pow(1.0 - hsLuminance, 2.0 / (2.0 - highlights)))) - hsLuminance, -1.0, 0.0);" +
"lowp vec3 hsresult = vec3(0.0, 0.0, 0.0) + ((hsLuminance + shadow + highlight) - 0.0) * ((result.rgb - vec3(0.0, 0.0, 0.0)) / (hsLuminance - 0.0));" +
"mediump float contrastedLuminance = ((hsLuminance - 0.5) * 1.5) + 0.5;" +
"mediump float whiteInterp = contrastedLuminance * contrastedLuminance * contrastedLuminance;" +
"mediump float whiteTarget = clamp(highlights, 1.0, 2.0) - 1.0;" +
"hsresult = mix(hsresult, vec3(1.0), whiteInterp * whiteTarget);" +
"mediump float invContrastedLuminance = 1.0 - contrastedLuminance;" +
"mediump float blackInterp = invContrastedLuminance * invContrastedLuminance * invContrastedLuminance;" +
"mediump float blackTarget = 1.0 - clamp(shadows, 0.0, 1.0);" +
"hsresult = mix(hsresult, vec3(0.0), blackInterp * blackTarget);" +
"result = vec4(hsresult.rgb, result.a);" +
"result = vec4(clamp(((result.rgb - vec3(0.5)) * contrast + vec3(0.5)), 0.0, 1.0), result.a);" +
"if (abs(fadeAmount) > toolEpsilon) {" +
"result.rgb = fadeAdjust(result.rgb, fadeAmount);" +
"}" +
"lowp float satLuminance = dot(result.rgb, satLuminanceWeighting);" +
"lowp vec3 greyScaleColor = vec3(satLuminance);" +
"result = vec4(clamp(mix(greyScaleColor, result.rgb, saturation), 0.0, 1.0), result.a);" +
"if (abs(shadowsTintIntensity) > toolEpsilon) {" +
"result.rgb = tintShadows(result.rgb, shadowsTintColor, shadowsTintIntensity * 2.0);" +
"}" +
"if (abs(highlightsTintIntensity) > toolEpsilon) {" +
"result.rgb = tintHighlights(result.rgb, highlightsTintColor, highlightsTintIntensity * 2.0);" +
"}" +
"if (abs(exposure) > toolEpsilon) {" +
"mediump float mag = exposure * 1.045;" +
"mediump float exppower = 1.0 + abs(mag);" +
"if (mag < 0.0) {" +
"exppower = 1.0 / exppower;" +
"}" +
"result.r = 1.0 - pow((1.0 - result.r), exppower);" +
"result.g = 1.0 - pow((1.0 - result.g), exppower);" +
"result.b = 1.0 - pow((1.0 - result.b), exppower);" +
"}" +
"if (abs(warmth) > toolEpsilon) {" +
"highp vec3 yuvVec;" +
"if (warmth > 0.0 ) {" +
"yuvVec = vec3(0.1765, -0.1255, 0.0902);" +
"} else {" +
"yuvVec = -vec3(0.0588, 0.1569, -0.1255);" +
"}" +
"highp vec3 yuvColor = rgbToYuv(result.rgb);" +
"highp float luma = yuvColor.r;" +
"highp float curveScale = sin(luma * 3.14159);" +
"yuvColor += 0.375 * warmth * curveScale * yuvVec;" +
"result.rgb = yuvToRgb(yuvColor);" +
"}" +
"if (abs(grain) > toolEpsilon) {" +
"highp vec3 rotOffset = vec3(1.425, 3.892, 5.835);" +
"highp vec2 rotCoordsR = coordRot(texCoord, rotOffset.x);" +
"highp vec3 noise = vec3(pnoise3D(vec3(rotCoordsR * vec2(width / grainsize, height / grainsize),0.0)));" +
"lowp vec3 lumcoeff = vec3(0.299,0.587,0.114);" +
"lowp float luminance = dot(result.rgb, lumcoeff);" +
"lowp float lum = smoothstep(0.2, 0.0, luminance);" +
"lum += luminance;" +
"noise = mix(noise,vec3(0.0),pow(lum,4.0));" +
"result.rgb = result.rgb + noise * grain;" +
"}" +
"if (abs(vignette) > toolEpsilon) {" +
"const lowp float midpoint = 0.7;" +
"const lowp float fuzziness = 0.62;" +
"lowp float radDist = length(texCoord - 0.5) / sqrt(0.5);" +
"lowp float mag = easeInOutSigmoid(radDist * midpoint, fuzziness) * vignette * 0.645;" +
"result.rgb = mix(pow(result.rgb, vec3(1.0 / (1.0 - mag))), vec3(0.0), mag * mag);" +
"}" +
"gl_FragColor = result;" +
"}";
public interface FilterShadersDelegate {
boolean shouldShowOriginal();
float getShadowsValue();
float getHighlightsValue();
float getEnhanceValue();
float getExposureValue();
float getContrastValue();
float getWarmthValue();
float getVignetteValue();
float getSharpenValue();
float getGrainValue();
float getFadeValue();
float getTintHighlightsIntensityValue();
float getTintShadowsIntensityValue();
float getSaturationValue();
int getTintHighlightsColor();
int getTintShadowsColor();
int getBlurType();
float getBlurExcludeSize();
float getBlurExcludeBlurSize();
float getBlurAngle();
Point getBlurExcludePoint();
boolean shouldDrawCurvesPass();
ByteBuffer fillAndGetCurveBuffer();
}
private boolean needUpdateBlurTexture = true;
private int rgbToHsvShaderProgram;
private int rgbToHsvPositionHandle;
private int rgbToHsvInputTexCoordHandle;
private int rgbToHsvSourceImageHandle;
private int rgbToHsvMatrixHandle;
private int enhanceShaderProgram;
private int enhancePositionHandle;
private int enhanceInputTexCoordHandle;
private int enhanceSourceImageHandle;
private int enhanceIntensityHandle;
private int enhanceInputImageTexture2Handle;
private int toolsShaderProgram;
private int positionHandle;
private int inputTexCoordHandle;
private int sourceImageHandle;
private int shadowsHandle;
private int highlightsHandle;
private int exposureHandle;
private int contrastHandle;
private int saturationHandle;
private int warmthHandle;
private int vignetteHandle;
private int grainHandle;
private int widthHandle;
private int heightHandle;
private int curvesImageHandle;
private int skipToneHandle;
private int fadeAmountHandle;
private int shadowsTintIntensityHandle;
private int highlightsTintIntensityHandle;
private int shadowsTintColorHandle;
private int highlightsTintColorHandle;
private int blurShaderProgram;
private int blurPositionHandle;
private int blurInputTexCoordHandle;
private int blurSourceImageHandle;
private int blurWidthHandle;
private int blurHeightHandle;
private int linearBlurShaderProgram;
private int linearBlurPositionHandle;
private int linearBlurInputTexCoordHandle;
private int linearBlurSourceImageHandle;
private int linearBlurSourceImage2Handle;
private int linearBlurExcludeSizeHandle;
private int linearBlurExcludePointHandle;
private int linearBlurExcludeBlurSizeHandle;
private int linearBlurAngleHandle;
private int linearBlurAspectRatioHandle;
private int radialBlurShaderProgram;
private int radialBlurPositionHandle;
private int radialBlurInputTexCoordHandle;
private int radialBlurSourceImageHandle;
private int radialBlurSourceImage2Handle;
private int radialBlurExcludeSizeHandle;
private int radialBlurExcludePointHandle;
private int radialBlurExcludeBlurSizeHandle;
private int radialBlurAspectRatioHandle;
private int sharpenShaderProgram;
private int sharpenHandle;
private int sharpenWidthHandle;
private int sharpenHeightHandle;
private int sharpenPositionHandle;
private int sharpenInputTexCoordHandle;
private int sharpenSourceImageHandle;
private int videoTexture;
private float[] videoMatrix;
private int videoFramesCount;
private int[] enhanceTextures = new int[2];
private int[] enhanceFrameBuffer = new int[1];
private int[] renderTexture = new int[3];
private int[] renderFrameBuffer;
private int[] curveTextures = new int[1];
private boolean hsvGenerated;
private int renderBufferWidth;
private int renderBufferHeight;
private FloatBuffer vertexBuffer;
private FloatBuffer textureBuffer;
private FloatBuffer vertexInvertBuffer;
private ByteBuffer hsvBuffer;
private ByteBuffer cdtBuffer;
private ByteBuffer calcBuffer;
private final static int PGPhotoEnhanceHistogramBins = 256;
private final static int PGPhotoEnhanceSegments = 4;
private FilterShadersDelegate delegate;
private boolean isVideo;
public FilterShaders(boolean video) {
isVideo = video;
float[] squareCoordinates = {
-1.0f, 1.0f,
1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, -1.0f};
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoordinates.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoordinates);
vertexBuffer.position(0);
float[] squareCoordinates2 = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f};
bb = ByteBuffer.allocateDirect(squareCoordinates2.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexInvertBuffer = bb.asFloatBuffer();
vertexInvertBuffer.put(squareCoordinates2);
vertexInvertBuffer.position(0);
float[] textureCoordinates = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};
bb = ByteBuffer.allocateDirect(textureCoordinates.length * 4);
bb.order(ByteOrder.nativeOrder());
textureBuffer = bb.asFloatBuffer();
textureBuffer.put(textureCoordinates);
textureBuffer.position(0);
}
public void setDelegate(FilterShadersDelegate filterShadersDelegate) {
delegate = filterShadersDelegate;
}
public boolean create() {
GLES20.glGenTextures(1, curveTextures, 0);
GLES20.glGenTextures(2, enhanceTextures, 0);
GLES20.glGenFramebuffers(1, enhanceFrameBuffer, 0);
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, enhanceTextures[1]);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, curveTextures[0]);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, simpleVertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, toolsFragmentShaderCode);
if (vertexShader != 0 && fragmentShader != 0) {
toolsShaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(toolsShaderProgram, vertexShader);
GLES20.glAttachShader(toolsShaderProgram, fragmentShader);
GLES20.glBindAttribLocation(toolsShaderProgram, 0, "position");
GLES20.glBindAttribLocation(toolsShaderProgram, 1, "inputTexCoord");
GLES20.glLinkProgram(toolsShaderProgram);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(toolsShaderProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
GLES20.glDeleteProgram(toolsShaderProgram);
toolsShaderProgram = 0;
} else {
positionHandle = GLES20.glGetAttribLocation(toolsShaderProgram, "position");
inputTexCoordHandle = GLES20.glGetAttribLocation(toolsShaderProgram, "inputTexCoord");
sourceImageHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "sourceImage");
shadowsHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "shadows");
highlightsHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "highlights");
exposureHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "exposure");
contrastHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "contrast");
saturationHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "saturation");
warmthHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "warmth");
vignetteHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "vignette");
grainHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "grain");
widthHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "width");
heightHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "height");
curvesImageHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "curvesImage");
skipToneHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "skipTone");
fadeAmountHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "fadeAmount");
shadowsTintIntensityHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "shadowsTintIntensity");
highlightsTintIntensityHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "highlightsTintIntensity");
shadowsTintColorHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "shadowsTintColor");
highlightsTintColorHandle = GLES20.glGetUniformLocation(toolsShaderProgram, "highlightsTintColor");
}
} else {
return false;
}
vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, sharpenVertexShaderCode);
fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, sharpenFragmentShaderCode);
if (vertexShader != 0 && fragmentShader != 0) {
sharpenShaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(sharpenShaderProgram, vertexShader);
GLES20.glAttachShader(sharpenShaderProgram, fragmentShader);
GLES20.glBindAttribLocation(sharpenShaderProgram, 0, "position");
GLES20.glBindAttribLocation(sharpenShaderProgram, 1, "inputTexCoord");
GLES20.glLinkProgram(sharpenShaderProgram);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(sharpenShaderProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
GLES20.glDeleteProgram(sharpenShaderProgram);
sharpenShaderProgram = 0;
} else {
sharpenPositionHandle = GLES20.glGetAttribLocation(sharpenShaderProgram, "position");
sharpenInputTexCoordHandle = GLES20.glGetAttribLocation(sharpenShaderProgram, "inputTexCoord");
sharpenSourceImageHandle = GLES20.glGetUniformLocation(sharpenShaderProgram, "sourceImage");
sharpenWidthHandle = GLES20.glGetUniformLocation(sharpenShaderProgram, "inputWidth");
sharpenHeightHandle = GLES20.glGetUniformLocation(sharpenShaderProgram, "inputHeight");
sharpenHandle = GLES20.glGetUniformLocation(sharpenShaderProgram, "sharpen");
}
} else {
return false;
}
vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, blurVertexShaderCode);
fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, blurFragmentShaderCode);
if (vertexShader != 0 && fragmentShader != 0) {
blurShaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(blurShaderProgram, vertexShader);
GLES20.glAttachShader(blurShaderProgram, fragmentShader);
GLES20.glBindAttribLocation(blurShaderProgram, 0, "position");
GLES20.glBindAttribLocation(blurShaderProgram, 1, "inputTexCoord");
GLES20.glLinkProgram(blurShaderProgram);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(blurShaderProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
GLES20.glDeleteProgram(blurShaderProgram);
blurShaderProgram = 0;
} else {
blurPositionHandle = GLES20.glGetAttribLocation(blurShaderProgram, "position");
blurInputTexCoordHandle = GLES20.glGetAttribLocation(blurShaderProgram, "inputTexCoord");
blurSourceImageHandle = GLES20.glGetUniformLocation(blurShaderProgram, "sourceImage");
blurWidthHandle = GLES20.glGetUniformLocation(blurShaderProgram, "texelWidthOffset");
blurHeightHandle = GLES20.glGetUniformLocation(blurShaderProgram, "texelHeightOffset");
}
} else {
return false;
}
vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, simpleVertexShaderCode);
fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, linearBlurFragmentShaderCode);
if (vertexShader != 0 && fragmentShader != 0) {
linearBlurShaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(linearBlurShaderProgram, vertexShader);
GLES20.glAttachShader(linearBlurShaderProgram, fragmentShader);
GLES20.glBindAttribLocation(linearBlurShaderProgram, 0, "position");
GLES20.glBindAttribLocation(linearBlurShaderProgram, 1, "inputTexCoord");
GLES20.glLinkProgram(linearBlurShaderProgram);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(linearBlurShaderProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
GLES20.glDeleteProgram(linearBlurShaderProgram);
linearBlurShaderProgram = 0;
} else {
linearBlurPositionHandle = GLES20.glGetAttribLocation(linearBlurShaderProgram, "position");
linearBlurInputTexCoordHandle = GLES20.glGetAttribLocation(linearBlurShaderProgram, "inputTexCoord");
linearBlurSourceImageHandle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "sourceImage");
linearBlurSourceImage2Handle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "inputImageTexture2");
linearBlurExcludeSizeHandle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "excludeSize");
linearBlurExcludePointHandle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "excludePoint");
linearBlurExcludeBlurSizeHandle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "excludeBlurSize");
linearBlurAngleHandle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "angle");
linearBlurAspectRatioHandle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "aspectRatio");
}
} else {
return false;
}
vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, simpleVertexShaderCode);
fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, radialBlurFragmentShaderCode);
if (vertexShader != 0 && fragmentShader != 0) {
radialBlurShaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(radialBlurShaderProgram, vertexShader);
GLES20.glAttachShader(radialBlurShaderProgram, fragmentShader);
GLES20.glBindAttribLocation(radialBlurShaderProgram, 0, "position");
GLES20.glBindAttribLocation(radialBlurShaderProgram, 1, "inputTexCoord");
GLES20.glLinkProgram(radialBlurShaderProgram);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(radialBlurShaderProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
GLES20.glDeleteProgram(radialBlurShaderProgram);
radialBlurShaderProgram = 0;
} else {
radialBlurPositionHandle = GLES20.glGetAttribLocation(radialBlurShaderProgram, "position");
radialBlurInputTexCoordHandle = GLES20.glGetAttribLocation(radialBlurShaderProgram, "inputTexCoord");
radialBlurSourceImageHandle = GLES20.glGetUniformLocation(radialBlurShaderProgram, "sourceImage");
radialBlurSourceImage2Handle = GLES20.glGetUniformLocation(radialBlurShaderProgram, "inputImageTexture2");
radialBlurExcludeSizeHandle = GLES20.glGetUniformLocation(radialBlurShaderProgram, "excludeSize");
radialBlurExcludePointHandle = GLES20.glGetUniformLocation(radialBlurShaderProgram, "excludePoint");
radialBlurExcludeBlurSizeHandle = GLES20.glGetUniformLocation(radialBlurShaderProgram, "excludeBlurSize");
radialBlurAspectRatioHandle = GLES20.glGetUniformLocation(radialBlurShaderProgram, "aspectRatio");
}
} else {
return false;
}
if (isVideo) {
fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, rgbToHsvFragmentVideoShaderCode);
vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, simpleVertexVideoShaderCode);
} else {
fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, rgbToHsvFragmentShaderCode);
vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, simpleVertexShaderCode);
}
if (vertexShader != 0 && fragmentShader != 0) {
rgbToHsvShaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(rgbToHsvShaderProgram, vertexShader);
GLES20.glAttachShader(rgbToHsvShaderProgram, fragmentShader);
GLES20.glBindAttribLocation(rgbToHsvShaderProgram, 0, "position");
GLES20.glBindAttribLocation(rgbToHsvShaderProgram, 1, "inputTexCoord");
GLES20.glLinkProgram(rgbToHsvShaderProgram);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(rgbToHsvShaderProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
GLES20.glDeleteProgram(rgbToHsvShaderProgram);
rgbToHsvShaderProgram = 0;
} else {
rgbToHsvPositionHandle = GLES20.glGetAttribLocation(rgbToHsvShaderProgram, "position");
rgbToHsvInputTexCoordHandle = GLES20.glGetAttribLocation(rgbToHsvShaderProgram, "inputTexCoord");
rgbToHsvSourceImageHandle = GLES20.glGetUniformLocation(rgbToHsvShaderProgram, "sourceImage");
if (isVideo) {
rgbToHsvMatrixHandle = GLES20.glGetUniformLocation(rgbToHsvShaderProgram, "videoMatrix");
}
}
} else {
return false;
}
vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, simpleVertexShaderCode);
fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, enhanceFragmentShaderCode);
if (vertexShader != 0 && fragmentShader != 0) {
enhanceShaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(enhanceShaderProgram, vertexShader);
GLES20.glAttachShader(enhanceShaderProgram, fragmentShader);
GLES20.glBindAttribLocation(enhanceShaderProgram, 0, "position");
GLES20.glBindAttribLocation(enhanceShaderProgram, 1, "inputTexCoord");
GLES20.glLinkProgram(enhanceShaderProgram);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(enhanceShaderProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
GLES20.glDeleteProgram(enhanceShaderProgram);
enhanceShaderProgram = 0;
} else {
enhancePositionHandle = GLES20.glGetAttribLocation(enhanceShaderProgram, "position");
enhanceInputTexCoordHandle = GLES20.glGetAttribLocation(enhanceShaderProgram, "inputTexCoord");
enhanceSourceImageHandle = GLES20.glGetUniformLocation(enhanceShaderProgram, "sourceImage");
enhanceIntensityHandle = GLES20.glGetUniformLocation(enhanceShaderProgram, "intensity");
enhanceInputImageTexture2Handle = GLES20.glGetUniformLocation(enhanceShaderProgram, "inputImageTexture2");
}
} else {
return false;
}
return true;
}
public void setRenderData(Bitmap currentBitmap, int orientation, int videoTex, int w, int h) {
loadTexture(currentBitmap, orientation, w, h);
videoTexture = videoTex;
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, enhanceTextures[0]);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, renderBufferWidth, renderBufferHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
}
public static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
int[] compileStatus = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
if (compileStatus[0] == 0) {
if (BuildVars.LOGS_ENABLED) {
FileLog.e(GLES20.glGetShaderInfoLog(shader));
}
GLES20.glDeleteShader(shader);
shader = 0;
}
return shader;
}
public void drawEnhancePass() {
boolean updateFrame;
if (isVideo) {
updateFrame = true;
} else {
updateFrame = !hsvGenerated;
}
if (updateFrame) {
GLES20.glUseProgram(rgbToHsvShaderProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
if (isVideo) {
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, videoTexture);
GLES20.glUniformMatrix4fv(rgbToHsvMatrixHandle, 1, false, videoMatrix, 0);
} else {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[1]);
}
GLES20.glUniform1i(rgbToHsvSourceImageHandle, 0);
GLES20.glEnableVertexAttribArray(rgbToHsvInputTexCoordHandle);
GLES20.glVertexAttribPointer(rgbToHsvInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glEnableVertexAttribArray(rgbToHsvPositionHandle);
GLES20.glVertexAttribPointer(rgbToHsvPositionHandle, 2, GLES20.GL_FLOAT, false, 8, isVideo ? vertexInvertBuffer : vertexBuffer);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, enhanceFrameBuffer[0]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, enhanceTextures[0], 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
if (!hsvGenerated) {
int newCapacity = renderBufferWidth * renderBufferHeight * 4;
if (hsvBuffer == null || newCapacity > hsvBuffer.capacity()) {
hsvBuffer = ByteBuffer.allocateDirect(newCapacity);
}
if (cdtBuffer == null) {
cdtBuffer = ByteBuffer.allocateDirect(PGPhotoEnhanceSegments * PGPhotoEnhanceSegments * PGPhotoEnhanceHistogramBins * 4);
}
if (calcBuffer == null) {
calcBuffer = ByteBuffer.allocateDirect(PGPhotoEnhanceSegments * PGPhotoEnhanceSegments * 2 * 4 * (1 + PGPhotoEnhanceHistogramBins));
}
GLES20.glReadPixels(0, 0, renderBufferWidth, renderBufferHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, hsvBuffer);
Utilities.calcCDT(hsvBuffer, renderBufferWidth, renderBufferHeight, cdtBuffer, calcBuffer);
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, enhanceTextures[1]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 256, 16, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, cdtBuffer);
if (!isVideo) {
hsvBuffer = null;
cdtBuffer = null;
calcBuffer = null;
}
hsvGenerated = true;
}
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[1]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[1], 0);
GLES20.glUseProgram(enhanceShaderProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, enhanceTextures[0]);
GLES20.glUniform1i(enhanceSourceImageHandle, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, enhanceTextures[1]);
GLES20.glUniform1i(enhanceInputImageTexture2Handle, 1);
if (delegate == null || delegate.shouldShowOriginal()) {
GLES20.glUniform1f(enhanceIntensityHandle, 0);
} else {
GLES20.glUniform1f(enhanceIntensityHandle, delegate.getEnhanceValue());
}
GLES20.glEnableVertexAttribArray(enhanceInputTexCoordHandle);
GLES20.glVertexAttribPointer(enhanceInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glEnableVertexAttribArray(enhancePositionHandle);
GLES20.glVertexAttribPointer(enhancePositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
public void drawSharpenPass() {
if (isVideo) {
return;
}
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[0]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[0], 0);
GLES20.glUseProgram(sharpenShaderProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[1]);
GLES20.glUniform1i(sharpenSourceImageHandle, 0);
if (delegate == null || delegate.shouldShowOriginal()) {
GLES20.glUniform1f(sharpenHandle, 0);
} else {
GLES20.glUniform1f(sharpenHandle, delegate.getSharpenValue());
}
GLES20.glUniform1f(sharpenWidthHandle, renderBufferWidth);
GLES20.glUniform1f(sharpenHeightHandle, renderBufferHeight);
GLES20.glEnableVertexAttribArray(sharpenInputTexCoordHandle);
GLES20.glVertexAttribPointer(sharpenInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glEnableVertexAttribArray(sharpenPositionHandle);
GLES20.glVertexAttribPointer(sharpenPositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexInvertBuffer);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
public void drawCustomParamsPass() {
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[isVideo ? 0 : 1]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[isVideo ? 0 : 1], 0);
GLES20.glUseProgram(toolsShaderProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[isVideo ? 1 : 0]);
GLES20.glUniform1i(sourceImageHandle, 0);
if (delegate == null || delegate.shouldShowOriginal()) {
GLES20.glUniform1f(shadowsHandle, 1);
GLES20.glUniform1f(highlightsHandle, 1);
GLES20.glUniform1f(exposureHandle, 0);
GLES20.glUniform1f(contrastHandle, 1);
GLES20.glUniform1f(saturationHandle, 1);
GLES20.glUniform1f(warmthHandle, 0);
GLES20.glUniform1f(vignetteHandle, 0);
GLES20.glUniform1f(grainHandle, 0);
GLES20.glUniform1f(fadeAmountHandle, 0);
GLES20.glUniform3f(highlightsTintColorHandle, 0, 0, 0);
GLES20.glUniform1f(highlightsTintIntensityHandle, 0);
GLES20.glUniform3f(shadowsTintColorHandle, 0, 0, 0);
GLES20.glUniform1f(shadowsTintIntensityHandle, 0);
GLES20.glUniform1f(skipToneHandle, 1);
} else {
GLES20.glUniform1f(shadowsHandle, delegate.getShadowsValue());
GLES20.glUniform1f(highlightsHandle, delegate.getHighlightsValue());
GLES20.glUniform1f(exposureHandle, delegate.getExposureValue());
GLES20.glUniform1f(contrastHandle, delegate.getContrastValue());
GLES20.glUniform1f(saturationHandle, delegate.getSaturationValue());
GLES20.glUniform1f(warmthHandle, delegate.getWarmthValue());
GLES20.glUniform1f(vignetteHandle, delegate.getVignetteValue());
GLES20.glUniform1f(grainHandle, delegate.getGrainValue());
GLES20.glUniform1f(fadeAmountHandle, delegate.getFadeValue());
int tintHighlightsColor = delegate.getTintHighlightsColor();
int tintShadowsColor = delegate.getTintShadowsColor();
GLES20.glUniform3f(highlightsTintColorHandle, (tintHighlightsColor >> 16 & 0xff) / 255.0f, (tintHighlightsColor >> 8 & 0xff) / 255.0f, (tintHighlightsColor & 0xff) / 255.0f);
GLES20.glUniform1f(highlightsTintIntensityHandle, delegate.getTintHighlightsIntensityValue());
GLES20.glUniform3f(shadowsTintColorHandle, (tintShadowsColor >> 16 & 0xff) / 255.0f, (tintShadowsColor >> 8 & 0xff) / 255.0f, (tintShadowsColor & 0xff) / 255.0f);
GLES20.glUniform1f(shadowsTintIntensityHandle, delegate.getTintShadowsIntensityValue());
boolean shouldDrawCurvesPass = delegate.shouldDrawCurvesPass();
GLES20.glUniform1f(skipToneHandle, shouldDrawCurvesPass ? 0.0f : 1.0f);
if (shouldDrawCurvesPass) {
ByteBuffer curveBuffer = delegate.fillAndGetCurveBuffer();
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, curveTextures[0]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 200, 1, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, curveBuffer);
GLES20.glUniform1i(curvesImageHandle, 1);
}
}
GLES20.glUniform1f(widthHandle, renderBufferWidth);
GLES20.glUniform1f(heightHandle, renderBufferHeight);
GLES20.glEnableVertexAttribArray(inputTexCoordHandle);
GLES20.glVertexAttribPointer(inputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexInvertBuffer);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
public boolean drawBlurPass() {
int blurType = delegate != null ? delegate.getBlurType() : 0;
if (isVideo || delegate == null || delegate.shouldShowOriginal() || blurType == 0) {
return false;
}
if (needUpdateBlurTexture) {
GLES20.glUseProgram(blurShaderProgram);
GLES20.glUniform1i(blurSourceImageHandle, 0);
GLES20.glEnableVertexAttribArray(blurInputTexCoordHandle);
GLES20.glVertexAttribPointer(blurInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glEnableVertexAttribArray(blurPositionHandle);
GLES20.glVertexAttribPointer(blurPositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexInvertBuffer);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[0]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[0], 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[1]);
GLES20.glUniform1f(blurWidthHandle, 0.0f);
GLES20.glUniform1f(blurHeightHandle, 1.0f / renderBufferHeight);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[2]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[2], 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[0]);
GLES20.glUniform1f(blurWidthHandle, 1.0f / renderBufferWidth);
GLES20.glUniform1f(blurHeightHandle, 0.0f);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
needUpdateBlurTexture = false;
}
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[0]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[0], 0);
if (blurType == 1) {
GLES20.glUseProgram(radialBlurShaderProgram);
GLES20.glUniform1i(radialBlurSourceImageHandle, 0);
GLES20.glUniform1i(radialBlurSourceImage2Handle, 1);
GLES20.glUniform1f(radialBlurExcludeSizeHandle, delegate.getBlurExcludeSize());
GLES20.glUniform1f(radialBlurExcludeBlurSizeHandle, delegate.getBlurExcludeBlurSize());
Point blurExcludePoint = delegate.getBlurExcludePoint();
GLES20.glUniform2f(radialBlurExcludePointHandle, blurExcludePoint.x, blurExcludePoint.y);
GLES20.glUniform1f(radialBlurAspectRatioHandle, (float) renderBufferHeight / (float) renderBufferWidth);
GLES20.glEnableVertexAttribArray(radialBlurInputTexCoordHandle);
GLES20.glVertexAttribPointer(radialBlurInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glEnableVertexAttribArray(radialBlurPositionHandle);
GLES20.glVertexAttribPointer(radialBlurPositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexInvertBuffer);
} else if (blurType == 2) {
GLES20.glUseProgram(linearBlurShaderProgram);
GLES20.glUniform1i(linearBlurSourceImageHandle, 0);
GLES20.glUniform1i(linearBlurSourceImage2Handle, 1);
GLES20.glUniform1f(linearBlurExcludeSizeHandle, delegate.getBlurExcludeSize());
GLES20.glUniform1f(linearBlurExcludeBlurSizeHandle, delegate.getBlurExcludeBlurSize());
GLES20.glUniform1f(linearBlurAngleHandle, delegate.getBlurAngle());
Point blurExcludePoint = delegate.getBlurExcludePoint();
GLES20.glUniform2f(linearBlurExcludePointHandle, blurExcludePoint.x, blurExcludePoint.y);
GLES20.glUniform1f(linearBlurAspectRatioHandle, (float) renderBufferHeight / (float) renderBufferWidth);
GLES20.glEnableVertexAttribArray(linearBlurInputTexCoordHandle);
GLES20.glVertexAttribPointer(linearBlurInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glEnableVertexAttribArray(linearBlurPositionHandle);
GLES20.glVertexAttribPointer(linearBlurPositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexInvertBuffer);
}
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[1]);
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[2]);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
return true;
}
public void onVideoFrameUpdate(float[] m) {
videoMatrix = m;
//videoFramesCount++;
hsvGenerated = false;
/*if (videoFramesCount >= 30) {
hsvGenerated = false;
videoFramesCount = 0;
}*/
}
private Bitmap createBitmap(Bitmap bitmap, int orientation, int w, int h, float scale) {
Matrix matrix = new Matrix();
matrix.setScale(scale, scale);
matrix.postRotate(orientation);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
private void loadTexture(Bitmap bitmap, int orientation, int w, int h) {
renderBufferWidth = w;
renderBufferHeight = h;
if (renderFrameBuffer == null) {
renderFrameBuffer = new int[3];
GLES20.glGenFramebuffers(3, renderFrameBuffer, 0);
GLES20.glGenTextures(3, renderTexture, 0);
}
if (bitmap != null && !bitmap.isRecycled()) {
float maxSize = AndroidUtilities.getPhotoSize();
if (renderBufferWidth > maxSize || renderBufferHeight > maxSize || orientation % 360 != 0) {
float scale = 1;
if (renderBufferWidth > maxSize || renderBufferHeight > maxSize) {
float scaleX = maxSize / bitmap.getWidth();
float scaleY = maxSize / bitmap.getHeight();
if (scaleX < scaleY) {
renderBufferWidth = (int) maxSize;
renderBufferHeight = (int) (bitmap.getHeight() * scaleX);
scale = scaleX;
} else {
renderBufferHeight = (int) maxSize;
renderBufferWidth = (int) (bitmap.getWidth() * scaleY);
scale = scaleY;
}
}
if (orientation % 360 == 90 || orientation % 360 == 270) {
int temp = renderBufferWidth;
renderBufferWidth = renderBufferHeight;
renderBufferHeight = temp;
}
bitmap = createBitmap(bitmap, orientation, renderBufferWidth, renderBufferHeight, scale);
}
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, renderTexture[1]);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
} else {
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, renderTexture[1]);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, renderBufferWidth, renderBufferHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
}
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[0]);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, renderBufferWidth, renderBufferHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[2]);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, renderBufferWidth, renderBufferHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
}
public FloatBuffer getTextureBuffer() {
return textureBuffer;
}
public FloatBuffer getVertexBuffer() {
return vertexBuffer;
}
public FloatBuffer getVertexInvertBuffer() {
return vertexInvertBuffer;
}
public int getRenderBufferWidth() {
return renderBufferWidth;
}
public int getRenderBufferHeight() {
return renderBufferHeight;
}
public int getRenderTexture(int index) {
if (isVideo) {
return renderTexture[index == 0 ? 1 : 0];
}
return renderTexture[index];
}
public int getRenderFrameBuffer() {
return renderFrameBuffer != null ? renderFrameBuffer[isVideo ? 0 : 1] : 0;
}
public void requestUpdateBlurTexture() {
needUpdateBlurTexture = true;
}
public static FilterShadersDelegate getFilterShadersDelegate(MediaController.SavedFilterState lastState) {
return new FilterShadersDelegate() {
@Override
public boolean shouldShowOriginal() {
return false;
}
@Override
public float getShadowsValue() {
return (lastState.shadowsValue * 0.55f + 100.0f) / 100.0f;
}
@Override
public float getHighlightsValue() {
return (lastState.highlightsValue * 0.75f + 100.0f) / 100.0f;
}
@Override
public float getEnhanceValue() {
return (lastState.enhanceValue / 100.0f);
}
@Override
public float getExposureValue() {
return (lastState.exposureValue / 100.0f);
}
@Override
public float getContrastValue() {
return (lastState.contrastValue / 100.0f) * 0.3f + 1;
}
@Override
public float getWarmthValue() {
return lastState.warmthValue / 100.0f;
}
@Override
public float getVignetteValue() {
return lastState.vignetteValue / 100.0f;
}
@Override
public float getSharpenValue() {
return 0.11f + lastState.sharpenValue / 100.0f * 0.6f;
}
@Override
public float getGrainValue() {
return lastState.grainValue / 100.0f * 0.04f;
}
@Override
public float getFadeValue() {
return lastState.fadeValue / 100.0f;
}
@Override
public float getTintHighlightsIntensityValue() {
float tintHighlightsIntensity = 50.0f;
return lastState.tintHighlightsColor == 0 ? 0 : tintHighlightsIntensity / 100.0f;
}
@Override
public float getTintShadowsIntensityValue() {
float tintShadowsIntensity = 50.0f;
return lastState.tintShadowsColor == 0 ? 0 : tintShadowsIntensity / 100.0f;
}
@Override
public float getSaturationValue() {
float parameterValue = (lastState.saturationValue / 100.0f);
if (parameterValue > 0) {
parameterValue *= 1.05f;
}
return parameterValue + 1;
}
@Override
public int getTintHighlightsColor() {
return lastState.tintHighlightsColor;
}
@Override
public int getTintShadowsColor() {
return lastState.tintShadowsColor;
}
@Override
public int getBlurType() {
return lastState.blurType;
}
@Override
public float getBlurExcludeSize() {
return lastState.blurExcludeSize;
}
@Override
public float getBlurExcludeBlurSize() {
return lastState.blurExcludeBlurSize;
}
@Override
public float getBlurAngle() {
return lastState.blurAngle;
}
@Override
public Point getBlurExcludePoint() {
return lastState.blurExcludePoint;
}
@Override
public boolean shouldDrawCurvesPass() {
return !lastState.curvesToolValue.shouldBeSkipped();
}
@Override
public ByteBuffer fillAndGetCurveBuffer() {
lastState.curvesToolValue.fillBuffer();
return lastState.curvesToolValue.curveBuffer;
}
};
}
}