001    /*
002    *
003    
004    Licensed under the Apache License, Version 2.0 (the "License");
005    you may not use this file except in compliance with the License.
006    You may obtain a copy of the License at
007    
008       http://www.apache.org/licenses/LICENSE-2.0
009    
010    Unless required by applicable law or agreed to in writing, software
011    distributed under the License is distributed on an "AS IS" BASIS,
012    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013    See the License for the specific language governing permissions and
014    limitations under the License.
015    */
016    
017    package railo.runtime.img.composite;
018    
019    import java.awt.Composite;
020    import java.awt.CompositeContext;
021    import java.awt.image.ColorModel;
022    import java.awt.image.Raster;
023    import java.awt.image.WritableRaster;
024    
025    public abstract class RGBComposite implements Composite {
026    
027            protected float extraAlpha;
028    
029            public RGBComposite() {
030                    this( 1.0f );
031            }
032    
033            public RGBComposite( float alpha ) {
034                    if ( alpha < 0.0f || alpha > 1.0f )
035                            throw new IllegalArgumentException("RGBComposite: alpha must be between 0 and 1");
036                    this.extraAlpha = alpha;
037            }
038    
039            public float getAlpha() {
040                    return extraAlpha;
041            }
042    
043            public int hashCode() {
044                    return Float.floatToIntBits(extraAlpha);
045            }
046    
047            public boolean equals(Object o) {
048                    if (!(o instanceof RGBComposite))
049                            return false;
050                    RGBComposite c = (RGBComposite)o;
051    
052                    if ( extraAlpha != c.extraAlpha )
053                            return false;
054                    return true;
055            }
056    
057        public abstract static class RGBCompositeContext implements CompositeContext {
058    
059            private float alpha;
060            private ColorModel srcColorModel;
061            private ColorModel dstColorModel;
062    
063            public RGBCompositeContext( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) {
064                this.alpha = alpha;
065                this.srcColorModel = srcColorModel;
066                this.dstColorModel = dstColorModel;
067            }
068    
069            public void dispose() {
070            }
071            
072            // Multiply two numbers in the range 0..255 such that 255*255=255
073            static int multiply255( int a, int b ) {
074                int t = a * b + 0x80;
075                return ((t >> 8) + t) >> 8;
076            }
077            
078            static int clamp( int a ) {
079                return a < 0 ? 0 : a > 255 ? 255 : a;
080            }
081            
082            public abstract void composeRGB( int[] src, int[] dst, float alpha );
083    
084            public void compose( Raster src, Raster dstIn, WritableRaster dstOut ) {
085                float alpha = this.alpha;
086    
087                int[] srcPix = null;
088                int[] dstPix = null;
089    
090                int x = dstOut.getMinX();
091                int w = dstOut.getWidth();
092                int y0 = dstOut.getMinY();
093                int y1 = y0 + dstOut.getHeight();
094    
095                for ( int y = y0; y < y1; y++ ) {
096                    srcPix = src.getPixels( x, y, w, 1, srcPix );
097                    dstPix = dstIn.getPixels( x, y, w, 1, dstPix );
098                    composeRGB( srcPix, dstPix, alpha );
099                    dstOut.setPixels( x, y, w, 1, dstPix );
100                }
101            }
102    
103        }
104    }