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.image; 018 019import java.awt.*; 020import java.awt.event.*; 021import java.awt.image.*; 022 023/** 024 * A filter for warping images using the gridwarp algorithm. 025 * You need to supply two warp grids, one for the source image and 026 * one for the destination image. The image will be warped so that 027 * a point in the source grid moves to its counterpart in the destination 028 * grid. 029 */ 030public class WarpFilter extends WholeImageFilter { 031 032 private WarpGrid sourceGrid; 033 private WarpGrid destGrid; 034 private int frames = 1; 035 036 private BufferedImage morphImage; 037 private float time; 038 039 /** 040 * Create a WarpFilter. 041 */ 042 public WarpFilter() { 043 } 044 045 /** 046 * Create a WarpFilter with two warp grids. 047 * @param sourceGrid the source grid 048 * @param destGrid the destination grid 049 */ 050 public WarpFilter(WarpGrid sourceGrid, WarpGrid destGrid) { 051 this.sourceGrid = sourceGrid; 052 this.destGrid = destGrid; 053 } 054 055 /** 056 * Set the source warp grid. 057 * @param sourceGrid the source grid 058 * @see #getSourceGrid 059 */ 060 public void setSourceGrid(WarpGrid sourceGrid) { 061 this.sourceGrid = sourceGrid; 062 } 063 064 /** 065 * Get the source warp grid. 066 * @return the source grid 067 * @see #setSourceGrid 068 */ 069 public WarpGrid getSourceGrid() { 070 return sourceGrid; 071 } 072 073 /** 074 * Set the destination warp grid. 075 * @param destGrid the destination grid 076 * @see #getDestGrid 077 */ 078 public void setDestGrid(WarpGrid destGrid) { 079 this.destGrid = destGrid; 080 } 081 082 /** 083 * Get the destination warp grid. 084 * @return the destination grid 085 * @see #setDestGrid 086 */ 087 public WarpGrid getDestGrid() { 088 return destGrid; 089 } 090 091 public void setFrames(int frames) { 092 this.frames = frames; 093 } 094 095 public int getFrames() { 096 return frames; 097 } 098 099 /** 100 * For morphing, sets the image we're morphing to. If not, set then we're just warping. 101 */ 102 public void setMorphImage(BufferedImage morphImage) { 103 this.morphImage = morphImage; 104 } 105 106 public BufferedImage getMorphImage() { 107 return morphImage; 108 } 109 110 public void setTime(float time) { 111 this.time = time; 112 } 113 114 public float getTime() { 115 return time; 116 } 117 118 protected void transformSpace(Rectangle r) { 119 r.width *= frames; 120 } 121 122 protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { 123 int[] outPixels = new int[width * height]; 124 125 if ( morphImage != null ) { 126 int[] morphPixels = getRGB( morphImage, 0, 0, width, height, null ); 127 morph( inPixels, morphPixels, outPixels, sourceGrid, destGrid, width, height, time ); 128 } else if (frames <= 1) { 129 sourceGrid.warp(inPixels, width, height, sourceGrid, destGrid, outPixels); 130 } else { 131 WarpGrid newGrid = new WarpGrid(sourceGrid.rows, sourceGrid.cols, width, height); 132 for (int i = 0; i < frames; i++) { 133 float t = (float)i/(frames-1); 134 sourceGrid.lerp(t, destGrid, newGrid); 135 sourceGrid.warp(inPixels, width, height, sourceGrid, newGrid, outPixels); 136 } 137 } 138 return outPixels; 139 } 140 141 public void morph(int[] srcPixels, int[] destPixels, int[] outPixels, WarpGrid srcGrid, WarpGrid destGrid, int width, int height, float t) { 142 WarpGrid newGrid = new WarpGrid(srcGrid.rows, srcGrid.cols, width, height); 143 srcGrid.lerp(t, destGrid, newGrid); 144 srcGrid.warp(srcPixels, width, height, srcGrid, newGrid, outPixels); 145 int[] destPixels2 = new int[width * height]; 146 destGrid.warp(destPixels, width, height, destGrid, newGrid, destPixels2); 147 crossDissolve(outPixels, destPixels2, width, height, t); 148 } 149 150 public void crossDissolve(int[] pixels1, int[] pixels2, int width, int height, float t) { 151 int index = 0; 152 for (int y = 0; y < height; y++) { 153 for (int x = 0; x < width; x++) { 154 pixels1[index] = ImageMath.mixColors(t, pixels1[index], pixels2[index]); 155 index++; 156 } 157 } 158 } 159 160 public String toString() { 161 return "Distort/Mesh Warp..."; 162 } 163 164} 165