152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk/* 252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * Copyright (C) 2014 The Android Open Source Project 352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * you may not use this file except in compliance with the License. 652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * You may obtain a copy of the License at 752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * http://www.apache.org/licenses/LICENSE-2.0 952842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 1052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * Unless required by applicable law or agreed to in writing, software 1152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 1252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * See the License for the specific language governing permissions and 1452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * limitations under the License. 1552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk */ 1652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk 1752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunkpackage android.hardware.camera2.params; 1852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk 1952842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunkimport java.util.Arrays; 2052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk 2152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunkimport static com.android.internal.util.Preconditions.checkNotNull; 2252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk 2352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk/** 2452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * Immutable class to store a 4-element vector of integers corresponding to a 2x2 pattern 2552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * of color channel offsets used for the black level offsets of each color channel. 2652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk */ 2752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunkpublic final class BlackLevelPattern { 2852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk 2952842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk /** 3052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * The number of offsets in this vector. 3152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk */ 3252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk public static final int COUNT = 4; 3352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk 3452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk /** 3552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * Create a new {@link BlackLevelPattern} from a given offset array. 3652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 3752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * <p>The given offset array must contain offsets for each color channel in 3852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * a 2x2 pattern corresponding to the color filter arrangement. Offsets are 3952842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * given in row-column scan order.</p> 4052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 4152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @param offsets an array containing a 2x2 pattern of offsets. 4252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 4352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @throws IllegalArgumentException if the given array has an incorrect length. 4452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @throws NullPointerException if the given array is null. 4552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @hide 4652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk */ 4752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk public BlackLevelPattern(int[] offsets) { 4852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk if (offsets == null) { 4952842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk throw new NullPointerException("Null offsets array passed to constructor"); 5052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } 5152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk if (offsets.length < COUNT) { 5252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk throw new IllegalArgumentException("Invalid offsets array length"); 5352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } 5452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk mCfaOffsets = Arrays.copyOf(offsets, COUNT); 5552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } 5652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk 5752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk /** 5852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * Return the color channel offset for a given index into the array of raw pixel values. 5952842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 6052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @param column the column index in the the raw pixel array. 6152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @param row the row index in the raw pixel array. 6252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @return a color channel offset. 6352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 6452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @throws IllegalArgumentException if a column or row given is negative. 6552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk */ 6652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk public int getOffsetForIndex(int column, int row) { 6752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk if (row < 0 || column < 0) { 6852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk throw new IllegalArgumentException("column, row arguments must be positive"); 6952842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } 7052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk return mCfaOffsets[((row & 1) << 1) | (column & 1)]; 7152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } 7252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk 7352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk /** 7452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * Copy the ColorChannel offsets into the destination vector. 7552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 7652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * <p>Offsets are given in row-column scan order for a given 2x2 color pattern.</p> 7752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 7852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @param destination an array big enough to hold at least {@value #COUNT} elements after the 7952842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * {@code offset} 8052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @param offset a non-negative offset into the array 8152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 8252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @throws IllegalArgumentException if the offset is invalid. 8352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @throws ArrayIndexOutOfBoundsException if the destination vector is too small. 8452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @throws NullPointerException if the destination is null. 8552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk */ 8652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk public void copyTo(int[] destination, int offset) { 8752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk checkNotNull(destination, "destination must not be null"); 8852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk if (offset < 0) { 8952842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk throw new IllegalArgumentException("Null offset passed to copyTo"); 9052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } 9152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk if (destination.length - offset < COUNT) { 9252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk throw new ArrayIndexOutOfBoundsException("destination too small to fit elements"); 9352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } 9452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk for (int i = 0; i < COUNT; ++i) { 9552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk destination[offset + i] = mCfaOffsets[i]; 9652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } 9752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } 9852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk 9952842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk /** 10052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * Check if this {@link BlackLevelPattern} is equal to another {@link BlackLevelPattern}. 10152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 10252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p> 10352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * 10452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * @return {@code true} if the objects were equal, {@code false} otherwise 10552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk */ 10652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk @Override 10752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk public boolean equals(Object obj) { 10852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk if (obj == null) { 10952842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk return false; 11052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } else if (this == obj) { 11152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk return true; 11252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } else if (obj instanceof BlackLevelPattern) { 11352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk final BlackLevelPattern other = (BlackLevelPattern) obj; 11452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk return Arrays.equals(other.mCfaOffsets, mCfaOffsets); 11552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } 11652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk return false; 11752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } 11852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk 11952842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk /** 12052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk * {@inheritDoc} 12152842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk */ 12252842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk @Override 12352842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk public int hashCode() { 12452842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk return Arrays.hashCode(mCfaOffsets); 12552842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk } 12652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk 127310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen /** 128310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen * Return this {@link BlackLevelPattern} as a string representation. 129310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen * 130310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen * <p> {@code "BlackLevelPattern([%d, %d], [%d, %d])"}, where each {@code %d} represents one 131310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen * black level offset of a color channel. The values are in the same order as channels listed 132310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen * for the CFA layout key (see 133310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT}). 134310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen * </p> 135310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen * 136310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen * @return string representation of {@link BlackLevelPattern} 137310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen * 138310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen * @see android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT 139310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen */ 140310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen @Override 141310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen public String toString() { 142310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen return String.format("BlackLevelPattern([%d, %d], [%d, %d])", mCfaOffsets[0], 143310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen mCfaOffsets[1], mCfaOffsets[2], mCfaOffsets[3]); 144310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen } 145310f381eac558bce069b52fbda9a8aeb83608858Chien-Yu Chen 14652842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk private final int[] mCfaOffsets; 14752842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk} 148