How do I “subtract” a color filter using GPUImageLibrary?












46















Currently the BlendModes (Subtract, Exclusion, etc.) use the LauncherImage as the mask. Can I apply these BlendModes to a ColorMatrix?



I'm using the GPUImageLibrary:



colorMatrix[
0.393, 0.7689999, 0.18899999, 0, 0,
0.349, 0.6859999, 0.16799999, 0, 0,
0.272, 0.5339999, 0.13099999, 0, 0,
0, 0, 0, 1, 0];


SubtractBlendFilter.java



public class GPUImageSubtractBlendFilter extends GPUImageTwoInputFilter {
public static final String SUBTRACT_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;n" +
" varying highp vec2 textureCoordinate2;n" +
"n" +
" uniform sampler2D inputImageTexture;n" +
" uniform sampler2D inputImageTexture2;n" +
" n" +
" void main()n" +
" {n" +
" lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);n" +
" lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);n" +
"n" +
" gl_FragColor = vec4(textureColor.rgb - textureColor2.rgb, textureColor.a);n" +
" }";

public GPUImageSubtractBlendFilter() {
super(SUBTRACT_BLEND_FRAGMENT_SHADER);
}
}


GPUIMageTwoInputFilter.java



public class GPUImageTwoInputFilter extends GPUImageFilter {
private static final String VERTEX_SHADER = "attribute vec4 position;n" +
"attribute vec4 inputTextureCoordinate;n" +
"attribute vec4 inputTextureCoordinate2;n" +
" n" +
"varying vec2 textureCoordinate;n" +
"varying vec2 textureCoordinate2;n" +
" n" +
"void main()n" +
"{n" +
" gl_Position = position;n" +
" textureCoordinate = inputTextureCoordinate.xy;n" +
" textureCoordinate2 = inputTextureCoordinate2.xy;n" +
"}";

public int mFilterSecondTextureCoordinateAttribute;
public int mFilterInputTextureUniform2;
public int mFilterSourceTexture2 = OpenGlUtils.NO_TEXTURE;
private ByteBuffer mTexture2CoordinatesBuffer;
private Bitmap mBitmap;

public GPUImageTwoInputFilter(String fragmentShader) {
this(VERTEX_SHADER, fragmentShader);
}

public GPUImageTwoInputFilter(String vertexShader, String fragmentShader) {
super(vertexShader, fragmentShader);
setRotation(Rotation.NORMAL, false, false);
}

@Override
public void onInit() {
super.onInit();

mFilterSecondTextureCoordinateAttribute = GLES20.glGetAttribLocation(getProgram(), "inputTextureCoordinate2");
mFilterInputTextureUniform2 = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture2"); // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader
GLES20.glEnableVertexAttribArray(mFilterSecondTextureCoordinateAttribute);

if (mBitmap != null&&!mBitmap.isRecycled()) {
setBitmap(mBitmap);
}
}

public void setBitmap(final Bitmap bitmap) {
if (bitmap != null && bitmap.isRecycled()) {
return;
}
mBitmap = bitmap;
if (mBitmap == null) {
return;
}
runOnDraw(new Runnable() {
public void run() {
if (mFilterSourceTexture2 == OpenGlUtils.NO_TEXTURE) {
if (bitmap == null || bitmap.isRecycled()) {
return;
}
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
mFilterSourceTexture2 = OpenGlUtils.loadTexture(bitmap, OpenGlUtils.NO_TEXTURE, false);
}
}
});
}

public Bitmap getBitmap() {
return mBitmap;
}

public void recycleBitmap() {
if (mBitmap != null && !mBitmap.isRecycled()) {
mBitmap.recycle();
mBitmap = null;
}
}

public void onDestroy() {
super.onDestroy();
GLES20.glDeleteTextures(1, new int{
mFilterSourceTexture2
}, 0);
mFilterSourceTexture2 = OpenGlUtils.NO_TEXTURE;
}

@Override
protected void onDrawArraysPre() {
GLES20.glEnableVertexAttribArray(mFilterSecondTextureCoordinateAttribute);
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFilterSourceTexture2);
GLES20.glUniform1i(mFilterInputTextureUniform2, 3);

mTexture2CoordinatesBuffer.position(0);
GLES20.glVertexAttribPointer(mFilterSecondTextureCoordinateAttribute, 2, GLES20.GL_FLOAT, false, 0, mTexture2CoordinatesBuffer);
}

public void setRotation(final Rotation rotation, final boolean flipHorizontal, final boolean flipVertical) {
float buffer = TextureRotationUtil.getRotation(rotation, flipHorizontal, flipVertical);

ByteBuffer bBuffer = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder());
FloatBuffer fBuffer = bBuffer.asFloatBuffer();
fBuffer.put(buffer);
fBuffer.flip();

mTexture2CoordinatesBuffer = bBuffer;
}
}


My guess it involves changing something with String SUBTRACT_BLEND_GRAGMENT_SHADER & String VERTEX_SHADER .










share|improve this question




















  • 1





    Sorry for my misunderstanding, but could you, please, provide what data do you have as input and what do you want to receive as output?

    – Michael Spitsin
    Jul 18 '16 at 17:18






  • 1





    Hi. I have a bitmap as the input and the final output should also be a bitmap

    – Zen
    Jul 27 '16 at 12:12






  • 1





    What exactly are you trying to achieve? I tried reading your question ew times, but not able to understand the requirement.

    – codetiger
    Aug 15 '16 at 11:34
















46















Currently the BlendModes (Subtract, Exclusion, etc.) use the LauncherImage as the mask. Can I apply these BlendModes to a ColorMatrix?



I'm using the GPUImageLibrary:



colorMatrix[
0.393, 0.7689999, 0.18899999, 0, 0,
0.349, 0.6859999, 0.16799999, 0, 0,
0.272, 0.5339999, 0.13099999, 0, 0,
0, 0, 0, 1, 0];


SubtractBlendFilter.java



public class GPUImageSubtractBlendFilter extends GPUImageTwoInputFilter {
public static final String SUBTRACT_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;n" +
" varying highp vec2 textureCoordinate2;n" +
"n" +
" uniform sampler2D inputImageTexture;n" +
" uniform sampler2D inputImageTexture2;n" +
" n" +
" void main()n" +
" {n" +
" lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);n" +
" lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);n" +
"n" +
" gl_FragColor = vec4(textureColor.rgb - textureColor2.rgb, textureColor.a);n" +
" }";

public GPUImageSubtractBlendFilter() {
super(SUBTRACT_BLEND_FRAGMENT_SHADER);
}
}


GPUIMageTwoInputFilter.java



public class GPUImageTwoInputFilter extends GPUImageFilter {
private static final String VERTEX_SHADER = "attribute vec4 position;n" +
"attribute vec4 inputTextureCoordinate;n" +
"attribute vec4 inputTextureCoordinate2;n" +
" n" +
"varying vec2 textureCoordinate;n" +
"varying vec2 textureCoordinate2;n" +
" n" +
"void main()n" +
"{n" +
" gl_Position = position;n" +
" textureCoordinate = inputTextureCoordinate.xy;n" +
" textureCoordinate2 = inputTextureCoordinate2.xy;n" +
"}";

public int mFilterSecondTextureCoordinateAttribute;
public int mFilterInputTextureUniform2;
public int mFilterSourceTexture2 = OpenGlUtils.NO_TEXTURE;
private ByteBuffer mTexture2CoordinatesBuffer;
private Bitmap mBitmap;

public GPUImageTwoInputFilter(String fragmentShader) {
this(VERTEX_SHADER, fragmentShader);
}

public GPUImageTwoInputFilter(String vertexShader, String fragmentShader) {
super(vertexShader, fragmentShader);
setRotation(Rotation.NORMAL, false, false);
}

@Override
public void onInit() {
super.onInit();

mFilterSecondTextureCoordinateAttribute = GLES20.glGetAttribLocation(getProgram(), "inputTextureCoordinate2");
mFilterInputTextureUniform2 = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture2"); // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader
GLES20.glEnableVertexAttribArray(mFilterSecondTextureCoordinateAttribute);

if (mBitmap != null&&!mBitmap.isRecycled()) {
setBitmap(mBitmap);
}
}

public void setBitmap(final Bitmap bitmap) {
if (bitmap != null && bitmap.isRecycled()) {
return;
}
mBitmap = bitmap;
if (mBitmap == null) {
return;
}
runOnDraw(new Runnable() {
public void run() {
if (mFilterSourceTexture2 == OpenGlUtils.NO_TEXTURE) {
if (bitmap == null || bitmap.isRecycled()) {
return;
}
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
mFilterSourceTexture2 = OpenGlUtils.loadTexture(bitmap, OpenGlUtils.NO_TEXTURE, false);
}
}
});
}

public Bitmap getBitmap() {
return mBitmap;
}

public void recycleBitmap() {
if (mBitmap != null && !mBitmap.isRecycled()) {
mBitmap.recycle();
mBitmap = null;
}
}

public void onDestroy() {
super.onDestroy();
GLES20.glDeleteTextures(1, new int{
mFilterSourceTexture2
}, 0);
mFilterSourceTexture2 = OpenGlUtils.NO_TEXTURE;
}

@Override
protected void onDrawArraysPre() {
GLES20.glEnableVertexAttribArray(mFilterSecondTextureCoordinateAttribute);
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFilterSourceTexture2);
GLES20.glUniform1i(mFilterInputTextureUniform2, 3);

mTexture2CoordinatesBuffer.position(0);
GLES20.glVertexAttribPointer(mFilterSecondTextureCoordinateAttribute, 2, GLES20.GL_FLOAT, false, 0, mTexture2CoordinatesBuffer);
}

public void setRotation(final Rotation rotation, final boolean flipHorizontal, final boolean flipVertical) {
float buffer = TextureRotationUtil.getRotation(rotation, flipHorizontal, flipVertical);

ByteBuffer bBuffer = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder());
FloatBuffer fBuffer = bBuffer.asFloatBuffer();
fBuffer.put(buffer);
fBuffer.flip();

mTexture2CoordinatesBuffer = bBuffer;
}
}


My guess it involves changing something with String SUBTRACT_BLEND_GRAGMENT_SHADER & String VERTEX_SHADER .










share|improve this question




















  • 1





    Sorry for my misunderstanding, but could you, please, provide what data do you have as input and what do you want to receive as output?

    – Michael Spitsin
    Jul 18 '16 at 17:18






  • 1





    Hi. I have a bitmap as the input and the final output should also be a bitmap

    – Zen
    Jul 27 '16 at 12:12






  • 1





    What exactly are you trying to achieve? I tried reading your question ew times, but not able to understand the requirement.

    – codetiger
    Aug 15 '16 at 11:34














46












46








46








Currently the BlendModes (Subtract, Exclusion, etc.) use the LauncherImage as the mask. Can I apply these BlendModes to a ColorMatrix?



I'm using the GPUImageLibrary:



colorMatrix[
0.393, 0.7689999, 0.18899999, 0, 0,
0.349, 0.6859999, 0.16799999, 0, 0,
0.272, 0.5339999, 0.13099999, 0, 0,
0, 0, 0, 1, 0];


SubtractBlendFilter.java



public class GPUImageSubtractBlendFilter extends GPUImageTwoInputFilter {
public static final String SUBTRACT_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;n" +
" varying highp vec2 textureCoordinate2;n" +
"n" +
" uniform sampler2D inputImageTexture;n" +
" uniform sampler2D inputImageTexture2;n" +
" n" +
" void main()n" +
" {n" +
" lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);n" +
" lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);n" +
"n" +
" gl_FragColor = vec4(textureColor.rgb - textureColor2.rgb, textureColor.a);n" +
" }";

public GPUImageSubtractBlendFilter() {
super(SUBTRACT_BLEND_FRAGMENT_SHADER);
}
}


GPUIMageTwoInputFilter.java



public class GPUImageTwoInputFilter extends GPUImageFilter {
private static final String VERTEX_SHADER = "attribute vec4 position;n" +
"attribute vec4 inputTextureCoordinate;n" +
"attribute vec4 inputTextureCoordinate2;n" +
" n" +
"varying vec2 textureCoordinate;n" +
"varying vec2 textureCoordinate2;n" +
" n" +
"void main()n" +
"{n" +
" gl_Position = position;n" +
" textureCoordinate = inputTextureCoordinate.xy;n" +
" textureCoordinate2 = inputTextureCoordinate2.xy;n" +
"}";

public int mFilterSecondTextureCoordinateAttribute;
public int mFilterInputTextureUniform2;
public int mFilterSourceTexture2 = OpenGlUtils.NO_TEXTURE;
private ByteBuffer mTexture2CoordinatesBuffer;
private Bitmap mBitmap;

public GPUImageTwoInputFilter(String fragmentShader) {
this(VERTEX_SHADER, fragmentShader);
}

public GPUImageTwoInputFilter(String vertexShader, String fragmentShader) {
super(vertexShader, fragmentShader);
setRotation(Rotation.NORMAL, false, false);
}

@Override
public void onInit() {
super.onInit();

mFilterSecondTextureCoordinateAttribute = GLES20.glGetAttribLocation(getProgram(), "inputTextureCoordinate2");
mFilterInputTextureUniform2 = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture2"); // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader
GLES20.glEnableVertexAttribArray(mFilterSecondTextureCoordinateAttribute);

if (mBitmap != null&&!mBitmap.isRecycled()) {
setBitmap(mBitmap);
}
}

public void setBitmap(final Bitmap bitmap) {
if (bitmap != null && bitmap.isRecycled()) {
return;
}
mBitmap = bitmap;
if (mBitmap == null) {
return;
}
runOnDraw(new Runnable() {
public void run() {
if (mFilterSourceTexture2 == OpenGlUtils.NO_TEXTURE) {
if (bitmap == null || bitmap.isRecycled()) {
return;
}
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
mFilterSourceTexture2 = OpenGlUtils.loadTexture(bitmap, OpenGlUtils.NO_TEXTURE, false);
}
}
});
}

public Bitmap getBitmap() {
return mBitmap;
}

public void recycleBitmap() {
if (mBitmap != null && !mBitmap.isRecycled()) {
mBitmap.recycle();
mBitmap = null;
}
}

public void onDestroy() {
super.onDestroy();
GLES20.glDeleteTextures(1, new int{
mFilterSourceTexture2
}, 0);
mFilterSourceTexture2 = OpenGlUtils.NO_TEXTURE;
}

@Override
protected void onDrawArraysPre() {
GLES20.glEnableVertexAttribArray(mFilterSecondTextureCoordinateAttribute);
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFilterSourceTexture2);
GLES20.glUniform1i(mFilterInputTextureUniform2, 3);

mTexture2CoordinatesBuffer.position(0);
GLES20.glVertexAttribPointer(mFilterSecondTextureCoordinateAttribute, 2, GLES20.GL_FLOAT, false, 0, mTexture2CoordinatesBuffer);
}

public void setRotation(final Rotation rotation, final boolean flipHorizontal, final boolean flipVertical) {
float buffer = TextureRotationUtil.getRotation(rotation, flipHorizontal, flipVertical);

ByteBuffer bBuffer = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder());
FloatBuffer fBuffer = bBuffer.asFloatBuffer();
fBuffer.put(buffer);
fBuffer.flip();

mTexture2CoordinatesBuffer = bBuffer;
}
}


My guess it involves changing something with String SUBTRACT_BLEND_GRAGMENT_SHADER & String VERTEX_SHADER .










share|improve this question
















Currently the BlendModes (Subtract, Exclusion, etc.) use the LauncherImage as the mask. Can I apply these BlendModes to a ColorMatrix?



I'm using the GPUImageLibrary:



colorMatrix[
0.393, 0.7689999, 0.18899999, 0, 0,
0.349, 0.6859999, 0.16799999, 0, 0,
0.272, 0.5339999, 0.13099999, 0, 0,
0, 0, 0, 1, 0];


SubtractBlendFilter.java



public class GPUImageSubtractBlendFilter extends GPUImageTwoInputFilter {
public static final String SUBTRACT_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;n" +
" varying highp vec2 textureCoordinate2;n" +
"n" +
" uniform sampler2D inputImageTexture;n" +
" uniform sampler2D inputImageTexture2;n" +
" n" +
" void main()n" +
" {n" +
" lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);n" +
" lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);n" +
"n" +
" gl_FragColor = vec4(textureColor.rgb - textureColor2.rgb, textureColor.a);n" +
" }";

public GPUImageSubtractBlendFilter() {
super(SUBTRACT_BLEND_FRAGMENT_SHADER);
}
}


GPUIMageTwoInputFilter.java



public class GPUImageTwoInputFilter extends GPUImageFilter {
private static final String VERTEX_SHADER = "attribute vec4 position;n" +
"attribute vec4 inputTextureCoordinate;n" +
"attribute vec4 inputTextureCoordinate2;n" +
" n" +
"varying vec2 textureCoordinate;n" +
"varying vec2 textureCoordinate2;n" +
" n" +
"void main()n" +
"{n" +
" gl_Position = position;n" +
" textureCoordinate = inputTextureCoordinate.xy;n" +
" textureCoordinate2 = inputTextureCoordinate2.xy;n" +
"}";

public int mFilterSecondTextureCoordinateAttribute;
public int mFilterInputTextureUniform2;
public int mFilterSourceTexture2 = OpenGlUtils.NO_TEXTURE;
private ByteBuffer mTexture2CoordinatesBuffer;
private Bitmap mBitmap;

public GPUImageTwoInputFilter(String fragmentShader) {
this(VERTEX_SHADER, fragmentShader);
}

public GPUImageTwoInputFilter(String vertexShader, String fragmentShader) {
super(vertexShader, fragmentShader);
setRotation(Rotation.NORMAL, false, false);
}

@Override
public void onInit() {
super.onInit();

mFilterSecondTextureCoordinateAttribute = GLES20.glGetAttribLocation(getProgram(), "inputTextureCoordinate2");
mFilterInputTextureUniform2 = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture2"); // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader
GLES20.glEnableVertexAttribArray(mFilterSecondTextureCoordinateAttribute);

if (mBitmap != null&&!mBitmap.isRecycled()) {
setBitmap(mBitmap);
}
}

public void setBitmap(final Bitmap bitmap) {
if (bitmap != null && bitmap.isRecycled()) {
return;
}
mBitmap = bitmap;
if (mBitmap == null) {
return;
}
runOnDraw(new Runnable() {
public void run() {
if (mFilterSourceTexture2 == OpenGlUtils.NO_TEXTURE) {
if (bitmap == null || bitmap.isRecycled()) {
return;
}
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
mFilterSourceTexture2 = OpenGlUtils.loadTexture(bitmap, OpenGlUtils.NO_TEXTURE, false);
}
}
});
}

public Bitmap getBitmap() {
return mBitmap;
}

public void recycleBitmap() {
if (mBitmap != null && !mBitmap.isRecycled()) {
mBitmap.recycle();
mBitmap = null;
}
}

public void onDestroy() {
super.onDestroy();
GLES20.glDeleteTextures(1, new int{
mFilterSourceTexture2
}, 0);
mFilterSourceTexture2 = OpenGlUtils.NO_TEXTURE;
}

@Override
protected void onDrawArraysPre() {
GLES20.glEnableVertexAttribArray(mFilterSecondTextureCoordinateAttribute);
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFilterSourceTexture2);
GLES20.glUniform1i(mFilterInputTextureUniform2, 3);

mTexture2CoordinatesBuffer.position(0);
GLES20.glVertexAttribPointer(mFilterSecondTextureCoordinateAttribute, 2, GLES20.GL_FLOAT, false, 0, mTexture2CoordinatesBuffer);
}

public void setRotation(final Rotation rotation, final boolean flipHorizontal, final boolean flipVertical) {
float buffer = TextureRotationUtil.getRotation(rotation, flipHorizontal, flipVertical);

ByteBuffer bBuffer = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder());
FloatBuffer fBuffer = bBuffer.asFloatBuffer();
fBuffer.put(buffer);
fBuffer.flip();

mTexture2CoordinatesBuffer = bBuffer;
}
}


My guess it involves changing something with String SUBTRACT_BLEND_GRAGMENT_SHADER & String VERTEX_SHADER .







java android opengl-es gpuimage






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 1 at 5:34









Peter Mortensen

13.7k1986113




13.7k1986113










asked Oct 27 '15 at 0:57









ZenZen

1,27911636




1,27911636








  • 1





    Sorry for my misunderstanding, but could you, please, provide what data do you have as input and what do you want to receive as output?

    – Michael Spitsin
    Jul 18 '16 at 17:18






  • 1





    Hi. I have a bitmap as the input and the final output should also be a bitmap

    – Zen
    Jul 27 '16 at 12:12






  • 1





    What exactly are you trying to achieve? I tried reading your question ew times, but not able to understand the requirement.

    – codetiger
    Aug 15 '16 at 11:34














  • 1





    Sorry for my misunderstanding, but could you, please, provide what data do you have as input and what do you want to receive as output?

    – Michael Spitsin
    Jul 18 '16 at 17:18






  • 1





    Hi. I have a bitmap as the input and the final output should also be a bitmap

    – Zen
    Jul 27 '16 at 12:12






  • 1





    What exactly are you trying to achieve? I tried reading your question ew times, but not able to understand the requirement.

    – codetiger
    Aug 15 '16 at 11:34








1




1





Sorry for my misunderstanding, but could you, please, provide what data do you have as input and what do you want to receive as output?

– Michael Spitsin
Jul 18 '16 at 17:18





Sorry for my misunderstanding, but could you, please, provide what data do you have as input and what do you want to receive as output?

– Michael Spitsin
Jul 18 '16 at 17:18




1




1





Hi. I have a bitmap as the input and the final output should also be a bitmap

– Zen
Jul 27 '16 at 12:12





Hi. I have a bitmap as the input and the final output should also be a bitmap

– Zen
Jul 27 '16 at 12:12




1




1





What exactly are you trying to achieve? I tried reading your question ew times, but not able to understand the requirement.

– codetiger
Aug 15 '16 at 11:34





What exactly are you trying to achieve? I tried reading your question ew times, but not able to understand the requirement.

– codetiger
Aug 15 '16 at 11:34












2 Answers
2






active

oldest

votes


















2














Color matrix is the entity that defines new color component values for some pixel as linear functions of the current color components of the same pixel. I.e. the only input for color matrix conversion is the pixel, which colors should be transformed. There is no way to involve another pixels to such conversion. Regardless if they are pixels from another image or even neighbors of transformed pixel - it is impossible.






share|improve this answer































    2














    Disclaimer



    Originally I answered another question from the same author and it seems was asked within the same problem. I decided not to mark this one as a duplicate, because the first question doesn't have context of using the GPUImageLibrary, which makes the things way simpler. However I don't want to overact, so if you need any additional details, please refer to the original answer. Here I'll merely outline the solution.





    You don't actually need to extend the GPUImageSubtractBlendFilter or any descendants of the GPUImageTwoInputFilter, because (as correctly was noted by Sergio) you should deal with only one instance of texture. Instead define your own fragment shader that will take a color filter, apply it and subtract the resulting
    value from original pixel:



    precision mediump float;
    struct ColorFilter {
    mat4 factor;
    vec4 shift;
    };
    uniform sampler2D inputImageTexture;
    uniform ColorFilter uColorFilter;
    varying vec2 textureCoordinate;
    void main() {
    vec4 originalColor = texture2D(inputImageTexture, textureCoordinate);
    originalColor.rgb *= originalColor.a;
    vec4 filteredColor = (originalColor * uColorFilter.factor) + uColorFilter.shift;
    filteredColor.rgb *= filteredColor.a;
    gl_FragColor = vec4(originalColor.rgb - filteredColor.rgb, originalColor.a);
    }


    And now just attach your color filter matrix to the shader:



    @Override
    public void onInitialized() {
    super.onInitialized();
    attachColorFilter(getProgram());
    }

    // ========================================== //
    // Private
    // ========================================== //

    private void attachColorFilter(int program) {
    final float colorFilterFactor = new float[4 * 4];
    final float colorFilterShift = new float[4];
    for (int i = 0; i < mColorFilter.length; i++) {
    final float value = mColorFilter[i];
    final int calculateIndex = i + 1;
    if (calculateIndex % 5 == 0) {
    colorFilterShift[calculateIndex / 5 - 1] = value / 255;
    } else {
    colorFilterFactor[i - calculateIndex / 5] = value;
    }
    }
    final int colorFactorLocation = GLES20.glGetUniformLocation(program,
    "uColorFilter.factor");
    setUniformMatrix4f(colorFactorLocation, colorFilterFactor);
    final int colorShiftLocation = GLES20.glGetUniformLocation(program,
    "uColorFilter.shift");
    setFloatVec4(colorShiftLocation, colorFilterShift);
    }


    Feel free to use the gist with the working subclass. Just instantiate it and pass to the GPUImageView:



    mBlendedImageView.setFilter(new ColorMatrixSubtractFilter(new float {
    0.393f, 0.7689999f, 0.18899999f, 0, 0,
    0.349f, 0.6859999f, 0.16799999f, 0, 0,
    0.272f, 0.5339999f, 0.13099999f, 0, 0,
    0, 0, 0, 1, 0
    }));


    On the right you can see the output of subtracted filter applied to the image on the left:



    Blended image






    share|improve this answer

























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f33358248%2fhow-do-i-subtract-a-color-filter-using-gpuimagelibrary%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      2














      Color matrix is the entity that defines new color component values for some pixel as linear functions of the current color components of the same pixel. I.e. the only input for color matrix conversion is the pixel, which colors should be transformed. There is no way to involve another pixels to such conversion. Regardless if they are pixels from another image or even neighbors of transformed pixel - it is impossible.






      share|improve this answer




























        2














        Color matrix is the entity that defines new color component values for some pixel as linear functions of the current color components of the same pixel. I.e. the only input for color matrix conversion is the pixel, which colors should be transformed. There is no way to involve another pixels to such conversion. Regardless if they are pixels from another image or even neighbors of transformed pixel - it is impossible.






        share|improve this answer


























          2












          2








          2







          Color matrix is the entity that defines new color component values for some pixel as linear functions of the current color components of the same pixel. I.e. the only input for color matrix conversion is the pixel, which colors should be transformed. There is no way to involve another pixels to such conversion. Regardless if they are pixels from another image or even neighbors of transformed pixel - it is impossible.






          share|improve this answer













          Color matrix is the entity that defines new color component values for some pixel as linear functions of the current color components of the same pixel. I.e. the only input for color matrix conversion is the pixel, which colors should be transformed. There is no way to involve another pixels to such conversion. Regardless if they are pixels from another image or even neighbors of transformed pixel - it is impossible.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Sep 14 '16 at 14:57









          SergioSergio

          6,73021941




          6,73021941

























              2














              Disclaimer



              Originally I answered another question from the same author and it seems was asked within the same problem. I decided not to mark this one as a duplicate, because the first question doesn't have context of using the GPUImageLibrary, which makes the things way simpler. However I don't want to overact, so if you need any additional details, please refer to the original answer. Here I'll merely outline the solution.





              You don't actually need to extend the GPUImageSubtractBlendFilter or any descendants of the GPUImageTwoInputFilter, because (as correctly was noted by Sergio) you should deal with only one instance of texture. Instead define your own fragment shader that will take a color filter, apply it and subtract the resulting
              value from original pixel:



              precision mediump float;
              struct ColorFilter {
              mat4 factor;
              vec4 shift;
              };
              uniform sampler2D inputImageTexture;
              uniform ColorFilter uColorFilter;
              varying vec2 textureCoordinate;
              void main() {
              vec4 originalColor = texture2D(inputImageTexture, textureCoordinate);
              originalColor.rgb *= originalColor.a;
              vec4 filteredColor = (originalColor * uColorFilter.factor) + uColorFilter.shift;
              filteredColor.rgb *= filteredColor.a;
              gl_FragColor = vec4(originalColor.rgb - filteredColor.rgb, originalColor.a);
              }


              And now just attach your color filter matrix to the shader:



              @Override
              public void onInitialized() {
              super.onInitialized();
              attachColorFilter(getProgram());
              }

              // ========================================== //
              // Private
              // ========================================== //

              private void attachColorFilter(int program) {
              final float colorFilterFactor = new float[4 * 4];
              final float colorFilterShift = new float[4];
              for (int i = 0; i < mColorFilter.length; i++) {
              final float value = mColorFilter[i];
              final int calculateIndex = i + 1;
              if (calculateIndex % 5 == 0) {
              colorFilterShift[calculateIndex / 5 - 1] = value / 255;
              } else {
              colorFilterFactor[i - calculateIndex / 5] = value;
              }
              }
              final int colorFactorLocation = GLES20.glGetUniformLocation(program,
              "uColorFilter.factor");
              setUniformMatrix4f(colorFactorLocation, colorFilterFactor);
              final int colorShiftLocation = GLES20.glGetUniformLocation(program,
              "uColorFilter.shift");
              setFloatVec4(colorShiftLocation, colorFilterShift);
              }


              Feel free to use the gist with the working subclass. Just instantiate it and pass to the GPUImageView:



              mBlendedImageView.setFilter(new ColorMatrixSubtractFilter(new float {
              0.393f, 0.7689999f, 0.18899999f, 0, 0,
              0.349f, 0.6859999f, 0.16799999f, 0, 0,
              0.272f, 0.5339999f, 0.13099999f, 0, 0,
              0, 0, 0, 1, 0
              }));


              On the right you can see the output of subtracted filter applied to the image on the left:



              Blended image






              share|improve this answer






























                2














                Disclaimer



                Originally I answered another question from the same author and it seems was asked within the same problem. I decided not to mark this one as a duplicate, because the first question doesn't have context of using the GPUImageLibrary, which makes the things way simpler. However I don't want to overact, so if you need any additional details, please refer to the original answer. Here I'll merely outline the solution.





                You don't actually need to extend the GPUImageSubtractBlendFilter or any descendants of the GPUImageTwoInputFilter, because (as correctly was noted by Sergio) you should deal with only one instance of texture. Instead define your own fragment shader that will take a color filter, apply it and subtract the resulting
                value from original pixel:



                precision mediump float;
                struct ColorFilter {
                mat4 factor;
                vec4 shift;
                };
                uniform sampler2D inputImageTexture;
                uniform ColorFilter uColorFilter;
                varying vec2 textureCoordinate;
                void main() {
                vec4 originalColor = texture2D(inputImageTexture, textureCoordinate);
                originalColor.rgb *= originalColor.a;
                vec4 filteredColor = (originalColor * uColorFilter.factor) + uColorFilter.shift;
                filteredColor.rgb *= filteredColor.a;
                gl_FragColor = vec4(originalColor.rgb - filteredColor.rgb, originalColor.a);
                }


                And now just attach your color filter matrix to the shader:



                @Override
                public void onInitialized() {
                super.onInitialized();
                attachColorFilter(getProgram());
                }

                // ========================================== //
                // Private
                // ========================================== //

                private void attachColorFilter(int program) {
                final float colorFilterFactor = new float[4 * 4];
                final float colorFilterShift = new float[4];
                for (int i = 0; i < mColorFilter.length; i++) {
                final float value = mColorFilter[i];
                final int calculateIndex = i + 1;
                if (calculateIndex % 5 == 0) {
                colorFilterShift[calculateIndex / 5 - 1] = value / 255;
                } else {
                colorFilterFactor[i - calculateIndex / 5] = value;
                }
                }
                final int colorFactorLocation = GLES20.glGetUniformLocation(program,
                "uColorFilter.factor");
                setUniformMatrix4f(colorFactorLocation, colorFilterFactor);
                final int colorShiftLocation = GLES20.glGetUniformLocation(program,
                "uColorFilter.shift");
                setFloatVec4(colorShiftLocation, colorFilterShift);
                }


                Feel free to use the gist with the working subclass. Just instantiate it and pass to the GPUImageView:



                mBlendedImageView.setFilter(new ColorMatrixSubtractFilter(new float {
                0.393f, 0.7689999f, 0.18899999f, 0, 0,
                0.349f, 0.6859999f, 0.16799999f, 0, 0,
                0.272f, 0.5339999f, 0.13099999f, 0, 0,
                0, 0, 0, 1, 0
                }));


                On the right you can see the output of subtracted filter applied to the image on the left:



                Blended image






                share|improve this answer




























                  2












                  2








                  2







                  Disclaimer



                  Originally I answered another question from the same author and it seems was asked within the same problem. I decided not to mark this one as a duplicate, because the first question doesn't have context of using the GPUImageLibrary, which makes the things way simpler. However I don't want to overact, so if you need any additional details, please refer to the original answer. Here I'll merely outline the solution.





                  You don't actually need to extend the GPUImageSubtractBlendFilter or any descendants of the GPUImageTwoInputFilter, because (as correctly was noted by Sergio) you should deal with only one instance of texture. Instead define your own fragment shader that will take a color filter, apply it and subtract the resulting
                  value from original pixel:



                  precision mediump float;
                  struct ColorFilter {
                  mat4 factor;
                  vec4 shift;
                  };
                  uniform sampler2D inputImageTexture;
                  uniform ColorFilter uColorFilter;
                  varying vec2 textureCoordinate;
                  void main() {
                  vec4 originalColor = texture2D(inputImageTexture, textureCoordinate);
                  originalColor.rgb *= originalColor.a;
                  vec4 filteredColor = (originalColor * uColorFilter.factor) + uColorFilter.shift;
                  filteredColor.rgb *= filteredColor.a;
                  gl_FragColor = vec4(originalColor.rgb - filteredColor.rgb, originalColor.a);
                  }


                  And now just attach your color filter matrix to the shader:



                  @Override
                  public void onInitialized() {
                  super.onInitialized();
                  attachColorFilter(getProgram());
                  }

                  // ========================================== //
                  // Private
                  // ========================================== //

                  private void attachColorFilter(int program) {
                  final float colorFilterFactor = new float[4 * 4];
                  final float colorFilterShift = new float[4];
                  for (int i = 0; i < mColorFilter.length; i++) {
                  final float value = mColorFilter[i];
                  final int calculateIndex = i + 1;
                  if (calculateIndex % 5 == 0) {
                  colorFilterShift[calculateIndex / 5 - 1] = value / 255;
                  } else {
                  colorFilterFactor[i - calculateIndex / 5] = value;
                  }
                  }
                  final int colorFactorLocation = GLES20.glGetUniformLocation(program,
                  "uColorFilter.factor");
                  setUniformMatrix4f(colorFactorLocation, colorFilterFactor);
                  final int colorShiftLocation = GLES20.glGetUniformLocation(program,
                  "uColorFilter.shift");
                  setFloatVec4(colorShiftLocation, colorFilterShift);
                  }


                  Feel free to use the gist with the working subclass. Just instantiate it and pass to the GPUImageView:



                  mBlendedImageView.setFilter(new ColorMatrixSubtractFilter(new float {
                  0.393f, 0.7689999f, 0.18899999f, 0, 0,
                  0.349f, 0.6859999f, 0.16799999f, 0, 0,
                  0.272f, 0.5339999f, 0.13099999f, 0, 0,
                  0, 0, 0, 1, 0
                  }));


                  On the right you can see the output of subtracted filter applied to the image on the left:



                  Blended image






                  share|improve this answer















                  Disclaimer



                  Originally I answered another question from the same author and it seems was asked within the same problem. I decided not to mark this one as a duplicate, because the first question doesn't have context of using the GPUImageLibrary, which makes the things way simpler. However I don't want to overact, so if you need any additional details, please refer to the original answer. Here I'll merely outline the solution.





                  You don't actually need to extend the GPUImageSubtractBlendFilter or any descendants of the GPUImageTwoInputFilter, because (as correctly was noted by Sergio) you should deal with only one instance of texture. Instead define your own fragment shader that will take a color filter, apply it and subtract the resulting
                  value from original pixel:



                  precision mediump float;
                  struct ColorFilter {
                  mat4 factor;
                  vec4 shift;
                  };
                  uniform sampler2D inputImageTexture;
                  uniform ColorFilter uColorFilter;
                  varying vec2 textureCoordinate;
                  void main() {
                  vec4 originalColor = texture2D(inputImageTexture, textureCoordinate);
                  originalColor.rgb *= originalColor.a;
                  vec4 filteredColor = (originalColor * uColorFilter.factor) + uColorFilter.shift;
                  filteredColor.rgb *= filteredColor.a;
                  gl_FragColor = vec4(originalColor.rgb - filteredColor.rgb, originalColor.a);
                  }


                  And now just attach your color filter matrix to the shader:



                  @Override
                  public void onInitialized() {
                  super.onInitialized();
                  attachColorFilter(getProgram());
                  }

                  // ========================================== //
                  // Private
                  // ========================================== //

                  private void attachColorFilter(int program) {
                  final float colorFilterFactor = new float[4 * 4];
                  final float colorFilterShift = new float[4];
                  for (int i = 0; i < mColorFilter.length; i++) {
                  final float value = mColorFilter[i];
                  final int calculateIndex = i + 1;
                  if (calculateIndex % 5 == 0) {
                  colorFilterShift[calculateIndex / 5 - 1] = value / 255;
                  } else {
                  colorFilterFactor[i - calculateIndex / 5] = value;
                  }
                  }
                  final int colorFactorLocation = GLES20.glGetUniformLocation(program,
                  "uColorFilter.factor");
                  setUniformMatrix4f(colorFactorLocation, colorFilterFactor);
                  final int colorShiftLocation = GLES20.glGetUniformLocation(program,
                  "uColorFilter.shift");
                  setFloatVec4(colorShiftLocation, colorFilterShift);
                  }


                  Feel free to use the gist with the working subclass. Just instantiate it and pass to the GPUImageView:



                  mBlendedImageView.setFilter(new ColorMatrixSubtractFilter(new float {
                  0.393f, 0.7689999f, 0.18899999f, 0, 0,
                  0.349f, 0.6859999f, 0.16799999f, 0, 0,
                  0.272f, 0.5339999f, 0.13099999f, 0, 0,
                  0, 0, 0, 1, 0
                  }));


                  On the right you can see the output of subtracted filter applied to the image on the left:



                  Blended image







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Jan 1 at 5:32









                  Peter Mortensen

                  13.7k1986113




                  13.7k1986113










                  answered Dec 14 '18 at 0:53









                  The Dreams WindThe Dreams Wind

                  1,572825




                  1,572825






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f33358248%2fhow-do-i-subtract-a-color-filter-using-gpuimagelibrary%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      MongoDB - Not Authorized To Execute Command

                      How to fix TextFormField cause rebuild widget in Flutter

                      in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith