Created
January 8, 2019 00:40
-
-
Save ZhangMenghe/8f795c3bc7f154ceaa3be5105aa85915 to your computer and use it in GitHub Desktop.
Convert Ndk image(AImage) to RGB image.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //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); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
any reason why
1.5 * _ndk_image_widthin the opencv functionupdate_ndk_image()?