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.image.*; 021import java.util.*; 022 023/** 024 * A filter which uses the alpha channel of a "mask" image to interpolate between a source and destination image. 025 */ 026public class ApplyMaskFilter extends AbstractBufferedImageOp { 027 028 private BufferedImage destination; 029 private BufferedImage maskImage; 030 031 /** 032 * Construct an ApplyMaskFIlter. 033 */ 034 public ApplyMaskFilter() { 035 } 036 037 /** 038 * Construct an ApplyMaskFIlter. 039 * @param maskImage the mask image 040 * @param destination the destination image 041 */ 042 public ApplyMaskFilter( BufferedImage maskImage, BufferedImage destination ) { 043 this.maskImage = maskImage; 044 this.destination = destination; 045 } 046 047 /** 048 * Set the destination image. 049 * @param destination the destination image 050 * @see #getDestination 051 */ 052 public void setDestination( BufferedImage destination ) { 053 this.destination = destination; 054 } 055 056 /** 057 * Get the destination image. 058 * @return the destination image 059 * @see #setDestination 060 */ 061 public BufferedImage getDestination() { 062 return destination; 063 } 064 065 /** 066 * Set the mask image. 067 * @param maskImage the mask image 068 * @see #getMaskImage 069 */ 070 public void setMaskImage( BufferedImage maskImage ) { 071 this.maskImage = maskImage; 072 } 073 074 /** 075 * Get the mask image. 076 * @return the mask image 077 * @see #setMaskImage 078 */ 079 public BufferedImage getMaskImage() { 080 return maskImage; 081 } 082 083 /** 084 * Interpolates between two rasters according to the alpha level of a mask raster. 085 * @param src the source raster 086 * @param dst the destination raster 087 * @param sel the mask raster 088 */ 089 public static void composeThroughMask(Raster src, WritableRaster dst, Raster sel) { 090 int x = src.getMinX(); 091 int y = src.getMinY(); 092 int w = src.getWidth(); 093 int h = src.getHeight(); 094 095 int srcRGB[] = null; 096 int selRGB[] = null; 097 int dstRGB[] = null; 098 099 for ( int i = 0; i < h; i++ ) { 100 srcRGB = src.getPixels(x, y, w, 1, srcRGB); 101 selRGB = sel.getPixels(x, y, w, 1, selRGB); 102 dstRGB = dst.getPixels(x, y, w, 1, dstRGB); 103 104 int k = x; 105 for ( int j = 0; j < w; j++ ) { 106 int sr = srcRGB[k]; 107 int dir = dstRGB[k]; 108 int sg = srcRGB[k+1]; 109 int dig = dstRGB[k+1]; 110 int sb = srcRGB[k+2]; 111 int dib = dstRGB[k+2]; 112 int sa = srcRGB[k+3]; 113 int dia = dstRGB[k+3]; 114 115 float a = selRGB[k+3]/255f; 116 float ac = 1-a; 117 118 dstRGB[k] = (int)(a*sr + ac*dir); 119 dstRGB[k+1] = (int)(a*sg + ac*dig); 120 dstRGB[k+2] = (int)(a*sb + ac*dib); 121 dstRGB[k+3] = (int)(a*sa + ac*dia); 122 k += 4; 123 } 124 125 dst.setPixels(x, y, w, 1, dstRGB); 126 y++; 127 } 128 } 129 130 public BufferedImage filter( BufferedImage src, BufferedImage dst ) { 131 int width = src.getWidth(); 132 int height = src.getHeight(); 133 int type = src.getType(); 134 WritableRaster srcRaster = src.getRaster(); 135 136 if ( dst == null ) 137 dst = createCompatibleDestImage( src, null ); 138 WritableRaster dstRaster = dst.getRaster(); 139 140 if ( destination != null && maskImage != null ) 141 composeThroughMask( src.getRaster(), dst.getRaster(), maskImage.getRaster() ); 142 143 return dst; 144 } 145 146 public String toString() { 147 return "Keying/Key..."; 148 } 149}