【发布时间】:2012-05-24 22:47:29
【问题描述】:
我创建了一个绘图应用程序,允许用户在其中绘制并保存图像,以便稍后重新加载以继续绘图。本质上,我将绘图作为位图传递给要保存的 JNI 层,并与加载以前的绘图相同。
我正在使用 OpenCv 来读写 png 文件。
我注意到图像的透明度有些奇怪。似乎是根据 OpenCv 上的黑色计算透明度?看看附上的图片,其中包含有透明胶片的线条。
通过将 int 数组传递给本机代码来纠正透明度,无需颜色转换:
通过将位图对象传递给本机代码来加深透明度,需要进行颜色转换:
可能会发生什么?
使用原生 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);
}
2012 年 5 月 25 日更新:
经过更多研究后,我发现如果我从位图中获取像素的 int 数组并将其直接传递给 JNI,而不是我目前所做的将整个位图传递给 JNI,则不会发生此问题图层然后获取像素并使用cvtColor 正确转换像素。我是否使用了正确的像素转换?
【问题讨论】:
-
compression的值是多少? -
我尝试的值是 0、3 和 9。它们都产生相同的结果。
-
这是什么版本,你从哪里下载的?
-
我是从官方“网站”v2.4.0下载的。请参阅我的问题的更新部分。我转换颜色的方式有问题,或者颜色与转换混淆了。
-
您真的需要进行转换吗?你确定吗?
标签: opencv android-ndk