1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "com_android_cts_verifier_camera_analyzer_ColorChecker.h" 18 19 #include "utils/Log.h" 20 #include "android/bitmap.h" 21 #include "colorchecker.h" 22 23 jboolean Java_com_android_cts_verifier_camera_analyzer_ColorChecker_findNative( 24 JNIEnv* env, 25 jobject thiz, 26 jobject inputBitmap) { 27 28 // Verify that we can handle the input bitmap 29 AndroidBitmapInfo inputInfo; 30 AndroidBitmap_getInfo(env, inputBitmap, &inputInfo); 31 if (inputInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888 && 32 inputInfo.format != ANDROID_BITMAP_FORMAT_RGB_565) { 33 LOGE("Only RGBA_8888 and RGB_565 bitmaps are supported, was given type %d.", inputInfo.format); 34 return JNI_FALSE; 35 } 36 37 // Get some references to the fields and class type of ColorChecker 38 jclass thizCls = env->GetObjectClass(thiz); 39 jfieldID patchId = env->GetFieldID(thizCls, "mPatchValues", "[F"); 40 jfieldID outputId = env->GetFieldID(thizCls, "mDebugOutput", "Landroid/graphics/Bitmap;"); 41 jfloatArray patchValues = (jfloatArray)env->GetObjectField(thiz, patchId); 42 43 // Get raw inputs and outputs ready 44 45 uint8_t *inputBuffer; 46 int result = AndroidBitmap_lockPixels( 47 env, 48 inputBitmap, 49 reinterpret_cast<void**>(&inputBuffer) ); 50 51 if (result != ANDROID_BITMAP_RESUT_SUCCESS) { 52 LOGE("Unable to lock input bitmap"); 53 return JNI_FALSE; 54 } 55 56 float *patchRawArray = env->GetFloatArrayElements(patchValues, 57 NULL); 58 59 uint8_t *outputImage = NULL; 60 int outputWidth, outputHeight; 61 62 // Find the color checker 63 bool success; 64 uint8_t *inputBufferRGBA = NULL; 65 int inputStride; 66 bool freeInputRGBA = false; 67 switch (inputInfo.format) { 68 case ANDROID_BITMAP_FORMAT_RGB_565: { 69 // First convert to RGBA_8888 70 inputBufferRGBA = new uint8_t[inputInfo.width * 71 inputInfo.height * 72 4]; 73 inputStride = inputInfo.width * 4; 74 uint8_t *outP = inputBufferRGBA; 75 for (int y = 0; y < inputInfo.height; y++ ) { 76 uint16_t *inP = (uint16_t*)(&inputBuffer[y * inputInfo.stride]); 77 for (int x = 0; x < inputInfo.width; x++) { 78 *(outP++) = ( ((*inP) >> 0) & 0x001F) << 3; 79 *(outP++) = ( ((*inP) >> 5) & 0x003F) << 2; 80 *(outP++) = ( ((*inP) >> 11) & 0x001F) << 3; 81 outP++; 82 inP++; 83 } 84 } 85 freeInputRGBA = true; 86 break; 87 } 88 case ANDROID_BITMAP_FORMAT_RGBA_8888: 89 // Already in RGBA 90 inputBufferRGBA = inputBuffer; 91 inputStride = inputInfo.stride; 92 break; 93 } 94 95 success = findColorChecker(inputBufferRGBA, 96 inputInfo.width, 97 inputStride, 98 inputInfo.height, 99 patchRawArray, 100 &outputImage, 101 &outputWidth, 102 &outputHeight); 103 104 // Clean up raw inputs/outputs 105 env->ReleaseFloatArrayElements(patchValues, patchRawArray, 0); 106 result = AndroidBitmap_unlockPixels(env, inputBitmap); 107 if (result != ANDROID_BITMAP_RESUT_SUCCESS) { 108 LOGE("Unable to unlock input bitmap"); 109 return JNI_FALSE; 110 } 111 112 if (freeInputRGBA) { 113 delete inputBufferRGBA; 114 } 115 116 // Create debug bitmap from output image data 117 if (outputImage != NULL) { 118 // Get method handles, create inputs to createBitmap 119 jclass bitmapClass = 120 env->FindClass("android/graphics/Bitmap"); 121 jclass bitmapConfigClass = 122 env->FindClass("android/graphics/Bitmap$Config"); 123 124 jmethodID createBitmap = env->GetStaticMethodID( 125 bitmapClass, "createBitmap", 126 "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;"); 127 128 jmethodID getConfig = env->GetStaticMethodID( 129 bitmapConfigClass, "valueOf", 130 "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;"); 131 132 // Create bitmap config and bitmap 133 jstring bitmapConfigValue = env->NewStringUTF("ARGB_8888"); 134 jobject rgbaConfig = env->CallStaticObjectMethod(bitmapConfigClass, 135 getConfig, 136 bitmapConfigValue); 137 jobject outputBitmap = env->CallStaticObjectMethod(bitmapClass, 138 createBitmap, 139 outputWidth, 140 outputHeight, 141 rgbaConfig); 142 // Copy output image into it 143 uint8_t *outputBuffer; 144 int result = AndroidBitmap_lockPixels( 145 env, 146 outputBitmap, 147 reinterpret_cast<void**>(&outputBuffer) ); 148 149 if (result != ANDROID_BITMAP_RESUT_SUCCESS) { 150 LOGE("Unable to lock output bitmap"); 151 return JNI_FALSE; 152 } 153 154 memcpy(outputBuffer, outputImage, outputWidth * outputHeight * 4); 155 156 result = AndroidBitmap_unlockPixels(env, outputBitmap); 157 if (result != ANDROID_BITMAP_RESUT_SUCCESS) { 158 LOGE("Unable to unlock output bitmap"); 159 return JNI_FALSE; 160 } 161 162 // Write new Bitmap reference into mDebugOutput class member 163 env->SetObjectField(thiz, outputId, outputBitmap); 164 165 delete outputImage; 166 } 167 if (!success) return JNI_FALSE; 168 169 return JNI_TRUE; 170 } 171