Home | History | Annotate | Download | only in cameraanalyzer
      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