Closed Amlana closed 10 years ago
Hi Amlana, I write class using .acv.
public class GPUImageToneCurveFilter extends MultiInputFilter { private int[] redPart; private int[] greenPart; private int[] bluePart; private int[] splineTexture;
public GPUImageToneCurveFilter() {
super(2);
}
private void createSplineTexture() {
int[] data = new int[256];
for(int i = 0; i < 256; i++) {
data[i] = (redPart[i] & 0x000000FF) | ((greenPart[i] << 8) & 0x0000FF00) | ((bluePart[i] << 16) & 0x00FF0000) | 0xFF000000;
}
splineTexture = new int[1];
GLES20.glGenTextures(1, splineTexture, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, splineTexture[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 256, 1, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, IntBuffer.wrap(data));
}
@Override
public void destroy() {
super.destroy();
if(splineTexture != null && splineTexture[0] != 0) {
GLES20.glDeleteTextures(1, splineTexture, 0);
splineTexture = null;
}
}
@Override
protected String getFragmentShader() {
return str;
}
String str = " varying highp vec2 "+VARYING_TEXCOORD+";\n" +
" uniform sampler2D "+UNIFORM_TEXTURE0+";\n" +
" uniform sampler2D "+UNIFORM_TEXTUREBASE+1+";\n" +
"\n" +
" void main()\n" +
" {\n" +
" lowp vec4 textureColor = texture2D("+UNIFORM_TEXTURE0+", "+VARYING_TEXCOORD+");\n" +
" lowp float redCurveValue = texture2D("+UNIFORM_TEXTUREBASE+1+", vec2(textureColor.r, 0.0)).r;\n" +
" lowp float greenCurveValue = texture2D("+UNIFORM_TEXTUREBASE+1+", vec2(textureColor.g, 0.0)).g;\n" +
" lowp float blueCurveValue = texture2D("+UNIFORM_TEXTUREBASE+1+", vec2(textureColor.b, 0.0)).b;\n" +
"\n" +
" gl_FragColor = vec4(redCurveValue, greenCurveValue, blueCurveValue, textureColor.a);\n" +
" }";
private float[] getPreparedSpline(Point[] points) {
Arrays.sort(points, new Comparator<Point>() {
@Override
public int compare(Point lhs, Point rhs) {
return lhs.x - rhs.x;
}
});
List<Point> spline = getSplineCurve(points);
// If we have a first point like (0.3, 0) we'll be missing some points at the beginning
// that should be 0.
if(spline.get(0).x > 0) {
for(int i = spline.get(0).x; i >= 0; i--) {
spline.add(0, new Point(i,0));
}
}
// Insert points similarly at the end, if necessary.
if(spline.get(spline.size()-1).x < 255) {
for(int i = spline.get(spline.size()-1).x; i < 256; i++) {
spline.add(new Point(i,255));
}
}
// Prepare the spline points.
float[] preparedSplinePoints = new float[spline.size()];
for (int i=0; i<spline.size(); i++)
{
Point newPoint = spline.get(i);
Point origPoint = new Point(newPoint.x, newPoint.x);
float distance = (float) Math.sqrt(Math.pow((origPoint.x - newPoint.x), 2.0) + Math.pow((origPoint.y - newPoint.y), 2.0));
if (origPoint.y > newPoint.y)
{
distance = -distance;
}
preparedSplinePoints[i] = distance;
}
return preparedSplinePoints;
}
private List<Point> getSplineCurve(Point[] points) {
double[] sdA = secondDerivative(points);
int n = sdA.length;
if (n < 1) {
return null;
}
List<Point> output = new ArrayList<Point>(n+1);
for(int i=0; i<n-1 ; i++) {
Point cur = points[i];
Point next = points[(i+1)];
for(int x=cur.x;x<(int)next.x;x++) {
double t = (double)(x-cur.x)/(next.x-cur.x);
double a = 1-t;
double b = t;
double h = next.x-cur.x;
double y= a*cur.y + b*next.y + (h*h/6)*( (a*a*a-a)*sdA[i]+ (b*b*b-b)*sdA[i+1] );
if (y > 255.0) {
y = 255.0;
} else if (y < 0.0) {
y = 0.0;
}
output.add(new Point(x,(int)y));
}
}
if(output.size() == 255) {
output.add(points[points.length-1]);
}
return output;
}
@Override
public void newTextureReady(int texture, GLTextureOutputRenderer source, boolean newData) {
if(filterLocations.size() < 2 || !source.equals(filterLocations.get(0))) {
clearRegisteredFilterLocations();
registerFilterLocation(source, 0);
registerFilterLocation(this, 1);
}
if(splineTexture == null || splineTexture[0] == 0) {
createSplineTexture();
}
super.newTextureReady(splineTexture[0], this, newData);
super.newTextureReady(texture, source, newData);
}
private double[] secondDerivative(Point[] points) {
int n = points.length;
if (n <= 1) {
return null;
}
double[][] matrix = new double[n][3];
double[] result = new double[n];
matrix[0][1]=1;
// What about matrix[0][1] and matrix[0][0]? Assuming 0 for now (Brad L.)
matrix[0][0]=0;
matrix[0][2]=0;
for(int i=1;i<n-1;i++) {
Point P1 = points[(i-1)];
Point P2 = points[i];
Point P3 = points[(i+1)];
matrix[i][0]=(double)(P2.x-P1.x)/6;
matrix[i][1]=(double)(P3.x-P1.x)/3;
matrix[i][2]=(double)(P3.x-P2.x)/6;
result[i]=(double)(P3.y-P2.y)/(P3.x-P2.x) - (double)(P2.y-P1.y)/(P2.x-P1.x);
}
// What about result[0] and result[n-1]? Assuming 0 for now (Brad L.)
result[0] = 0;
result[n-1] = 0;
matrix[n-1][1]=1;
// What about matrix[n-1][0] and matrix[n-1][2]? For now, assuming they are 0 (Brad L.)
matrix[n-1][0]=0;
matrix[n-1][2]=0;
// solving pass1 (up->down)
for(int i=1;i<n;i++)
{
double k = matrix[i][0]/matrix[i-1][1];
matrix[i][1] -= k*matrix[i-1][2];
matrix[i][0] = 0;
result[i] -= k*result[i-1];
}
// solving pass2 (down->up)
for(int i=n-2;i>=0;i--)
{
double k = matrix[i][2]/matrix[i+1][1];
matrix[i][1] -= k*matrix[i+1][0];
matrix[i][2] = 0;
result[i] -= k*result[i+1];
}
double[] y2 = new double[n];
for(int i=0;i<n;i++) y2[i]=result[i]/matrix[i][1];
return y2;
}
private Point[] mRgbCompositeControlPoints;
private Point[] mRedControlPoints;
private Point[] mGreenControlPoints;
private Point[] mBlueControlPoints;
public void setFromCurveFileInputStream(InputStream input) {
try {
int version = readShort(input);
int totalCurves = readShort(input);
ArrayList<Point[]> curves = new ArrayList<Point[]>(totalCurves);
// float pointRate = 1.0f / 255;
for (int i = 0; i < totalCurves; i++) {
// 2 bytes, Count of points in the curve (short integer from 2...19)
short pointCount = readShort(input);
Point[] points = new Point[pointCount];
// point count * 4
// Curve points. Each curve point is a pair of short integers where
// the first number is the output value (vertical coordinate on the
// Curves dialog graph) and the second is the input value. All coordinates have range 0 to 255.
for (int j = 0; j < pointCount; j++) {
short y = readShort(input);
short x = readShort(input);
points[j] = new Point(x , y );
}
curves.add(points);
}
input.close();
mRgbCompositeControlPoints = curves.get(0);
mRedControlPoints = curves.get(1);
mGreenControlPoints = curves.get(2);
mBlueControlPoints = curves.get(3);
System.out.println(" RGB = "+mRedControlPoints.length + " ");
for(int i = 0 ; i < mRgbCompositeControlPoints.length; i++){
System.out.println("XRBG = "+mRgbCompositeControlPoints[i].x+" || YRGB = "+mRgbCompositeControlPoints[i].y);
}
for(int i = 0 ; i < mRedControlPoints.length; i++){
System.out.println("XRED = "+mRedControlPoints[i].x+" || YRED = "+mRedControlPoints[i].y);
}
for(int i = 0 ; i < mGreenControlPoints.length; i++){
System.out.println("XGR = "+mGreenControlPoints[i].x+" || YGR = "+mGreenControlPoints[i].y);
}
for(int i = 0 ; i < mBlueControlPoints.length; i++){
System.out.println("XBLU = "+mBlueControlPoints[i].x+" || YBLU = "+mBlueControlPoints[i].y);
}
float[] redCurve = getPreparedSpline(mRedControlPoints);
float[] blueCurve = getPreparedSpline(mBlueControlPoints);
float[] greenCurve = getPreparedSpline(mGreenControlPoints);
float[] rgbCompositeCurve = getPreparedSpline(mRgbCompositeControlPoints);
redPart = new int[256];
greenPart = new int[256];
bluePart = new int[256];
for (int i = 0; i < 256; i++) {
redPart[i] = (int) Math.min(Math.max(i + redCurve[i] + rgbCompositeCurve[i], 0), 255);
greenPart[i] = (int) Math.min(Math.max(i + greenCurve[i] + rgbCompositeCurve[i], 0), 255);
bluePart[i] = (int) Math.min(Math.max(i + blueCurve[i] + rgbCompositeCurve[i], 0), 255);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private short readShort(InputStream input) throws IOException {
return (short) (input.read() << 8 | input.read());
}
}
Using:
InputStream in = getResources().openRawResource(R.raw.autumn2); filter = new GPUImageToneCurveFilter(); ((GPUImageToneCurveFilter) filter).setFromCurveFileInputStream(in);
I hope help you!
Thanks a lot truongnguyenptit
Hi Chrisbatt, I want to apply filter from a .acv file. How can i do that?