我创建了一个绘图应用程序,我允许用户绘制并保存图像以便以后重新加载以继续绘图。基本上,我将绘图作为位图传递给要保存的JNI图层,并将其加载到上一个图形中。
我正在使用OpenCv来编写和读取png文件。
我注意到图像的透明度方面有些奇怪。几乎看起来透明度是根据OpenCv上的黑色计算的?看一下附加的图像,包含透明胶片的行。
通过将int数组传递给本机代码来纠正透明度,无需进行颜色转换:
通过将Bitmap对象传递给本机代码来实现透明度变暗,需要进行颜色转换:
可能发生什么?
使用原生Bitmap保存图像获取像素方法:
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);
}
使用原生int像素数组方法保存图像:
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);
}
更新05/25/12:
经过一番研究后,我发现如果我从位图获取像素的int数组并将其直接传递给JNI,而不是我目前将整个Bitmap传递给JNI,那么这个问题就不会发生。然后获取像素并使用cvtColor
正确转换像素。我使用正确的像素转换吗?
答案 0 :(得分:4)
有两种方法可以表示RGBA像素中的alpha,预乘还是不是。通过预乘,R,G和B值乘以alpha:color =(color * alpha)/ 255的百分比。这简化了大量的混合计算,并且通常在成像库内部使用。在保存为不使用预乘alpha的格式(例如PNG)之前,颜色值必须为“unmultiplied”:color =(255 * color)/ alpha。如果不是,颜色看起来会太暗;颜色越透明,颜色越深。这看起来就像你在这里看到的效果。
答案 1 :(得分:-1)
在opencv中没有任何称为透明图像的东西。前景和背景图像被适当地混合以产生透明度的错觉。检查this以查看其完成情况。