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 package com.android.cts.verifier.camera.analyzer; 18 19 import android.graphics.Bitmap; 20 import android.graphics.BitmapFactory; 21 import android.graphics.ImageFormat; 22 import android.graphics.Rect; 23 import android.hardware.Camera; 24 import android.hardware.Camera.Area; 25 import android.util.Log; 26 import android.widget.ImageView; 27 28 import java.io.FileOutputStream; 29 import java.io.FileNotFoundException; 30 import java.io.IOException; 31 import java.util.ArrayList; 32 import java.util.List; 33 import java.util.Random; 34 35 /** 36 * Implements a test to verify whether the camera metering system works as 37 * described in the API. 38 * 39 * The test consists two sub-categories. The first one has tests with only 40 * one metering area defined. The second one has tests with two metering areas 41 * defined. For each single sub-test, we use a random number generator to 42 * decide where to put some of the metering areas to and how much weight should 43 * be assigned to each area. For different tests, we use different ways to 44 * define other metering areas and their weight, in order to cover all possible 45 * fail cases. The metering areas are contrained to the grey squares in the 46 * bottom of the color checker. 47 */ 48 public class MeteringTest extends CameraTests { 49 50 private static final String TAG = "MeteringTest"; 51 52 /** A long wait.*/ 53 private static final int LONG_SLEEP = 4000; 54 /** Debug result in text. */ 55 private String mDebugText; 56 /** Thread lock. */ 57 private final Object mProcessingImage = new Object(); 58 /** Memory address of the native test handler. */ 59 private long mTestHandler; 60 /** The maximum number of metering area the device supports. */ 61 private int mMaxNumMeteringArea; 62 /** The metering areas. */ 63 private List<Camera.Area> mGreyAreas; 64 /** The coordinates of the grey squares on the color checker. */ 65 private int[] mGreyCoordinates = new int[24]; 66 /** Random number generator. */ 67 private final Random mRandomGenerator = new Random(); 68 /** Reference comparison result for tests. */ 69 private ArrayList<Boolean> mReferenceCompareResults; 70 /** Number of tests in the same instance. */ 71 private int mTestCount; 72 /** Reference test logs. */ 73 private ArrayList<String> mReferenceLogs; 74 /** Test result to show. */ 75 private int[] mTestResults; 76 /** Number of tests. */ 77 private int mNumTests; 78 /** Camera Parameters. */ 79 private Camera.Parameters mParams; 80 /** Singleton test instance. */ 81 private static MeteringTest singletonTest = null; 82 83 /** Constructs a <code>MeteringTest</code> instance with the given 84 * camera pointer. 85 */ MeteringTest()86 private MeteringTest() { 87 super(); 88 } 89 updateCamera()90 public void updateCamera() { 91 // Looks up how many metering area the device supports. 92 mParams = mTestCamera.getParameters(); 93 mMaxNumMeteringArea = mParams.getMaxNumMeteringAreas(); 94 Log.v(TAG, String.format("Maximum number if metering area is %d", mMaxNumMeteringArea)); 95 if (mMaxNumMeteringArea == 0) { 96 mDebugText = "Custom Metering not supported!"; 97 Log.v(TAG, "Custom Metering not supported"); 98 } 99 } 100 getSingletonTest()101 public static synchronized MeteringTest getSingletonTest() { 102 if (singletonTest == null) { 103 Log.v(TAG, "Creating a new MeteringTest instance"); 104 singletonTest = new MeteringTest(); 105 singletonTest.initializeTest(); 106 } 107 return singletonTest; 108 } 109 initializeTest()110 private void initializeTest() { 111 // Creates a native metering test handler. 112 mTestHandler = createMeteringTest(); 113 mDebugText = new String(); 114 mReferenceCompareResults = new ArrayList<Boolean>(); 115 mReferenceLogs = new ArrayList<String>(); 116 mNumTests = 3; 117 mTestResults = new int[mNumTests]; 118 for (int i = 0; i < mNumTests; ++i) { 119 mTestResults[i] = CameraTests.CAMERA_TEST_NOT_RUN; 120 } 121 } 122 123 /** 124 * Runs the metering test instance. 125 */ 126 @Override run(int index)127 public synchronized void run(int index) { 128 if (index == 0) { 129 run(1); 130 run(2); 131 return; 132 } 133 Log.v(TAG, "MeteringTest thread started!"); 134 135 // Finds the coordinates of the grey squares on the color checker. 136 // The coordinate system has (-1000, -1000) on the upper left corner. 137 // And (1000, 1000) on the bottom right corner. 138 findGreyCoordinates(mGreyCoordinates, getCheckerCenter(), getCheckerRadius()); 139 140 if (mMaxNumMeteringArea > 0) { 141 mTestCount = 0; 142 // Runs the metering tests category by category. 143 switch (index) { 144 case 1: 145 runOneAreaTest(); 146 break; 147 case 2: 148 if (mMaxNumMeteringArea > 1) { 149 runTwoAreasTest(); 150 } 151 break; 152 default: 153 break; 154 } 155 } 156 157 mParams = mTestCamera.getParameters(); 158 mParams.setMeteringAreas(null); 159 mTestCamera.setParameters(mParams); 160 161 boolean[] testCompareResults = new boolean[2 * mTestCount]; 162 163 // Processes the image data taken so far and stores the test results. 164 processMeteringTest(mTestHandler, testCompareResults); 165 // Prepares debug output based on the test results. 166 prepareDebugText(testCompareResults, index); 167 168 mReferenceCompareResults.clear(); 169 mReferenceLogs.clear(); 170 } 171 172 /** 173 * Prepares the test results in HTML text string to show in the UI. 174 * 175 * If the test result is the same as the reference result, the text will be 176 * shown in green. Otherwise it would be shown as red. 177 * 178 * @param testCompareResults the array storing the comparison results from 179 * the data taken by the camera so far. 180 */ prepareDebugText(boolean[] testCompareResults, int index)181 private void prepareDebugText(boolean[] testCompareResults, int index) { 182 mDebugText = ""; 183 boolean groupTestPassed = true; 184 for (int i = 0; i < mTestCount; ++i) { 185 String testLog; 186 boolean testPassed = true; 187 testLog = mReferenceLogs.get(i); 188 mDebugText += (testLog + "<br/>"); 189 190 if (testCompareResults[i * 2] == mReferenceCompareResults.get(i * 2)) { 191 mDebugText += String.format( 192 "Picture 1 equivalent to Picture 2 is %b \n", 193 testCompareResults[i * 2]); 194 } else { 195 mDebugText += String.format( 196 "Picture 1 equivalent to Picture 2 is %b \n", 197 testCompareResults[i * 2]); 198 testPassed = false; 199 } 200 201 if (testCompareResults[i * 2 + 1] == mReferenceCompareResults.get(i * 2 + 1)) { 202 mDebugText += String.format( 203 "Picture 1 darker than Picture 2 is %b \n", 204 testCompareResults[i * 2 + 1]); 205 } else { 206 mDebugText += String.format( 207 "Picture 1 darker than Picture 2 is %b \n", 208 testCompareResults[i * 2 + 1]); 209 testPassed = false; 210 } 211 212 if (testPassed) { 213 mDebugText += "Test passed! \n"; 214 } else { 215 mDebugText += "Test failed! \n"; 216 groupTestPassed = false; 217 } 218 Log.v(TAG, String.format("%s", mDebugText)); 219 } 220 221 if (groupTestPassed) { 222 mTestResults[index] = CameraTests.CAMERA_TEST_SUCCESS; 223 } else { 224 mTestResults[index] = CameraTests.CAMERA_TEST_FAILURE; 225 } 226 227 } 228 229 /** 230 * Runs tests to check whether the metering functionalities work properly 231 * when one metering area is added. 232 */ runOneAreaTest()233 private void runOneAreaTest() { 234 int weight1; 235 int weight2; 236 int square1; 237 int square2; 238 239 Log.v(TAG, "Running one area Test"); 240 241 // Test case 1: Two images have the same metering area. Image 1 has 242 // a diffent weight than Image 2. The result images should be 243 // identical. 244 // Tests whether weight normalization works. 245 square1 = mRandomGenerator.nextInt(6); 246 weight1 = mRandomGenerator.nextInt(100) + 1; 247 runSingleTest(square1, square1, weight1); 248 249 square2 = square1; 250 weight2 = mRandomGenerator.nextInt(100) + 901; 251 runSingleTest(square2, square2, weight2); 252 mReferenceCompareResults.add(true); 253 mReferenceCompareResults.add(false); 254 Log.v(TAG, String.format("Running test for %d square with weights %d, %d", 255 square1, weight1, weight2)); 256 mReferenceLogs.add(String.format( 257 "Running test for %d 1x1 square with weights %d, %d", square1, weight1, weight2)); 258 ++mTestCount; 259 260 // Test case 2: Two images have different metering areas. Image 1 has 261 // one of the grey squares as its metering area. Image 2 has a darker 262 // grey square as its metering area. The weights for both images are 263 // the same. Image 1 is expected to be darker than Image 2. 264 // Tests whether metering on uni-brightness patches work. 265 square1 = mRandomGenerator.nextInt(5); 266 weight1 = mRandomGenerator.nextInt(1000) + 1; 267 runSingleTest(square1, square1, weight1); 268 269 square2 = mRandomGenerator.nextInt(6 - square1 - 1) + square1 + 1; 270 weight2 = weight1; 271 runSingleTest(square2, square2, weight2); 272 mReferenceCompareResults.add(false); 273 mReferenceCompareResults.add(true); 274 mReferenceLogs.add(String.format( 275 "Running test for %d, %d 1x1 square with weight %d", square1, square2, weight1)); 276 ++mTestCount; 277 278 // Test case 3: Two images have different metering areas. Image one has 279 // one of the grey squares as its metering area. Image 2 has a 280 // rectangle which contains Image 1's metering area and the neighboring 281 // darker grey square. The weights for both tests are the same. Image 1 282 // is expected to be darker than Image 2. 283 // Tests whether metering on patches with different brightness works. 284 square1 = mRandomGenerator.nextInt(5); 285 weight1 = mRandomGenerator.nextInt(1000) + 1; 286 runSingleTest(square1, square1, weight1); 287 288 square2 = square1; 289 weight2 = weight1; 290 runSingleTest(square2, square2 + 1, weight2); 291 mReferenceCompareResults.add(false); 292 mReferenceCompareResults.add(true); 293 mReferenceLogs.add(String.format( 294 "Running test for %d 1x1, 1x2 square with weight %d", square1, weight1)); 295 ++mTestCount; 296 297 // Test case 4: Two images have different metering areas. Image one has 298 // two neighboring grey squares as its metering area. Image 2 has two 299 // darker neighboring grey squares as its metering area. Weights are 300 // the same for both images. Image 1 is expected to be darker than 301 // Image 2. 302 // Tests whether metering on two mixed-brightness patches work. 303 square1 = mRandomGenerator.nextInt(4); 304 weight1 = mRandomGenerator.nextInt(1000) + 1; 305 runSingleTest(square1, square1 + 1, weight1); 306 307 square2 = mRandomGenerator.nextInt(5 - square1 - 1) + square1 + 1; 308 weight2 = weight1; 309 runSingleTest(square2, square2 + 1, weight2); 310 mReferenceCompareResults.add(false); 311 mReferenceCompareResults.add(true); 312 mReferenceLogs.add(String.format( 313 "Running test for %d, %d 1x2 square with weight %d", square1, square2, weight1)); 314 ++mTestCount; 315 316 // Test case 5: Two images have different metering areas. Image one has 317 // three neighboring grey squares as its metering area. Image 2 has 318 // three darker neighboring grey squares as its metering area. Weights 319 // are the same. Image 1 is expected to be darker than Image 2. 320 // Tests whether metering on three mixed-brightness patches work. 321 square1 = mRandomGenerator.nextInt(3); 322 weight1 = mRandomGenerator.nextInt(1000) + 1; 323 runSingleTest(square1, square1 + 2, weight1); 324 325 square2 = mRandomGenerator.nextInt(4 - square1 - 1) + square1 + 1; 326 weight2 = weight1; 327 runSingleTest(square2, square2 + 2, weight2); 328 mReferenceCompareResults.add(false); 329 mReferenceCompareResults.add(true); 330 mReferenceLogs.add(String.format( 331 "Running test for %d, %d 1x3 square with weight %d", square1, square2, weight1)); 332 ++mTestCount; 333 } 334 335 /** 336 * Runs metering tests to verify the functionalities when there are two 337 * areas set as the metering area. 338 */ runTwoAreasTest()339 private void runTwoAreasTest() { 340 int[] weight1 = new int[2]; 341 int[] weight2 = new int[2]; 342 int[] square1Start = new int[2]; 343 int[] square2Start = new int[2]; 344 int[] square1End = new int[2]; 345 int[] square2End = new int[2]; 346 347 Log.v(TAG, "Running two-area Test"); 348 349 // Test case 1: Image 1 has two metering areas. They are two adjacent 350 // grey squares (each set as a metering area). The two areas have the 351 // same weight. Image 2 has one metering area, which is the combination 352 // of Image 1's two metering areas as a rectangle. The weight is the 353 // same as that of Image 1's individual area. Image 1 is expected to 354 // be equivalent to Image 2. 355 // Tests whether having seperating a metering area into two will yield 356 // the same result. 357 square1Start[0] = mRandomGenerator.nextInt(5); 358 square1End[0] = square1Start[0]; 359 weight1[0] = mRandomGenerator.nextInt(1000) + 1; 360 square1Start[1] = square1Start[0] + 1; 361 square1End[1] = square1Start[1]; 362 weight1[1] = weight1[0]; 363 runMultipleAreaTest(square1Start, square1End, weight1); 364 365 square2Start[0] = square1Start[0]; 366 weight2[0] = weight1[0]; 367 runSingleTest(square2Start[0], square2Start[0] + 1, weight2[0]); 368 mReferenceCompareResults.add(true); 369 mReferenceCompareResults.add(false); 370 mReferenceLogs.add(String.format( 371 "Running test for %d, %d 1x1 square with weight %d", 372 square1Start[0], square1Start[1], weight1[0])); 373 ++mTestCount; 374 375 // Test case 2: Image 1 has two metering areas. They are two random 376 // grey squareson the color checker. The brighter square has a larger 377 // weight than the darker square. Image 2 has the same two metering 378 // areas as Image 1. The weights for both are equal to the weight of 379 // the darker square in Image 1, which is smaller than the weight of 380 // the brighter square in Image 1. Image 1 is expected to be darker 381 // than Image 2. 382 // Tests whether giving one of the two metering areas a different 383 // weight would change the image in the correct way. 384 square1Start[0] = mRandomGenerator.nextInt(4); 385 square1End[0] = square1Start[0]; 386 weight1[0] = mRandomGenerator.nextInt(100) + 901; 387 square1Start[1] = mRandomGenerator.nextInt(5 - square1Start[0] - 1) + square1Start[0] + 1; 388 square1End[1] = square1Start[1]; 389 weight1[1] = mRandomGenerator.nextInt(100) + 1; 390 runMultipleAreaTest(square1Start, square1End, weight1); 391 392 square2Start[0] = square1Start[0]; 393 square2End[0] = square2Start[0]; 394 weight2[0] = weight1[1]; 395 square2Start[1] = square1Start[1]; 396 square2End[1] = square1End[1]; 397 weight2[1] = weight2[0]; 398 runMultipleAreaTest(square2Start, square2End, weight2); 399 mReferenceCompareResults.add(false); 400 mReferenceCompareResults.add(true); 401 mReferenceLogs.add(String.format( 402 "Running test for %d, %d 1x1 square with weight %d, %d", 403 square1Start[0], square1Start[1], weight1[0], weight2[1])); 404 ++mTestCount; 405 406 // Test case 3: Image 1 has two metering areas. Both are set to the 407 // same random grey square on the color checker. The weight for both 408 // are the same. Image 2 has one meterig area, which is the same as 409 // Image 1's chosen grey square. The weight for it is the same as 410 // Image 1's weight for one metering area. Image 1 is expected to be 411 // equivalent to Image 2. 412 // Tests whether defining overlapping metering area works. 413 square1Start[0] = mRandomGenerator.nextInt(6); 414 square1End[0] = square1Start[0]; 415 weight1[0] = mRandomGenerator.nextInt(1000) + 1; 416 square1Start[1] = square1Start[0]; 417 square1End[1] = square1Start[1]; 418 weight1[1] = weight1[0]; 419 runMultipleAreaTest(square1Start, square1End, weight1); 420 421 square2Start[0] = square1Start[0]; 422 square2End[0] = square2Start[0]; 423 weight2[0] = weight1[0]; 424 runSingleTest(square2Start[0], square2End[0], weight2[0]); 425 mReferenceCompareResults.add(true); 426 mReferenceCompareResults.add(false); 427 mReferenceLogs.add(String.format( 428 "Running test for %d 1x1 square with weight %d,", square1Start[0], weight1[0])); 429 ++mTestCount; 430 431 // Test case 4: Image 1 has two metering areas. The first one is a 432 // grey square on the color checker. The second one is a rectangle 433 // containing the first metering area's grey square and its neighboring 434 // darker square. The weights for both metering area are the same. 435 // Image 2 has two metering areas. The first one is the same grey 436 // square as Image 1's first metering area. The second one is the 437 // neighboring darker grey square. The weight for the brighter square 438 // is double the weight of Image 1's weights for each metering area. 439 // The weight for the Image 2's darker grey square is the same as 440 // Image 1's weight for each of its metering areas. Image 1 is expected 441 // to be equivalent to Image 2. 442 // Tests whether the weights for overlapping metering area add up. 443 square1Start[0] = mRandomGenerator.nextInt(2); 444 square1End[0] = square1Start[0]; 445 weight1[0] = mRandomGenerator.nextInt(500) + 1; 446 square1Start[1] = square1Start[0]; 447 square1End[1] = square1Start[1] + 1; 448 weight1[1] = weight1[0]; 449 runMultipleAreaTest(square1Start, square1End, weight1); 450 451 square2Start[0] = square1Start[0]; 452 square2End[0] = square1End[0]; 453 weight2[0] = weight1[0] * 2; 454 square2Start[1] = square2Start[0] + 1; 455 square2End[1] = square2Start[1]; 456 weight2[1] = weight1[1]; 457 runMultipleAreaTest(square2Start, square2End, weight2); 458 mReferenceCompareResults.add(true); 459 mReferenceCompareResults.add(false); 460 mReferenceLogs.add(String.format( 461 "Running test for %d 1x2 1x1 and 1x2 square with weight %d,", 462 square1Start[0], weight1[0])); 463 ++mTestCount; 464 } 465 466 /** 467 * Runs the metering test when multiple metering areas are defined. 468 * 469 * @param startIndex the array storing the index of the grey square where 470 * one metering area starts 471 * @param endIndex the array storing the index of the grey square where one 472 * metering area ends. 473 * @param weight the array storing the weight for each metering area. 474 */ runMultipleAreaTest(int[] startIndex, int[] endIndex, int[] weight)475 private void runMultipleAreaTest(int[] startIndex, int[] endIndex, int[] weight) { 476 int numAreas = startIndex.length; 477 mParams = mTestCamera.getParameters(); 478 List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>(); 479 480 for (int i = 0; i < numAreas; ++i) { 481 meteringAreas.add(makeArea(startIndex[i], endIndex[i], weight[i])); 482 Log.v(TAG, String.format("Add metering area for %d, %d, %d", 483 startIndex[i], endIndex[i], weight[i])); 484 } 485 mParams.setMeteringAreas(meteringAreas); 486 mTestCamera.setParameters(mParams); 487 takePicture(); 488 } 489 490 /** 491 * Runs the metering test when one metering area is defined. 492 * 493 * @param startIndex the index of the grey square where the metering area 494 * starts 495 * @param endIndex the index of the grey square where the metering area 496 * ends. 497 * @param weight the weight for the metering area. 498 */ runSingleTest(int startIndex, int endIndex, int weight)499 private void runSingleTest(int startIndex, int endIndex, int weight) { 500 mParams = mTestCamera.getParameters(); 501 List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>(); 502 503 Log.v(TAG, String.format("Single test for %d, %d, %d", startIndex, endIndex, weight)); 504 meteringAreas.add(makeArea(startIndex, endIndex, weight)); 505 mParams.setMeteringAreas(meteringAreas); 506 mTestCamera.setParameters(mParams); 507 takePicture(); 508 } 509 510 /** 511 * Takes picture with the camera instance linked to this test class. 512 */ takePicture()513 private void takePicture() { 514 // Waits for the metering to be stable 515 try{ 516 Log.v(TAG, "Waiting for metering"); 517 Thread.sleep(LONG_SLEEP); 518 Log.v(TAG, "END Waiting"); 519 } catch (InterruptedException e) {} 520 521 mTestCamera.takePicture(null, null, null, mTestJpegListener); 522 523 // Locks thread until picture is taken and ready for processing. 524 synchronized (mProcessingImage) { 525 try{ 526 Log.v(TAG, "Start waiting for Image"); 527 528 mProcessingImage.wait(); 529 } catch (InterruptedException e) { 530 Log.v(TAG, "Callback wait fails!"); 531 } 532 } 533 } 534 535 /** 536 * Constructs a <code>Camera.Area</code> object of the metering area. 537 * Given the start and end index of one metering area, it takes the upper 538 * left corner of the starting square and the bottom right corner of the 539 * end square to construct an Area. 540 * 541 * @param startIndex the index of the grey square where the metering area 542 * starts 543 * @param endIndex the index of the grey square where the metering area 544 * ends 545 * @param weight the weight of this metering area. 546 * 547 * @return a <code>Camera.Area</code> object which represents this metering 548 * area 549 */ makeArea(int startIndex, int endIndex, int weight)550 private Camera.Area makeArea(int startIndex, int endIndex, int weight) { 551 Rect areaRect = new Rect(mGreyCoordinates[startIndex * 4], 552 mGreyCoordinates[startIndex * 4 + 1], 553 mGreyCoordinates[endIndex * 4 + 2], 554 mGreyCoordinates[endIndex * 4 + 3]); 555 Camera.Area area = new Camera.Area(areaRect, weight); 556 557 return area; 558 } 559 560 @Override getDebugText()561 public String getDebugText() { 562 return mDebugText; 563 } 564 565 @Override getResultText()566 public String getResultText() { 567 return mDebugText; 568 } 569 570 @Override getTestName()571 public String getTestName() { 572 return "Metering Test: \n"; 573 } 574 575 @Override getTestName(int index)576 public String getTestName(int index) { 577 switch (index) { 578 case 0: 579 return "Run all tests"; 580 case 1: 581 return "One metering area tests"; 582 case 2: 583 return "Multiple metering areas tests"; 584 default: 585 return ""; 586 } 587 } 588 589 @Override getResult(int index)590 public int getResult(int index) { 591 return mTestResults[index]; 592 } 593 594 @Override getNumTests()595 public int getNumTests() { 596 return mNumTests; 597 } 598 599 private Camera.PictureCallback mTestJpegListener = new Camera.PictureCallback() { 600 public void onPictureTaken(byte[] data, Camera mCamera) { 601 Log.v(TAG, "Shutter pressed down!"); 602 Bitmap inputImage; 603 try { 604 FileOutputStream outStream = new FileOutputStream( 605 String.format("/sdcard/metering%d.jpg", System.currentTimeMillis())); 606 outStream.write(data); 607 outStream.close(); 608 } catch (FileNotFoundException e) { 609 } catch (IOException e) {} 610 611 // Decodes the input data of the camera. 612 inputImage = BitmapFactory.decodeByteArray(data, 0, data.length); 613 614 // Records the memory address of the native image class instance. 615 long bufferAddress = findNative(inputImage); 616 Log.v(TAG, "findNative method finishes"); 617 618 // Cleans up the memory taken by the bitmap. 619 inputImage.recycle(); 620 data = null; 621 inputImage = null; 622 System.gc(); 623 624 // Add the image data to the native test handler. 625 createMeteringClass(bufferAddress, mTestHandler, 626 getCheckerCenter(), getCheckerRadius()); 627 mCamera.startPreview(); 628 629 // Releases thread lock after the image is processed. 630 synchronized (mProcessingImage) { 631 mProcessingImage.notifyAll(); 632 } 633 } 634 }; 635 636 /** 637 * Finds the coordinates of the grey squares on the color checker. 638 * The coordinates are computed by using the checker center and radius. 639 * The coordinates are converted to a system with (-1000, -1000) in the 640 * upper left corner and (1000, 1000) in the bottom right corner. 641 * 642 * @param greyCoordinates the array to store the coordinates of the grey 643 * squares 644 * @param checkerCenterAddress the memory address pointing to the vector 645 * storing the color checker's centers. 646 * @param checkerRadiusAddress the memory address pointing to the vetor 647 * storing the color checker's radius. 648 */ findGreyCoordinates(int[] greyCoordinates, long checkerCenterAddress, long checkerRadiusAddress)649 private native void findGreyCoordinates(int[] greyCoordinates, 650 long checkerCenterAddress, long checkerRadiusAddress); 651 652 /** 653 * Creates the native metering test handler with no debug image. 654 * 655 * @return the memory address pointing to the native test handler instance 656 */ createMeteringTest()657 private native long createMeteringTest(); 658 659 /** 660 * Adds the data from the native image class instance to the native test 661 * handler. 662 * 663 * @param bufferAddress the meory address of the native image class 664 * @param handlerAddress the memory address of the native test handler 665 * @param checkerCenterAddress the memory address of the checker cneters 666 * @param checkerRadiusAddress the meory address of the checker radius 667 */ createMeteringClass(long bufferAddress, long handlerAddress, long checkerCenterAddress, long checkerRadiusAddress)668 private native void createMeteringClass(long bufferAddress, long handlerAddress, 669 long checkerCenterAddress, 670 long checkerRadiusAddress); 671 672 /** 673 * Process the data stored in the native test handler and stores the 674 * comparison results. 675 * 676 * @param handlerAddress the memory address of the native test handler 677 * @param testCompareResults the boolean array to store the test comparison 678 * results 679 */ processMeteringTest(long handlerAddress, boolean[] testCompareResults)680 private native void processMeteringTest(long handlerAddress, boolean[] testCompareResults); 681 682 static { 683 System.loadLibrary("cameraanalyzer"); 684 } 685 } 686