001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.plugins.streetside.cubemap;
003
004import java.awt.geom.AffineTransform;
005import java.awt.image.AffineTransformOp;
006import java.awt.image.BufferedImage;
007import java.io.File;
008import java.io.IOException;
009
010import javax.imageio.ImageIO;
011
012import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
013import org.openstreetmap.josm.tools.Logging;
014
015import javafx.application.Platform;
016import javafx.scene.image.PixelWriter;
017import javafx.scene.image.WritableImage;
018
019@SuppressWarnings({ "restriction"})
020public class GraphicsUtils {
021
022        public static javafx.scene.image.Image convertBufferedImage2JavaFXImage(BufferedImage bf) {
023                WritableImage wr = null;
024                if (bf != null) {
025                        wr = new WritableImage(bf.getWidth(), bf.getHeight());
026                        PixelWriter pw = wr.getPixelWriter();
027                        for (int x = 0; x < bf.getWidth(); x++) {
028                                for (int y = 0; y < bf.getHeight(); y++) {
029                                        pw.setArgb(x, y, bf.getRGB(x, y));
030                                }
031                        }
032                }
033                return wr;
034        }
035
036        public static class PlatformHelper {
037
038        public static void run(Runnable treatment) {
039            if(treatment == null) throw new IllegalArgumentException("The treatment to perform can not be null");
040
041            if(Platform.isFxApplicationThread()) treatment.run();
042            else Platform.runLater(treatment);
043        }
044    }
045
046        public static BufferedImage buildMultiTiledCubemapFaceImage(BufferedImage[] tiles) {
047
048                BufferedImage res = null;
049
050                int pixelBuffer = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?2:1;
051
052                tiles = cropMultiTiledImages(tiles, pixelBuffer);
053
054                int rows = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?4:2; //we assume the no. of rows and cols are known and each chunk has equal width and height
055        int cols = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?4:2;
056
057        // TODO: images still not backwards after cropping
058        /*for(int i=0; i<tiles.length;i++) {
059                File outputfileBefore = new File("/Users/renerr18/Desktop/TileImagesTest/tile16" + Long.valueOf(System.currentTimeMillis()).toString() + "CroppingAfter.jpeg");
060                //File outputfileAfter= new File("/Users/renerr18/Desktop/TileImagesTest/tile16" + Long.valueOf(System.currentTimeMillis()).toString() + "ImageAfter" + Integer.valueOf(i).toString() + ".jpeg");
061            try {
062                        ImageIO.write(tiles[i], "jpeg", outputfileBefore);
063                        //ImageIO.write(res[i], "jpeg", outputfileAfter);
064                } catch (IOException e) {
065                        // TODO Auto-generated catch block
066                        e.printStackTrace();
067                }
068        }*/
069
070
071
072
073        int chunkWidth, chunkHeight;
074
075        chunkWidth = tiles[0].getWidth();
076        chunkHeight = tiles[0].getHeight();
077
078        //Initializing the final image
079        BufferedImage img = new BufferedImage(chunkWidth*cols, chunkHeight*rows, BufferedImage.TYPE_INT_ARGB);
080
081        int num = 0;
082        for (int i = 0; i < rows; i++) {
083            for (int j = 0; j < cols; j++) {
084                img.createGraphics().drawImage(tiles[num], chunkWidth * j, chunkHeight * i, null);
085                // TODO: build images without making them backwards, so no flipping is required
086                // (Change previous line?)
087                // images are reversed, flip them
088                // TODO: flip image - drawImage produces backwards images
089                /*AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);
090                tx.translate(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1018:512, 0);
091                AffineTransformOp op = new AffineTransformOp(tx,
092                        AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
093                res = op.filter(img, null);*/
094
095                // BufferedImage for mirror image
096
097                int width = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510;
098                int height = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510;
099
100                res = new BufferedImage(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510, StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510,
101                                                BufferedImage.TYPE_INT_ARGB);
102
103                // Create mirror image pixel by pixel
104                for (int y = 0; y < height; y++)
105                {
106                    for (int lx = 0, rx = width - 1; lx < width; lx++, rx--)
107                    {
108                        // lx starts from the left side of the image
109                        // rx starts from the right side of the image
110                        // lx is used since we are getting pixel from left side
111                        // rx is used to set from right side
112                        // get source pixel value
113                        int p = img.getRGB(lx, y);
114
115                        // set mirror image pixel value
116                        res.setRGB(rx, y, p);
117                    }
118                }
119                num++;
120            }
121        }
122
123        Logging.info("Image concatenated.....");
124
125        File outputfileBefore = new File("/Users/renerr18/Desktop/TileImagesTest/tile16" + Long.valueOf(System.currentTimeMillis()).toString() + "StitchingAfter.jpeg");
126                //File outputfileAfter= new File("/Users/renerr18/Desktop/TileImagesTest/tile16" + Long.valueOf(System.currentTimeMillis()).toString() + "ImageAfter" + Integer.valueOf(i).toString() + ".jpeg");
127            try {
128                        ImageIO.write(res, "jpeg", outputfileBefore);
129                        //ImageIO.write(res[i], "jpeg", outputfileAfter);
130                } catch (IOException e) {
131                        // TODO Auto-generated catch block
132                        e.printStackTrace();
133                }
134
135        return res;
136        }
137
138        public static BufferedImage rotateImage(BufferedImage bufImg) {
139                AffineTransform tx = AffineTransform.getScaleInstance(-1, -1);
140            tx.translate(-bufImg.getWidth(null), -bufImg.getHeight(null));
141            AffineTransformOp op = new AffineTransformOp(tx,
142                AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
143            bufImg = op.filter(bufImg, null);
144            return bufImg;
145        }
146
147        private static BufferedImage[] cropMultiTiledImages(BufferedImage[] tiles, int pixelBuffer) {
148
149                BufferedImage[] res = new BufferedImage[tiles.length];
150
151                        for(int i=0; i<tiles.length;i++) {
152                                // TODO: compare and, if necessary, fix cropping!
153                                if(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {
154                                        res[i] = tiles[i].getSubimage(pixelBuffer, pixelBuffer, 256-pixelBuffer, 256-pixelBuffer);
155                                        /*File outputfileBefore = new File("/Users/renerr18/Desktop/TileImagesTest/tile16" + Long.valueOf(System.currentTimeMillis()).toString() + "ImageBefore" + Integer.valueOf(i).toString() + ".jpeg");
156                                        File outputfileAfter= new File("/Users/renerr18/Desktop/TileImagesTest/tile16" + Long.valueOf(System.currentTimeMillis()).toString() + "ImageAfter" + Integer.valueOf(i).toString() + ".jpeg");
157                                    try {
158                                                ImageIO.write(tiles[i], "jpeg", outputfileBefore);
159                                                ImageIO.write(res[i], "jpeg", outputfileAfter);
160                                        } catch (IOException e) {
161                                                // TODO Auto-generated catch block
162                                                e.printStackTrace();
163                                        }*/
164                                } else {
165                                        res[i] = tiles[i].getSubimage(pixelBuffer, pixelBuffer, 256-pixelBuffer, 256-pixelBuffer);
166                                        /*File outputfileBefore = new File("/Users/renerr18/Desktop/TileImagesTest/tile4" + Long.valueOf(System.currentTimeMillis()).toString() + "ImageBefore" + Integer.valueOf(i).toString() + ".jpeg");
167                                        File outputfileAfter= new File("/Users/renerr18/Desktop/TileImagesTest/tile4" + Long.valueOf(System.currentTimeMillis()).toString() + "ImageAfter" + Integer.valueOf(i).toString() + ".jpeg");
168                                        try {
169                                                ImageIO.write(tiles[i], "jpeg", outputfileBefore);
170                                                ImageIO.write(res[i], "jpeg", outputfileAfter);
171                                        } catch (IOException e) {
172                                                // TODO Auto-generated catch block
173                                                e.printStackTrace();
174                                        }*/
175                                }
176                        }
177                return res;
178        }
179}