/* * Copyright (c) 2009 Piotr Piastucki * * This file is part of Patchca CAPTCHA library. * * Patchca is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Patchca is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Patchca. If not, see <http://www.gnu.org/licenses/>. */ package com.xiongyingqi.captcha.filter.library; import java.awt.*; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; public abstract class AbstractImageOp implements BufferedImageOp { public static final int EDGE_ZERO = 0; public static final int EDGE_MIRROR = 1; public static final int EDGE_CLAMP = 2; protected int edgeMode; protected RenderingHints hints; public int getEdgeMode() { return edgeMode; } public void setEdgeMode(int edgeMode) { this.edgeMode = edgeMode; } protected int getPixel(int pixels[], int x, int y, int width, int height, int edgeMode) { if (x >= 0 && x < width && y >= 0 && y < height) { return pixels[x + y * width]; } else if (edgeMode == EDGE_ZERO) { return 0; } else if (edgeMode == EDGE_CLAMP) { if (x < 0) { x = 0; } else if (x >= width) { x = width - 1; } if (y < 0) { y = 0; } else if (y >= height) { y = height - 1; } return pixels[x + y * width]; } else { if (x < 0) { x = -x; } else if (x >= width) { x = width + width - x - 1; } if (y < 0) { y = -y; } else if (y > height) { y = height = height - y - 1; } try { return pixels[x + y * width]; } catch (Exception e) { return 0; } } } private int linear(int from, int to, int shift, double d) { return ((int) Math.floor(((from >> shift) & 0xff) + d * (((to >> shift) & 0xff) - ((from >> shift) & 0xff)))) << shift; } private int linear(int from, int to, double d) { int c = 0; for (int i = 0; i < 4; i++) { c += linear(from, to, i * 8, d); } return c; } protected int bilinear(int nw, int ne, int sw, int se, double xd, double yd) { return linear(linear(nw, ne, xd), linear(sw, se, xd), yd); } protected int getPixelBilinear(int pixels[], double x, double y, int width, int height, int edgeMode) { int xi = (int) Math.floor(x); int yi = (int) Math.floor(y); double xd = x - xi; double yd = y - yi; int nw = getPixel(pixels, xi, yi, width, height, edgeMode); int ne = getPixel(pixels, xi + 1, yi, width, height, edgeMode); int sw = getPixel(pixels, xi, yi + 1, width, height, edgeMode); int se = getPixel(pixels, xi + 1, yi + 1, width, height, edgeMode); return bilinear(nw, ne, sw, se, xd, yd); } protected int limit(int v, int min, int max) { if (v < min) { v = min; } else if (v > max) { v = max; } return v; } protected int limitByte(int v) { return limit(v, 0, 255); } protected void filter(int[] inPixels, int[] outPixels, int width, int height) { } @Override public BufferedImage filter(BufferedImage src, BufferedImage dest) { if (dest == null) { dest = createCompatibleDestImage(src, null); } int width = src.getWidth(); int height = src.getHeight(); int[] inPixels = new int[width * height]; int[] outPixels = new int[width * height]; src.getRaster().getDataElements(0, 0, width, height, inPixels); filter(inPixels, outPixels, width, height); dest.getRaster().setDataElements(0, 0, width, height, outPixels); return dest; } @Override public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) { if (destCM == null) { destCM = src.getColorModel(); if (destCM instanceof IndexColorModel) { destCM = ColorModel.getRGBdefault(); } } return new BufferedImage(destCM, destCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), destCM.isAlphaPremultiplied(), null); } @Override public Rectangle2D getBounds2D(BufferedImage src) { return src.getRaster().getBounds(); } @Override public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) { if (dstPt == null) { dstPt = new Point2D.Float(); } dstPt.setLocation(srcPt.getX(), srcPt.getY()); return dstPt; } @Override public RenderingHints getRenderingHints() { return hints; } }