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    import java.awt.image.WritableRaster;
020    
021    import railo.runtime.engine.ThreadLocalPageContext;
022    import railo.runtime.exp.FunctionException;
023    import railo.runtime.exp.PageException;
024    import railo.runtime.img.ImageUtil;
025    import railo.runtime.type.KeyImpl;
026    import railo.runtime.type.List;
027    import railo.runtime.type.Struct;
028    
029    /**
030     * A filter which flips images or rotates by multiples of 90 degrees.
031     */
032    public class FlipFilter extends AbstractBufferedImageOp  implements DynFiltering {
033    
034            /**
035         * Flip the image horizontally.
036         */
037        public static final int FLIP_H = 1;
038    
039            /**
040         * Flip the image vertically.
041         */
042            public static final int FLIP_V = 2;
043    
044            /**
045         * Flip the image horizontally and vertically.
046         */
047            public static final int FLIP_HV = 3;
048    
049            /**
050         * Rotate the image 90 degrees clockwise.
051         */
052            public static final int FLIP_90CW = 4;
053    
054            /**
055         * Rotate the image 90 degrees counter-clockwise.
056         */
057            public static final int FLIP_90CCW = 5;
058    
059            /**
060         * Rotate the image 180 degrees.
061         */
062            public static final int FLIP_180 = 6;
063    
064            private int operation;
065            private int width, height;
066            private int newWidth, newHeight;
067    
068        /**
069         * Construct a FlipFilter which flips horizontally and vertically.
070         */
071            public FlipFilter() {
072                    this(FLIP_HV);
073            }
074    
075        /**
076         * Construct a FlipFilter.
077         * @param operation the filter operation
078         */
079            public FlipFilter(int operation) {
080                    this.operation = operation;
081            }
082    
083        /**
084         * Set the filter operation.
085         * @param operation the filter operation
086         * @see #getOperation
087         */
088            public void setOperation(int operation) {
089                    this.operation = operation;
090            }
091    
092        /**
093         * Get the filter operation.
094         * @return the filter operation
095         * @see #setOperation
096         */
097            public int getOperation() {
098                    return operation;
099            }
100    
101        public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
102            int width = src.getWidth();
103            int height = src.getHeight();
104                    int type = src.getType();
105                    WritableRaster srcRaster = 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 = dst.getRaster();
189                    setRGB( dst, 0, 0, newW, newH, newPixels );
190    
191            return dst;
192        }
193    
194            public String toString() {
195                    switch (operation) {
196                    case FLIP_H:
197                            return "Flip Horizontal";
198                    case FLIP_V:
199                            return "Flip Vertical";
200                    case FLIP_HV:
201                            return "Flip Diagonal";
202                    case FLIP_90CW:
203                            return "Rotate 90";
204                    case FLIP_90CCW:
205                            return "Rotate -90";
206                    case FLIP_180:
207                            return "Rotate 180";
208                    }
209                    return "Flip";
210            }
211            public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
212                    Object o;
213                    if((o=parameters.removeEL(KeyImpl.init("Operation")))!=null)setOperation(ImageFilterUtil.toIntValue(o,"Operation"));
214    
215                    // check for arguments not supported
216                    if(parameters.size()>0) {
217                            throw new FunctionException(ThreadLocalPageContext.get(), "ImageFilter", 3, "parameters", "the parameter"+(parameters.size()>1?"s":"")+" ["+List.arrayToList(parameters.keysAsString(),", ")+"] "+(parameters.size()>1?"are":"is")+" not allowed, only the following parameters are supported [Operation]");
218                    }
219    
220                    return filter(src, dst);
221            }
222    }