001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.image; 031 032import org.openimaj.image.processor.KernelProcessor; 033import org.openimaj.image.processor.SinglebandImageProcessor; 034import org.openimaj.image.processor.SinglebandKernelProcessor; 035 036/** 037 * A base class for representing a single band image of any pixel type. 038 * 039 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 040 * @param <Q> 041 * The pixel type 042 * @param <I> 043 * The concrete image subclass type. 044 */ 045public abstract class SingleBandImage<Q extends Comparable<Q>, I extends SingleBandImage<Q, I>> 046 extends 047 Image<Q, I> 048 implements 049 SinglebandImageProcessor.Processable<Q, I, I>, 050 SinglebandKernelProcessor.Processable<Q, I, I> 051{ 052 private static final long serialVersionUID = 1L; 053 054 /** The image height */ 055 public int height; 056 057 /** The image width */ 058 public int width; 059 060 /** 061 * {@inheritDoc} 062 * 063 * @see org.openimaj.image.Image#getHeight() 064 */ 065 @Override 066 public int getHeight() { 067 return height; 068 } 069 070 /** 071 * {@inheritDoc} 072 * 073 * @see org.openimaj.image.Image#getWidth() 074 */ 075 @Override 076 public int getWidth() { 077 return width; 078 } 079 080 /** 081 * {@inheritDoc} 082 * 083 * @see org.openimaj.image.Image#process(org.openimaj.image.processor.KernelProcessor) 084 */ 085 @Override 086 public I process(KernelProcessor<Q, I> p) { 087 return process(p, false); 088 } 089 090 /** 091 * {@inheritDoc} 092 * 093 * @see org.openimaj.image.Image#process(org.openimaj.image.processor.KernelProcessor, 094 * boolean) 095 */ 096 @Override 097 public I process(KernelProcessor<Q, I> p, boolean pad) { 098 final I newImage = newInstance(width, height); 099 final I tmp = newInstance(p.getKernelWidth(), p.getKernelHeight()); 100 101 final int hh = p.getKernelHeight() / 2; 102 final int hw = p.getKernelWidth() / 2; 103 104 if (!pad) { 105 for (int y = hh; y < getHeight() - (p.getKernelHeight() - hh); y++) { 106 for (int x = hw; x < getWidth() - (p.getKernelWidth() - hw); x++) { 107 newImage.setPixel(x, y, p.processKernel(this.extractROI(x, y, tmp))); 108 } 109 } 110 } else { 111 for (int y = 0; y < getHeight(); y++) { 112 for (int x = 0; x < getWidth(); x++) { 113 newImage.setPixel(x, y, p.processKernel(this.extractROI(x, y, tmp))); 114 } 115 } 116 } 117 118 return newImage; 119 } 120 121 /** 122 * {@inheritDoc} 123 * 124 * @see org.openimaj.image.processor.SinglebandKernelProcessor.Processable#process(org.openimaj.image.processor.SinglebandKernelProcessor) 125 */ 126 @Override 127 public I process(SinglebandKernelProcessor<Q, I> p) { 128 return process(p, false); 129 } 130 131 /** 132 * {@inheritDoc} 133 * 134 * @see org.openimaj.image.processor.SinglebandKernelProcessor.Processable#process(org.openimaj.image.processor.SinglebandKernelProcessor, 135 * boolean) 136 */ 137 @Override 138 public I process(SinglebandKernelProcessor<Q, I> p, boolean pad) { 139 final I newImage = newInstance(width, height); 140 final I tmp = newInstance(p.getKernelWidth(), p.getKernelHeight()); 141 142 final int hh = p.getKernelHeight() / 2; 143 final int hw = p.getKernelWidth() / 2; 144 145 if (!pad) { 146 for (int y = hh; y < getHeight() - (p.getKernelHeight() - hh); y++) { 147 for (int x = hw; x < getWidth() - (p.getKernelWidth() - hw); x++) { 148 newImage.setPixel(x, y, p.processKernel(this.extractROI(x, y, tmp))); 149 } 150 } 151 } else { 152 for (int y = 0; y < getHeight(); y++) { 153 for (int x = 0; x < getWidth(); x++) { 154 newImage.setPixel(x, y, p.processKernel(this.extractROI(x, y, tmp))); 155 } 156 } 157 } 158 159 return newImage; 160 } 161 162 /** 163 * {@inheritDoc} 164 * 165 * @see org.openimaj.image.processor.SinglebandKernelProcessor.Processable#processInplace(org.openimaj.image.processor.SinglebandKernelProcessor) 166 */ 167 @Override 168 public I processInplace(SinglebandKernelProcessor<Q, I> p) { 169 return processInplace(p, false); 170 } 171 172 /** 173 * {@inheritDoc} 174 * 175 * @see org.openimaj.image.processor.SinglebandKernelProcessor.Processable#processInplace(org.openimaj.image.processor.SinglebandKernelProcessor, 176 * boolean) 177 */ 178 @Override 179 @SuppressWarnings("unchecked") 180 public I processInplace(SinglebandKernelProcessor<Q, I> p, boolean pad) { 181 final I newImage = process(p, pad); 182 this.internalAssign(newImage); 183 return (I) this; 184 } 185 186 /** 187 * {@inheritDoc} 188 * 189 * @see org.openimaj.image.processor.SinglebandImageProcessor.Processable#process(org.openimaj.image.processor.SinglebandImageProcessor) 190 */ 191 @Override 192 public I process(SinglebandImageProcessor<Q, I> p) { 193 final I newImage = this.clone(); 194 newImage.processInplace(p); 195 return newImage; 196 } 197 198 /** 199 * {@inheritDoc} 200 * 201 * @see org.openimaj.image.processor.SinglebandImageProcessor.Processable#processInplace(org.openimaj.image.processor.SinglebandImageProcessor) 202 */ 203 @SuppressWarnings("unchecked") 204 @Override 205 public I processInplace(SinglebandImageProcessor<Q, I> p) { 206 p.processImage((I) this); 207 return (I) this; 208 } 209 210 /** 211 * {@inheritDoc} 212 * 213 * @see org.openimaj.image.Image#fill(java.lang.Object) 214 */ 215 @SuppressWarnings("unchecked") 216 @Override 217 public I fill(Q colour) { 218 for (int y = 0; y < getHeight(); y++) 219 for (int x = 0; x < getWidth(); x++) 220 this.setPixel(x, y, colour); 221 222 return (I) this; 223 } 224 225 /** 226 * {@inheritDoc} 227 * 228 * @see org.openimaj.image.Image#clone() 229 */ 230 @Override 231 public abstract I clone(); 232 233 @Override 234 public boolean equals(Object obj) { 235 @SuppressWarnings("unchecked") 236 final I that = (I) obj; 237 for (int y = 0; y < getHeight(); y++) 238 for (int x = 0; x < getWidth(); x++) 239 { 240 final boolean fail = !this.getPixel(x, y).equals(that.getPixel(x, y)); 241 if (fail) 242 return false; 243 } 244 245 return true; 246 } 247}