Search code examples
openglqmlglsltexturesshader

Replace white by black


I want to replace every white pixel in an image by black, but keep everything else unchanged

Window {
    id: window;
    width: 800;
    height: 600;
    visible: true;

    Image {
        id: sourceImage
        anchors.centerIn: parent
        source: "qrc:/source.png"
    }

    Item {
        anchors.fill: sourceImage
        layer.enabled: true
        layer.samplerName: "maskSource"
        layer.effect: ShaderEffect {
            fragmentShader: "
                             uniform lowp sampler2D maskSource;
                             uniform lowp float qt_Opacity;
                             varying highp vec2 qt_TexCoord0;
                             void main() {
                                 vec4 pixel = texture2D(maskSource, qt_TexCoord0);
                                 if (pixel == vec4(1.0, 1.0, 1.0, pixel.a)) {
                                     pixel = vec4(0.0, 0.0, 0.0, pixel.a);
                                 }
                                 gl_FragColor = vec4(pixel.r, pixel.g, pixel.b, pixel.a);
                             }"
        }
    }
}

I can't manage to make it work


Solution

  • I found a solution to my problem :

    ShaderEffect {
        property variant src: sourceImage
        vertexShader: "
                                 uniform highp mat4 qt_Matrix;
                                 attribute highp vec4 qt_Vertex;
                                 attribute highp vec2 qt_MultiTexCoord0;
                                 varying highp vec2 coord;
                                 void main() {
                                     coord = qt_MultiTexCoord0;
                                     gl_Position = qt_Matrix * qt_Vertex;
                                 }"
        fragmentShader: "
                                 uniform lowp sampler2D src;
                                 uniform lowp float qt_Opacity;
                                 varying highp vec2 coord;
                                 void main() {
                                     vec4 pixel = texture2D(src, coord);
                                     if (pixel.r > 0.2 && pixel.g > 0.2 && pixel.b > 0.2) {
                                         pixel.rgb = vec3(0.0, 0.0, 0.0);
                                     }
                                     gl_FragColor = pixel;
                                 }"
    }
    

    The values I use to detect whites (0.2,0.2,0.2) work for my images, but they would probably not work for every cases. I don't know if this is the best that can be done.