194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin/* 294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Copyright (C) 2014 The Android Open Source Project 394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Licensed under the Apache License, Version 2.0 (the "License"); 594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * you may not use this file except in compliance with the License. 694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * You may obtain a copy of the License at 794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * http://www.apache.org/licenses/LICENSE-2.0 994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 1094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Unless required by applicable law or agreed to in writing, software 1194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * distributed under the License is distributed on an "AS IS" BASIS, 1294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * See the License for the specific language governing permissions and 1494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * limitations under the License. 1594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin */ 1694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 1772f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinpackage android.hardware.camera2.params; 1894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 1994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkinimport static com.android.internal.util.Preconditions.*; 2072f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinimport static android.hardware.camera2.params.RggbChannelVector.*; 2194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 2272f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinimport android.hardware.camera2.CaptureResult; 233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.utils.HashCodeHelpers; 2494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 2594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkinimport java.util.Arrays; 2694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 2794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin/** 2894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Immutable class for describing a {@code 4 x N x M} lens shading map of floats. 2994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 30574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk * @see CaptureResult#STATISTICS_LENS_SHADING_CORRECTION_MAP 3194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin */ 3294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkinpublic final class LensShadingMap { 3394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 3494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin /** 3594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * The smallest gain factor in this map. 3694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 3794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * <p>All values in this map will be at least this large.</p> 3894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin */ 3994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin public static final float MINIMUM_GAIN_FACTOR = 1.0f; 4094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 4194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin /** 4294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Create a new immutable LensShadingMap instance. 4394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 4494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * <p>The elements must be stored in a row-major order (fully packed).</p> 4594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 4694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * <p>This constructor takes over the array; do not write to the array afterwards.</p> 4794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 4894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @param elements 4994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * An array of elements whose length is 5094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * {@code RggbChannelVector.COUNT * rows * columns} 5194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 5294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @throws IllegalArgumentException 5394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * if the {@code elements} array length is invalid, 5494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * if any of the subelems are not finite or less than {@value #MINIMUM_GAIN_FACTOR}, 5594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * or if rows or columns is not positive 5694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @throws NullPointerException 5794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * if {@code elements} is {@code null} 5894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 5994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @hide 6094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin */ 6194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin public LensShadingMap(final float[] elements, final int rows, final int columns) { 6294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 6394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin mRows = checkArgumentPositive(rows, "rows must be positive"); 64574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk mColumns = checkArgumentPositive(columns, "columns must be positive"); 6594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin mElements = checkNotNull(elements, "elements must not be null"); 6694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 6794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin if (elements.length != getGainFactorCount()) { 6894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin throw new IllegalArgumentException("elements must be " + getGainFactorCount() + 69574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk " length, received " + elements.length); 7094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 7194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 7294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin // Every element must be finite and >= 1.0f 7394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin checkArrayElementsInRange(elements, MINIMUM_GAIN_FACTOR, Float.MAX_VALUE, "elements"); 7494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 7594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 7694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin /** 7794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Get the number of rows in this map. 7894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin */ 7994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin public int getRowCount() { 8094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin return mRows; 8194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 8294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 8394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin /** 8494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Get the number of columns in this map. 8594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin */ 8694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin public int getColumnCount() { 8794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin return mColumns; 8894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 8994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 9094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin /** 9194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Get the total number of gain factors in this map. 9294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 9394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * <p>A single gain factor contains exactly one color channel. 9494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Use with {@link #copyGainFactors} to allocate a large-enough array.</p> 9594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin */ 9694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin public int getGainFactorCount() { 9794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin return mRows * mColumns * COUNT; 9894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 9994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 10094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin /** 10194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Get a single color channel gain factor from this lens shading map by its row and column. 10294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 10394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * <p>The rows must be within the range [0, {@link #getRowCount}), 10494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * the column must be within the range [0, {@link #getColumnCount}), 10594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * and the color channel must be within the range [0, {@value RggbChannelVector#COUNT}).</p> 10694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 10794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * <p>The channel order is {@code [R, Geven, Godd, B]}, where 10894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * {@code Geven} is the green channel for the even rows of a Bayer pattern, and 10994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * {@code Godd} is the odd rows. 11094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * </p> 11194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 11294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @param colorChannel color channel from {@code [R, Geven, Godd, B]} 11394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @param column within the range [0, {@link #getColumnCount}) 11494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @param row within the range [0, {@link #getRowCount}) 11594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 11694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @return a gain factor >= {@value #MINIMUM_GAIN_FACTOR} 11794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 11894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @throws IllegalArgumentException if any of the parameters was out of range 11994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 12094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @see #RED 12194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @see #GREEN_EVEN 12294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @see #GREEN_ODD 12394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @see #BLUE 12494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @see #getRowCount 12594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @see #getColumnCount 12694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin */ 12794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin public float getGainFactor(final int colorChannel, final int column, final int row) { 12894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin if (colorChannel < 0 || colorChannel > COUNT) { 12994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin throw new IllegalArgumentException("colorChannel out of range"); 13094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } else if (column < 0 || column >= mColumns) { 13194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin throw new IllegalArgumentException("column out of range"); 13294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } else if (row < 0 || row >= mRows) { 13394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin throw new IllegalArgumentException("row out of range"); 13494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 13594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 13694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin return mElements[colorChannel + (row * mColumns + column) * COUNT ]; 13794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 13894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 13994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin /** 14094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Get a gain factor vector from this lens shading map by its row and column. 14194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 14294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * <p>The rows must be within the range [0, {@link #getRowCount}), 14394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * the column must be within the range [0, {@link #getColumnCount}).</p> 14494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 14594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @param column within the range [0, {@link #getColumnCount}) 14694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @param row within the range [0, {@link #getRowCount}) 14794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 14894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @return an {@link RggbChannelVector} where each gain factor >= {@value #MINIMUM_GAIN_FACTOR} 14994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 15094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @throws IllegalArgumentException if any of the parameters was out of range 15194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 15294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @see #getRowCount 15394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @see #getColumnCount 15494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin */ 15594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin public RggbChannelVector getGainFactorVector(final int column, final int row) { 15694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin if (column < 0 || column >= mColumns) { 15794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin throw new IllegalArgumentException("column out of range"); 15894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } else if (row < 0 || row >= mRows) { 15994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin throw new IllegalArgumentException("row out of range"); 16094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 16194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 16294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin final int offset = (row * mColumns + column) * COUNT; 16394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 16494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin final float red = 16594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin mElements[RED + offset]; 16694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin final float greenEven = 16794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin mElements[GREEN_EVEN + offset]; 16894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin final float greenOdd = 16994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin mElements[GREEN_ODD + offset]; 17094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin final float blue = 17194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin mElements[BLUE + offset]; 17294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 17394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin return new RggbChannelVector(red, greenEven, greenOdd, blue); 17494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 17594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 17694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin /** 17794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Copy all gain factors in row-major order from this lens shading map into the destination. 17894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 17994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * <p>Each gain factor will be >= {@link #MINIMUM_GAIN_FACTOR}.</p> 18094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 18194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @param destination 18294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * an array big enough to hold at least {@link RggbChannelVector#COUNT} 18394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * elements after the {@code offset} 18494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @param offset 18594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * a non-negative offset into the array 18694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @throws NullPointerException 18794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * If {@code destination} was {@code null} 18894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @throws IllegalArgumentException 18994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * If offset was negative 19094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @throws ArrayIndexOutOfBoundsException 19194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * If there's not enough room to write the elements at the specified destination and 19294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * offset. 19394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 19494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @see CaptureResult#STATISTICS_LENS_SHADING_MAP 19594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin */ 19694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin public void copyGainFactors(final float[] destination, final int offset) { 19794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin checkArgumentNonnegative(offset, "offset must not be negative"); 19894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin checkNotNull(destination, "destination must not be null"); 19994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin if (destination.length + offset < getGainFactorCount()) { 20094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin throw new ArrayIndexOutOfBoundsException("destination too small to fit elements"); 20194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 20294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 20394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin System.arraycopy(mElements, /*srcPos*/0, destination, offset, getGainFactorCount()); 20494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 20594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 20694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin /** 20794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * Check if this LensShadingMap is equal to another LensShadingMap. 20894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 20994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * <p>Two lens shading maps are equal if and only if they have the same rows/columns, 21094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * and all of their elements are {@link Object#equals equal}.</p> 21194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * 21294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * @return {@code true} if the objects were equal, {@code false} otherwise 21394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin */ 21494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin @Override 21594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin public boolean equals(final Object obj) { 21694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin if (obj == null) { 21794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin return false; 21894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 21994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin if (this == obj) { 22094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin return true; 22194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 22294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin if (obj instanceof LensShadingMap) { 22394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin final LensShadingMap other = (LensShadingMap) obj; 22494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin return mRows == other.mRows 22594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin && mColumns == other.mColumns 22694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin && Arrays.equals(mElements, other.mElements); 22794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 22894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin return false; 22994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 23094814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 23194814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin /** 23294814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin * {@inheritDoc} 23394814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin */ 23494814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin @Override 23594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin public int hashCode() { 23694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin int elemsHash = HashCodeHelpers.hashCode(mElements); 23794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin return HashCodeHelpers.hashCode(mRows, mColumns, elemsHash); 23894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin } 23994814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 24018be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh /** 24118be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh * Return the LensShadingMap as a string representation. 24218be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh * 24318be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh * <p> {@code "LensShadingMap{R:([%f, %f, ... %f], ... [%f, %f, ... %f]), G_even:([%f, %f, ... 24418be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh * %f], ... [%f, %f, ... %f]), G_odd:([%f, %f, ... %f], ... [%f, %f, ... %f]), B:([%f, %f, ... 24518be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh * %f], ... [%f, %f, ... %f])}"}, 24618be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh * where each {@code %f} represents one gain factor and each {@code [%f, %f, ... %f]} represents 24718be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh * a row of the lens shading map</p> 24818be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh * 24918be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh * @return string representation of {@link LensShadingMap} 25018be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh */ 25118be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh @Override 25218be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh public String toString() { 25318be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh StringBuilder str = new StringBuilder(); 25418be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh str.append("LensShadingMap{"); 25518be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh 25618be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh final String channelPrefix[] = {"R:(", "G_even:(", "G_odd:(", "B:("}; 25718be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh 25818be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh for (int ch = 0; ch < COUNT; ch++) { 25918be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh str.append(channelPrefix[ch]); 26018be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh 26118be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh for (int r = 0; r < mRows; r++) { 26218be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh str.append("["); 26318be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh for (int c = 0; c < mColumns; c++) { 26418be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh float gain = getGainFactor(ch, c, r); 26518be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh str.append(gain); 26618be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh if (c < mColumns - 1) { 26718be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh str.append(", "); 26818be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh } 26918be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh } 27018be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh str.append("]"); 27118be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh if (r < mRows - 1) { 27218be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh str.append(", "); 27318be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh } 27418be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh } 27518be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh 27618be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh str.append(")"); 27718be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh if (ch < COUNT - 1) { 27818be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh str.append(", "); 27918be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh } 28018be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh } 28118be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh 28218be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh str.append("}"); 28318be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh return str.toString(); 28418be00f77ab6d534d378f09bd254ad397ac10a7aYin-Chia Yeh } 28594814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin 28694814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin private final int mRows; 28794814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin private final int mColumns; 28894814218d2313a989a5a8969f633e3fc33e43071Igor Murashkin private final float[] mElements; 289574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk} 290