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.filter;import java.awt.image.BufferedImage;
018    import java.awt.image.ColorModel;
019    
020    import railo.runtime.engine.ThreadLocalPageContext;
021    import railo.runtime.exp.FunctionException;
022    import railo.runtime.exp.PageException;
023    import railo.runtime.img.ImageUtil;
024    import railo.runtime.type.KeyImpl;
025    import railo.runtime.type.Struct;
026    import railo.runtime.type.util.CollectionUtil;
027    
028    /**
029     * A filter which flips images or rotates by multiples of 90 degrees.
030     */
031    public class FlipFilter extends AbstractBufferedImageOp  implements DynFiltering {
032    
033            /**
034         * Flip the image horizontally.
035         */
036        public static final int FLIP_H = 1;
037    
038            /**
039         * Flip the image vertically.
040         */
041            public static final int FLIP_V = 2;
042    
043            /**
044         * Flip the image horizontally and vertically.
045         */
046            public static final int FLIP_HV = 3;
047    
048            /**
049         * Rotate the image 90 degrees clockwise.
050         */
051            public static final int FLIP_90CW = 4;
052    
053            /**
054         * Rotate the image 90 degrees counter-clockwise.
055         */
056            public static final int FLIP_90CCW = 5;
057    
058            /**
059         * Rotate the image 180 degrees.
060         */
061            public static final int FLIP_180 = 6;
062    
063            private int operation;
064            private int width, height;
065            private int newWidth, newHeight;
066    
067        /**
068         * Construct a FlipFilter which flips horizontally and vertically.
069         */
070            public FlipFilter() {
071                    this(FLIP_HV);
072            }
073    
074        /**
075         * Construct a FlipFilter.
076         * @param operation the filter operation
077         */
078            public FlipFilter(int operation) {
079                    this.operation = operation;
080            }
081    
082        /**
083         * Set the filter operation.
084         * @param operation the filter operation
085         * @see #getOperation
086         */
087            public void setOperation(int operation) {
088                    this.operation = operation;
089            }
090    
091        /**
092         * Get the filter operation.
093         * @return the filter operation
094         * @see #setOperation
095         */
096            public int getOperation() {
097                    return operation;
098            }
099    
100        public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
101            int width = src.getWidth();
102            int height = src.getHeight();
103                    //int type = src.getType();
104                    //WritableRaster srcRaster = 
105            src.getRaster();
106    
107                    int[] inPixels = getRGB( src, 0, 0, width, height, null );
108    
109                    //int x = 0, y = 0;
110                    int w = width;
111                    int h = height;
112    
113                    //int newX = 0;
114                    //int newY = 0;
115                    int newW = w;
116                    int newH = h;
117                    switch (operation) {
118                    case FLIP_H:
119                            //newX = width - (x + w);
120                            break;
121                    case FLIP_V:
122                            //newY = height - (y + h);
123                            break;
124                    case FLIP_HV:
125                            newW = h;
126                            newH = w;
127                            //newX = y;
128                            //newY = x;
129                            break;
130                    case FLIP_90CW:
131                            newW = h;
132                            newH = w;
133                            //newX = height - (y + h);
134                            //newY = x;
135                            break;
136                    case FLIP_90CCW:
137                            newW = h;
138                            newH = w;
139                            //newX = y;
140                            //newY = width - (x + w);
141                            break;
142                    case FLIP_180:
143                            //newX = width - (x + w);
144                            //newY = height - (y + h);
145                            break;
146                    }
147    
148                    int[] newPixels = new int[newW * newH];
149    
150                    for (int row = 0; row < h; row++) {
151                            for (int col = 0; col < w; col++) {
152                                    int index = row * width + col;
153                                    int newRow = row;
154                                    int newCol = col;
155                                    switch (operation) {
156                                    case FLIP_H:
157                                            newCol = w - col - 1;
158                                            break;
159                                    case FLIP_V:
160                                            newRow = h - row - 1;
161                                            break;
162                                    case FLIP_HV:
163                                            newRow = col;
164                                            newCol = row;
165                                            break;
166                                    case FLIP_90CW:
167                                            newRow = col;
168                                            newCol = h - row - 1;;
169                                            break;
170                                    case FLIP_90CCW:
171                                            newRow = w - col - 1;
172                                            newCol = row;
173                                            break;
174                                    case FLIP_180:
175                                            newRow = h - row - 1;
176                                            newCol = w - col - 1;
177                                            break;
178                                    }
179                                    int newIndex = newRow * newW + newCol;
180                                    newPixels[newIndex] = inPixels[index];
181                            }
182                    }
183    
184            if ( dst == null ) {
185                ColorModel dstCM = src.getColorModel();
186                            dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(newW, newH), dstCM.isAlphaPremultiplied(), null);
187                    }
188                    //WritableRaster dstRaster = 
189                    dst.getRaster();
190                    setRGB( dst, 0, 0, newW, newH, newPixels );
191    
192            return dst;
193        }
194    
195            public String toString() {
196                    switch (operation) {
197                    case FLIP_H:
198                            return "Flip Horizontal";
199                    case FLIP_V:
200                            return "Flip Vertical";
201                    case FLIP_HV:
202                            return "Flip Diagonal";
203                    case FLIP_90CW:
204                            return "Rotate 90";
205                    case FLIP_90CCW:
206                            return "Rotate -90";
207                    case FLIP_180:
208                            return "Rotate 180";
209                    }
210                    return "Flip";
211            }
212            public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
213                    Object o;
214                    if((o=parameters.removeEL(KeyImpl.init("Operation")))!=null)setOperation(ImageFilterUtil.toIntValue(o,"Operation"));
215    
216                    // check for arguments not supported
217                    if(parameters.size()>0) {
218                            throw new FunctionException(ThreadLocalPageContext.get(), "ImageFilter", 3, "parameters", "the parameter"+(parameters.size()>1?"s":"")+" ["+CollectionUtil.getKeyList(parameters,", ")+"] "+(parameters.size()>1?"are":"is")+" not allowed, only the following parameters are supported [Operation]");
219                    }
220    
221                    return filter(src, dst);
222            }
223    }