Skip to content

Instantly share code, notes, and snippets.

@ZhangMenghe
Created January 8, 2019 00:40
Show Gist options
  • Select an option

  • Save ZhangMenghe/8f795c3bc7f154ceaa3be5105aa85915 to your computer and use it in GitHub Desktop.

Select an option

Save ZhangMenghe/8f795c3bc7f154ceaa3be5105aa85915 to your computer and use it in GitHub Desktop.
Convert Ndk image(AImage) to RGB image.
//Here shows the ordinary conversion and the method use OpenCV
static inline uint32_t YUV2RGB(int nY, int nU, int nV, uint8_t&r, uint8_t&g, uint8_t&b) {
nY -= 16;
nU -= 128;
nV -= 128;
if (nY < 0) nY = 0;
// This is the floating point equivalent. We do the conversion in integer
// because some Android devices do not have floating point in hardware.
// nR = (int)(1.164 * nY + 1.596 * nV);
// nG = (int)(1.164 * nY - 0.813 * nV - 0.391 * nU);
// nB = (int)(1.164 * nY + 2.018 * nU);
int nR = (int)(1192 * nY + 1634 * nV);
int nG = (int)(1192 * nY - 833 * nV - 400 * nU);
int nB = (int)(1192 * nY + 2066 * nU);
nR = std::min(262143, std::max(0, nR));
nG = std::min(262143, std::max(0, nG));
nB = std::min(262143, std::max(0, nB));
nR = (nR >> 10) & 0xff;
nG = (nG >> 10) & 0xff;
nB = (nB >> 10) & 0xff;
b = (uint8_t)nB;
g = (uint8_t)nG;
r = (uint8_t)nR;
return 0xff000000 | (nR << 16) | (nG << 8) | nB;
}
//ordinary way
void update_ndk_image(){
AImage * ndk_image = GET_NDK_IMAGE_SOMEWHERE();
uint8_t * rgb_image;
uint8_t *yPixel, *uPixel, *vPixel;
int32_t yLen, uLen, vLen;
AImage_getPlaneData(ndk_image, 0, &yPixel, &yLen);
AImage_getPlaneData(ndk_image, 1, &uPixel, &uLen);
AImage_getPlaneData(ndk_image, 2, &vPixel, &vLen);
int32_t format = 0, width, height, num_plane = 0, stride = 0, strideuv=0;
if (ndk_image != nullptr) {
if (GetNdkImageProperties(ndk_image, &format, &width, &height, &num_plane,
&stride, &strideuv)) {
if (format == AIMAGE_FORMAT_YUV_420_888) {
if (width > 0 || height > 0 || num_plane > 0 || stride > 0) {
uint8_t *yPixel, *uPixel, *vPixel;
int32_t yLen, uLen, vLen;
rgb_image = new uint8_t[width * height * 3];
int32_t uvPixelStride;
AImage_getPlanePixelStride(ndk_image, 1, &uvPixelStride);
AImageCropRect srcRect;
AImage_getCropRect(ndk_image, &srcRect);
AImage_getPlaneData(ndk_image, 0, &yPixel, &yLen);
AImage_getPlaneData(ndk_image, 1, &uPixel, &uLen);
AImage_getPlaneData(ndk_image, 2, &vPixel, &vLen);
for (int32_t y = 0; y < height; y++) {
const uint8_t *pY = yPixel + stride * (y + srcRect.top) + srcRect.left;
int32_t uv_row_start = strideuv * ((y + srcRect.top) >> 1);
const uint8_t *pU = uPixel + uv_row_start + (srcRect.left >> 1);
const uint8_t *pV = vPixel + uv_row_start + (srcRect.left >> 1);
for (int32_t x = 0; x < width; x++) {
const int32_t uv_offset = (x >> 1) * uvPixelStride;
int idx = y * width + x;
YUV2RGB(pY[x], pU[uv_offset], pV[uv_offset],rgb_image[3 * idx],
rgb_image[3 * idx + 1], rgb_image[3 * idx + 2]);
}
}
}
} else {
LOGE("Expected image in YUV_420_888 format.");
}
}
}
}
//use opencv
void update_ndk_image(){
//........ something similar
cv::Mat _ndk_rgb_img, _ndk_gray_img;
uint8_t *yPixel, *uPixel, *vPixel;
int32_t yLen, uLen, vLen;
AImage_getPlaneData(ndk_image, 0, &yPixel, &yLen);
AImage_getPlaneData(ndk_image, 1, &uPixel, &uLen);
AImage_getPlaneData(ndk_image, 2, &vPixel, &vLen);
uint8_t * data = new uint8_t[yLen + vLen + uLen];
memcpy(data, yPixel, yLen);
memcpy(data+yLen, vPixel, vLen);
memcpy(data+yLen+vLen, uPixel, uLen);
cv::Mat mYUV = cv::Mat(_ndk_image_width * 1.5, _ndk_image_height, CV_8UC1, data);
cv::cvtColor(mYUV, _ndk_rgb_img, CV_YUV2RGB_NV21, 3);
cv::rotate(_ndk_rgb_img, _ndk_rgb_img, cv::ROTATE_90_CLOCKWISE);
//gray image only use plane Y
_ndk_gray_img = cv::Mat(_ndk_image_width, _ndk_image_height, CV_8UC1, yPixel);
cv::rotate(_ndk_gray_img, _ndk_gray_img, cv::ROTATE_90_CLOCKWISE);
}
@milinddeore
Copy link
Copy Markdown

any reason why 1.5 * _ndk_image_width in the opencv function update_ndk_image()?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment