Image transparency fades when saved with OpenCv

I created a drawing application where I allow the user to draw and save the image for subsequent reloading in order to continue drawing. Essentially, I am transferring the drawing as a bitmap to the JNI level I want to save, and the same thing to load the previous drawing.

I use OpenCv to write and read to a png file.

I notice something strange in terms of image transparency. Does transparency seem to be calculated against black on OpenCv? See attached images containing transparencies.

Fix transparency by passing int array to native code, color conversion is not required: enter image description here

Dark transparency, passing the Bitmap object to its own code, color conversion is required: enter image description here

What can happen?

Saving an image using its own Bitmap tags to obtain pixels:

if ((error = AndroidBitmap_getInfo(pEnv, jbitmap, &info)) < 0) { LOGE("AndroidBitmap_getInfo() failed! error:%d",error); } if (0 == error) { if ((error = AndroidBitmap_lockPixels(pEnv, jbitmap, &pixels)) < 0) { LOGE("AndroidBitmap_lockPixels() failed ! error=%d", error); } } if (0 == error) { if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) { LOGI("ANDROID_BITMAP_FORMAT_RGBA_8888"); } else { LOGI("ANDROID_BITMAP_FORMAT %d",info.format); } Mat bgra(info.height, info.width, CV_8UC4, pixels); Mat image; //bgra.copyTo(image); // fix pixel order RGBA -> BGRA cvtColor(bgra, image, COLOR_RGBA2BGRA); vector<int> compression_params; compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); compression_params.push_back(3); // save image if (!imwrite(filePath, image, compression_params)) { LOGE("saveImage() -> Error saving image!"); error = -7; } // release locked pixels AndroidBitmap_unlockPixels(pEnv, jbitmap); } 

Saving an image using int int array methods

 JNIEXPORT void JNICALL Java_com_vblast_smasher_Smasher_saveImageRaw (JNIEnv *pEnv, jobject obj, jstring jFilePath, jintArray jbgra, jint options, jint compression) { jint* _bgra = pEnv->GetIntArrayElements(jbgra, 0); const char *filePath = pEnv->GetStringUTFChars(jFilePath, 0); if (NULL != filePath) { Mat image; Mat bgra(outputHeight, outputWidth, CV_8UC4, (unsigned char *)_bgra); bgra.copyTo(image); if (0 == options) { // replace existing cache value mpCache->insert(filePath, image); } vector<int> compression_params; compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); compression_params.push_back(compression); // save image if (!imwrite(filePath, image)) { LOGE("saveImage() -> Error saving image!"); } } pEnv->ReleaseIntArrayElements(jbgra, _bgra, 0); pEnv->ReleaseStringUTFChars(jFilePath, filePath); } 

Update 05/25/12:
After a little research, I found out that this problem does not occur if I get an array of int pixels from a bitmap and pass it directly to JNI, unlike what I am doing now, which transfers the entire bitmap to JNI then get the pixels and use cvtColor to convert pixels properly. Am I using the correct pixel transform?

+4
source share
2 answers

There are two ways to represent alpha in an RGBA pixel, pre-multiplied or not. When multiplied, the values ​​of R, G, and B are multiplied by the percentage alpha: color = (color * alpha) / 255. This simplifies many blending calculations and is often used inside the image library. Before saving in a format that does not use pre-multiplied alpha, such as PNG, the color values ​​must be "unmultiplied": color = (255 * color) / alpha. If it is not, the colors will look too dark; the more transparent the color, the darker it will be. This is similar to the effect you see here.

+4
source

There is nothing transparent in opencv. The foreground and background images are mixed appropriately to create the illusion of transparency. Check this one to find out how.

-1
source

Source: https://habr.com/ru/post/1414271/


All Articles