Search code examples
imageopencvpngtransparencyjavacv

How to change png transprant layer to white in JavaCV


I have a code to resize images using JavaCV and I need to change the image transparent background area to white. here is my code, I tried using cvtColor() with COLOR_RGBA2RGB or COLOR_BGRA2BGR but the result is an image with black background. any idea?

void myFnc(byte[] imageData){
        Mat img = imdecode(new Mat(imageData),IMREAD_UNCHANGED);
        Size size = new Size(newWidth, newHeight);
        Mat whbkImg = new Mat();
        cvtColor(img, whbkImg, COLOR_BGRA2BGR);
        Mat destImg = new Mat();
        resize(whbkImg,destImg,size);

        IntBuffer param = IntBuffer.allocate(6);
        param.put(CV_IMWRITE_PNG_COMPRESSION);
        param.put(1);
        param.put(CV_IMWRITE_JPEG_QUALITY);
        param.put(100);
        imwrite(filePath, destImg, param);
}

Solution

  • You will need to set the RGB color to white, i.e. set R, G, B channel to 255 where alpha suppose to be 0 (transparent)

    This answer is based on: Change all white pixels of image to transparent in OpenCV C++

    // load image and convert to transparent to white  
    Mat inImg = imread(argv[1], IMREAD_UNCHANGED);
    if (inImg.empty())
    {
        cout << "Error: cannot load source image!\n";
        return -1;
    }
    
    imshow ("Input Image", inImg);
    
    Mat outImg = Mat::zeros( inImg.size(), inImg.type() );
    
    for( int y = 0; y < inImg.rows; y++ ) {
        for( int x = 0; x < inImg.cols; x++ ) {
            cv::Vec4b &pixel = inImg.at<cv::Vec4b>(y, x);
            if (pixel[3] < 0.001) { // transparency threshold: 0.1% 
              pixel[0] = pixel[1] = pixel[2] = 255;
            }
            outImg.at<cv::Vec4b>(y,x) = pixel;
        }
    }
    
    imshow("Output Image", outImg);
    
    return 0;
    

    You can test the above code here: http://www.techep.csi.cuny.edu/~zhangs/cv.html

    For javacv, the below code would be equivalent (I haven't tested yet)

    Mat inImg = imdecode(new Mat(imageData),IMREAD_UNCHANGED);
    Mat outImg = Mat.zeros(inImg.size(), CV_8UC3).asMat();
    
    UByteIndexer inIndexer = inImg.createIndexer();
    UByteIndexer outIndexer = outImg.createIndexer();
    
    for (int i = 0; i < inIndexer.rows(); i++) {
        for (int j = 0; j < inIndexer.cols(); i++) {
            int[] pixel = new int[4];
            try {
                inIndexer.get(i, j, pixel);
                if (pixel[3] == 0) { // transparency
                    pixel[0] = pixel[1] = pixel[2] = 255;
                }
                outIndexer.put(i, j, pixel);
            } catch (IndexOutOfBoundsException e) {
    
            }
        }
    }