001/* 002Copyright 2006 Jerry Huxtable 003 004Licensed under the Apache License, Version 2.0 (the "License"); 005you may not use this file except in compliance with the License. 006You may obtain a copy of the License at 007 008 http://www.apache.org/licenses/LICENSE-2.0 009 010Unless required by applicable law or agreed to in writing, software 011distributed under the License is distributed on an "AS IS" BASIS, 012WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013See the License for the specific language governing permissions and 014limitations under the License. 015*/ 016 017package com.jhlabs.math; 018 019import java.awt.*; 020import java.awt.image.*; 021import com.jhlabs.image.*; 022 023public class ImageFunction2D implements Function2D { 024 025 public final static int ZERO = 0; 026 public final static int CLAMP = 1; 027 public final static int WRAP = 2; 028 029 protected int[] pixels; 030 protected int width; 031 protected int height; 032 protected int edgeAction = ZERO; 033 protected boolean alpha = false; 034 035 public ImageFunction2D(BufferedImage image) { 036 this(image, false); 037 } 038 039 public ImageFunction2D(BufferedImage image, boolean alpha) { 040 this(image, ZERO, alpha); 041 } 042 043 public ImageFunction2D(BufferedImage image, int edgeAction, boolean alpha) { 044 init( getRGB( image, 0, 0, image.getWidth(), image.getHeight(), null), image.getWidth(), image.getHeight(), edgeAction, alpha); 045 } 046 047 public ImageFunction2D(int[] pixels, int width, int height, int edgeAction, boolean alpha) { 048 init(pixels, width, height, edgeAction, alpha); 049 } 050 051 public ImageFunction2D(Image image) { 052 this( image, ZERO, false ); 053 } 054 055 public ImageFunction2D(Image image, int edgeAction, boolean alpha) { 056 PixelGrabber pg = new PixelGrabber(image, 0, 0, -1, -1, null, 0, -1); 057 try { 058 pg.grabPixels(); 059 } catch (InterruptedException e) { 060 throw new RuntimeException("interrupted waiting for pixels!"); 061 } 062 if ((pg.status() & ImageObserver.ABORT) != 0) { 063 throw new RuntimeException("image fetch aborted"); 064 } 065 init((int[])pg.getPixels(), pg.getWidth(), pg.getHeight(), edgeAction, alpha); 066 } 067 068 /** 069 * A convenience method for getting ARGB pixels from an image. This tries to avoid the performance 070 * penalty of BufferedImage.getRGB unmanaging the image. 071 */ 072 public int[] getRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) { 073 int type = image.getType(); 074 if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB ) 075 return (int [])image.getRaster().getDataElements( x, y, width, height, pixels ); 076 return image.getRGB( x, y, width, height, pixels, 0, width ); 077 } 078 079 public void init(int[] pixels, int width, int height, int edgeAction, boolean alpha) { 080 this.pixels = pixels; 081 this.width = width; 082 this.height = height; 083 this.edgeAction = edgeAction; 084 this.alpha = alpha; 085 } 086 087 public float evaluate(float x, float y) { 088 int ix = (int)x; 089 int iy = (int)y; 090 if (edgeAction == WRAP) { 091 ix = ImageMath.mod(ix, width); 092 iy = ImageMath.mod(iy, height); 093 } else if (ix < 0 || iy < 0 || ix >= width || iy >= height) { 094 if (edgeAction == ZERO) 095 return 0; 096 if (ix < 0) 097 ix = 0; 098 else if (ix >= width) 099 ix = width-1; 100 if (iy < 0) 101 iy = 0; 102 else if (iy >= height) 103 iy = height-1; 104 } 105 return alpha ? ((pixels[iy*width+ix] >> 24) & 0xff) / 255.0f : PixelUtils.brightness(pixels[iy*width+ix]) / 255.0f; 106 } 107 108 public void setEdgeAction(int edgeAction) { 109 this.edgeAction = edgeAction; 110 } 111 112 public int getEdgeAction() { 113 return edgeAction; 114 } 115 116 public int getWidth() { 117 return width; 118 } 119 120 public int getHeight() { 121 return height; 122 } 123 124 public int[] getPixels() { 125 return pixels; 126 } 127} 128