001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019/* 020* 021 022Licensed under the Apache License, Version 2.0 (the "License"); 023you may not use this file except in compliance with the License. 024You may obtain a copy of the License at 025 026 http://www.apache.org/licenses/LICENSE-2.0 027 028Unless required by applicable law or agreed to in writing, software 029distributed under the License is distributed on an "AS IS" BASIS, 030WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 031See the License for the specific language governing permissions and 032limitations under the License. 033*/ 034 035package lucee.runtime.img.math; 036 037import java.awt.Image; 038import java.awt.image.BufferedImage; 039import java.awt.image.ImageObserver; 040import java.awt.image.PixelGrabber; 041 042import lucee.runtime.img.filter.ImageMath; 043import lucee.runtime.img.filter.PixelUtils; 044 045public class ImageFunction2D implements Function2D { 046 047 public final static int ZERO = 0; 048 public final static int CLAMP = 1; 049 public final static int WRAP = 2; 050 051 protected int[] pixels; 052 protected int width; 053 protected int height; 054 protected int edgeAction = ZERO; 055 protected boolean alpha = false; 056 057 public ImageFunction2D(BufferedImage image) { 058 this(image, false); 059 } 060 061 public ImageFunction2D(BufferedImage image, boolean alpha) { 062 this(image, ZERO, alpha); 063 } 064 065 public ImageFunction2D(BufferedImage image, int edgeAction, boolean alpha) { 066 init( getRGB( image, 0, 0, image.getWidth(), image.getHeight(), null), image.getWidth(), image.getHeight(), edgeAction, alpha); 067 } 068 069 public ImageFunction2D(int[] pixels, int width, int height, int edgeAction, boolean alpha) { 070 init(pixels, width, height, edgeAction, alpha); 071 } 072 073 public ImageFunction2D(Image image) { 074 this( image, ZERO, false ); 075 } 076 077 public ImageFunction2D(Image image, int edgeAction, boolean alpha) { 078 PixelGrabber pg = new PixelGrabber(image, 0, 0, -1, -1, null, 0, -1); 079 try { 080 pg.grabPixels(); 081 } catch (InterruptedException e) { 082 throw new RuntimeException("interrupted waiting for pixels!"); 083 } 084 if ((pg.status() & ImageObserver.ABORT) != 0) { 085 throw new RuntimeException("image fetch aborted"); 086 } 087 init((int[])pg.getPixels(), pg.getWidth(), pg.getHeight(), edgeAction, alpha); 088 } 089 090 /** 091 * A convenience method for getting ARGB pixels from an image. This tries to avoid the performance 092 * penalty of BufferedImage.getRGB unmanaging the image. 093 */ 094 public int[] getRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) { 095 int type = image.getType(); 096 if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB ) 097 return (int [])image.getRaster().getDataElements( x, y, width, height, pixels ); 098 return image.getRGB( x, y, width, height, pixels, 0, width ); 099 } 100 101 public void init(int[] pixels, int width, int height, int edgeAction, boolean alpha) { 102 this.pixels = pixels; 103 this.width = width; 104 this.height = height; 105 this.edgeAction = edgeAction; 106 this.alpha = alpha; 107 } 108 109 public float evaluate(float x, float y) { 110 int ix = (int)x; 111 int iy = (int)y; 112 if (edgeAction == WRAP) { 113 ix = ImageMath.mod(ix, width); 114 iy = ImageMath.mod(iy, height); 115 } else if (ix < 0 || iy < 0 || ix >= width || iy >= height) { 116 if (edgeAction == ZERO) 117 return 0; 118 if (ix < 0) 119 ix = 0; 120 else if (ix >= width) 121 ix = width-1; 122 if (iy < 0) 123 iy = 0; 124 else if (iy >= height) 125 iy = height-1; 126 } 127 return alpha ? ((pixels[iy*width+ix] >> 24) & 0xff) / 255.0f : PixelUtils.brightness(pixels[iy*width+ix]) / 255.0f; 128 } 129 130 public void setEdgeAction(int edgeAction) { 131 this.edgeAction = edgeAction; 132 } 133 134 public int getEdgeAction() { 135 return edgeAction; 136 } 137 138 public int getWidth() { 139 return width; 140 } 141 142 public int getHeight() { 143 return height; 144 } 145 146 public int[] getPixels() { 147 return pixels; 148 } 149} 150