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-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit http://imagingbook.com for additional details. 008 *******************************************************************************/ 009 010package imagingbook.lib.image; 011 012 013/* 014 * This class implements different schemes for accessing pixel values from 015 * a 2D image that is contained in a 1D array. 016 * 017 */ 018public abstract class PixelIndexer { 019 020 public static PixelIndexer create(int width, int height, OutOfBoundsStrategy mode) { 021 switch (mode) { 022 case DefaultValue : return new PixelIndexer.DefaultValueIndexer(width, height); 023 case NearestBorder : return new PixelIndexer.NearestBorderIndexer(width, height); 024 case MirrorImage : return new PixelIndexer.MirrorImageIndexer(width, height); 025 case Exception : return new PixelIndexer.ExceptionIndexer(width, height); 026 } 027 return null; 028 } 029 030 protected final int width; 031 protected final int height; 032 033 private PixelIndexer(int width, int height) { 034 this.width = width; 035 this.height = height; 036 } 037 038 public abstract int getIndex(int u, int v); 039 040 /* 041 * This indexer returns out of bounds pixel values that 042 * are taken from the closest border pixel. This is the 043 * most common method. 044 */ 045 public static class NearestBorderIndexer extends PixelIndexer { 046 NearestBorderIndexer(int width, int height) { 047 super(width, height); 048 } 049 050 public int getIndex(int u, int v) { 051 if (u < 0) 052 u = 0; 053 else if (u >= width) 054 u = width - 1; 055 if (v < 0) 056 v = 0; 057 else if (v >= height) 058 v = height - 1; 059 return width * v + u; 060 } 061 } 062 063 /* 064 * This index returns out of bound pixels taken from 065 * the mirrored image. 066 */ 067 public static class MirrorImageIndexer extends PixelIndexer { 068 MirrorImageIndexer(int width, int height) { 069 super(width, height); 070 } 071 072 public int getIndex(int u, int v) { 073 // this is a fast modulo operation for positive divisors only 074 u = u % width; 075 if (u < 0) u = u + width; 076 v = v % height; 077 if (v < 0) v = v + height; 078 return width * v + u; 079 } 080 } 081 082 /* 083 * This indexer returns -1 for out of bounds pixels to 084 * indicate that a (predefined) default value should be used. 085 */ 086 public static class DefaultValueIndexer extends PixelIndexer { 087 DefaultValueIndexer(int width, int height) { 088 super(width, height); 089 } 090 091 public int getIndex(int u, int v) { 092 if (u < 0 || u >= width || v < 0 || v >= height) 093 return -1; 094 else 095 return width * v + u; 096 } 097 } 098 099 /* 100 * This indexer throws an exception if out of bounds pixels 101 * are accessed. 102 */ 103 public static class ExceptionIndexer extends PixelIndexer { 104 ExceptionIndexer(int width, int height) { 105 super(width, height); 106 } 107 108 public int getIndex(int u, int v) { 109 if (u < 0 || u >= width || v < 0 || v >= height) { 110 throw new ArrayIndexOutOfBoundsException(); 111 } 112 else 113 return width * v + u; 114 } 115 } 116 117} 118 119