001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019/*
020*
021
022Licensed under the Apache License, Version 2.0 (the "License");
023you may not use this file except in compliance with the License.
024You may obtain a copy of the License at
025
026   http://www.apache.org/licenses/LICENSE-2.0
027
028Unless required by applicable law or agreed to in writing, software
029distributed under the License is distributed on an "AS IS" BASIS,
030WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
031See the License for the specific language governing permissions and
032limitations under the License.
033*/
034
035package lucee.runtime.img.filter;import java.awt.image.BufferedImage;
036import java.awt.image.ColorModel;
037
038import lucee.runtime.engine.ThreadLocalPageContext;
039import lucee.runtime.exp.FunctionException;
040import lucee.runtime.exp.PageException;
041import lucee.runtime.img.ImageUtil;
042import lucee.runtime.type.KeyImpl;
043import lucee.runtime.type.Struct;
044import lucee.runtime.type.util.CollectionUtil;
045
046/**
047 * A filter which flips images or rotates by multiples of 90 degrees.
048 */
049public class FlipFilter extends AbstractBufferedImageOp  implements DynFiltering {
050
051        /**
052     * Flip the image horizontally.
053     */
054    public static final int FLIP_H = 1;
055
056        /**
057     * Flip the image vertically.
058     */
059        public static final int FLIP_V = 2;
060
061        /**
062     * Flip the image horizontally and vertically.
063     */
064        public static final int FLIP_HV = 3;
065
066        /**
067     * Rotate the image 90 degrees clockwise.
068     */
069        public static final int FLIP_90CW = 4;
070
071        /**
072     * Rotate the image 90 degrees counter-clockwise.
073     */
074        public static final int FLIP_90CCW = 5;
075
076        /**
077     * Rotate the image 180 degrees.
078     */
079        public static final int FLIP_180 = 6;
080
081        private int operation;
082        private int width, height;
083        private int newWidth, newHeight;
084
085    /**
086     * Construct a FlipFilter which flips horizontally and vertically.
087     */
088        public FlipFilter() {
089                this(FLIP_HV);
090        }
091
092    /**
093     * Construct a FlipFilter.
094     * @param operation the filter operation
095     */
096        public FlipFilter(int operation) {
097                this.operation = operation;
098        }
099
100    /**
101     * Set the filter operation.
102     * @param operation the filter operation
103     * @see #getOperation
104     */
105        public void setOperation(int operation) {
106                this.operation = operation;
107        }
108
109    /**
110     * Get the filter operation.
111     * @return the filter operation
112     * @see #setOperation
113     */
114        public int getOperation() {
115                return operation;
116        }
117
118    public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
119        int width = src.getWidth();
120        int height = src.getHeight();
121                //int type = src.getType();
122                //WritableRaster srcRaster = 
123        src.getRaster();
124
125                int[] inPixels = getRGB( src, 0, 0, width, height, null );
126
127                //int x = 0, y = 0;
128                int w = width;
129                int h = height;
130
131                //int newX = 0;
132                //int newY = 0;
133                int newW = w;
134                int newH = h;
135                switch (operation) {
136                case FLIP_H:
137                        //newX = width - (x + w);
138                        break;
139                case FLIP_V:
140                        //newY = height - (y + h);
141                        break;
142                case FLIP_HV:
143                        newW = h;
144                        newH = w;
145                        //newX = y;
146                        //newY = x;
147                        break;
148                case FLIP_90CW:
149                        newW = h;
150                        newH = w;
151                        //newX = height - (y + h);
152                        //newY = x;
153                        break;
154                case FLIP_90CCW:
155                        newW = h;
156                        newH = w;
157                        //newX = y;
158                        //newY = width - (x + w);
159                        break;
160                case FLIP_180:
161                        //newX = width - (x + w);
162                        //newY = height - (y + h);
163                        break;
164                }
165
166                int[] newPixels = new int[newW * newH];
167
168                for (int row = 0; row < h; row++) {
169                        for (int col = 0; col < w; col++) {
170                                int index = row * width + col;
171                                int newRow = row;
172                                int newCol = col;
173                                switch (operation) {
174                                case FLIP_H:
175                                        newCol = w - col - 1;
176                                        break;
177                                case FLIP_V:
178                                        newRow = h - row - 1;
179                                        break;
180                                case FLIP_HV:
181                                        newRow = col;
182                                        newCol = row;
183                                        break;
184                                case FLIP_90CW:
185                                        newRow = col;
186                                        newCol = h - row - 1;;
187                                        break;
188                                case FLIP_90CCW:
189                                        newRow = w - col - 1;
190                                        newCol = row;
191                                        break;
192                                case FLIP_180:
193                                        newRow = h - row - 1;
194                                        newCol = w - col - 1;
195                                        break;
196                                }
197                                int newIndex = newRow * newW + newCol;
198                                newPixels[newIndex] = inPixels[index];
199                        }
200                }
201
202        if ( dst == null ) {
203            ColorModel dstCM = src.getColorModel();
204                        dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(newW, newH), dstCM.isAlphaPremultiplied(), null);
205                }
206                //WritableRaster dstRaster = 
207                dst.getRaster();
208                setRGB( dst, 0, 0, newW, newH, newPixels );
209
210        return dst;
211    }
212
213        public String toString() {
214                switch (operation) {
215                case FLIP_H:
216                        return "Flip Horizontal";
217                case FLIP_V:
218                        return "Flip Vertical";
219                case FLIP_HV:
220                        return "Flip Diagonal";
221                case FLIP_90CW:
222                        return "Rotate 90";
223                case FLIP_90CCW:
224                        return "Rotate -90";
225                case FLIP_180:
226                        return "Rotate 180";
227                }
228                return "Flip";
229        }
230        public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
231                Object o;
232                if((o=parameters.removeEL(KeyImpl.init("Operation")))!=null)setOperation(ImageFilterUtil.toIntValue(o,"Operation"));
233
234                // check for arguments not supported
235                if(parameters.size()>0) {
236                        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]");
237                }
238
239                return filter(src, dst);
240        }
241}