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