How to subtract a color filter using GPUImageLibrary?

Currently, BlendModes (subtraction, exception, etc.) use LauncherImage as a mask. Can I apply these BlendModes to ColorMatrix?

I am using 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; } } 

I assume this is due to changing something with String SUBTRACT_BLEND_GRAGMENT_SHADER and String VERTEX_SHADER .

+45
java android gpuimage opengl-es
Oct 27 '15 at 0:57
source share
2 answers

A color matrix is ​​an object that defines the new color component values ​​for a certain pixel as linear functions of the current color components of the same pixel. That is, the only input for converting the color matrix is ​​a pixel, the colors of which must be converted. It is not possible to use other pixels for such a conversion. Regardless of whether they are pixels from another image or even neighbors from a transformed pixel, this is impossible.

+2
Sep 14 '16 at 14:57
source share

renouncement

I initially answered another question from the same author, and it seems to have been asked as part of the same problem. I decided not to mark this one as a duplicate, because the first question has no context for using GPUImageLibrary , which simplifies the work. However, I do not want to overestimate, therefore, if you need any additional details, please refer to the original answer . Here I just outline the solution.




In fact, you do not need to extend the GPUImageSubtractBlendFilter or any descendants of the GPUImageTwoInputFilter , because (as Sergio correctly noted) you have to deal with only one instance of the texture. Instead, define your own fragment shader that will take the color filter, apply it and subtract the resulting value from the 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); } 

Now just attach the 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 entity with a working subclass. Just instantiate it and go to 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 see the result of the subtracted filter applied to the image on the left:

Blended image

0
Dec 14 '18 at 0:53
source share



All Articles