001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2023 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit https://imagingbook.com for additional details. 008 ******************************************************************************/ 009package imagingbook.common.image.access; 010 011import ij.process.ImageProcessor; 012import imagingbook.common.image.OutOfBoundsStrategy; 013import imagingbook.common.image.interpolation.InterpolationMethod; 014 015/** 016 * Accessor for vector-valued images with arbitrary depth (number of components). 017 */ 018public abstract class VectorAccessor extends ImageAccessor { 019 020 final int depth; 021 final ScalarAccessor[] componentAccessors; 022 023 VectorAccessor(ImageProcessor ip, int depth, OutOfBoundsStrategy obs, InterpolationMethod ipm) { 024 super(ip, obs, ipm); 025 this.depth = depth; 026 this.componentAccessors = new ScalarAccessor[this.depth]; 027 for (int k = 0; k < depth; k++) { 028 componentAccessors[k] = makeComponentAccessor(k); 029 } 030 } 031 032 /** 033 * To be implemented by all real sublasses of {@link ScalarAccessor}, who know how to create an accessor object to 034 * their k-th component. See {@link RgbAccessor#makeComponentAccessor(int)} for an example. 035 * 036 * @param k the component index 037 * @return the image accessor for the specified component 038 */ 039 abstract ScalarAccessor makeComponentAccessor(int k); 040 041 @Override 042 public int getDepth() { 043 return this.depth; 044 } 045 046 @Override 047 public ScalarAccessor getComponentAccessor(int k) { 048 checkComponentIndex(k); 049 return componentAccessors[k]; 050 } 051 052 @Override 053 public float getVal(int u, int v, int k) { 054 checkComponentIndex(k); 055 return componentAccessors[k].getVal(u, v); 056 } 057 058 @Override 059 public float getVal(double x, double y, int k) { 060 checkComponentIndex(k); 061 return componentAccessors[k].getVal(x, y); 062 } 063 064 @Override 065 public void setVal(int u, int v, int k, float val) { 066 checkComponentIndex(k); 067 componentAccessors[k].setVal(u, v, val); 068 } 069 070 // --------------------------------------------------------------------- 071 072// @Override 073// public void setDefaultValue(float val) { 074// for (int k = 0; k < depth; k++) { 075// componentAccessors[k].setDefaultValue(val); 076// } 077// } 078 079// @Override 080// public void setDefaultValue(float[] vals) { 081// if (vals.length != depth) { 082// throw new IllegalArgumentException("default values must be of length " + depth); 083// } 084// for (int k = 0; k < depth; k++) { 085// componentAccessors[k].setDefaultValue(vals[k]); 086// } 087// } 088 089 @Override 090 void checkComponentIndex(int k) { 091 if (k < 0 || k >= depth) { 092 throw new IllegalArgumentException("invalid component index " + k); 093 } 094 } 095 096}