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;
007
008import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
009import org.openstreetmap.josm.tools.I18n;
010import org.openstreetmap.josm.tools.Logging;
011
012import javafx.application.Platform;
013import javafx.scene.image.PixelWriter;
014import javafx.scene.image.WritableImage;
015
016@SuppressWarnings({ "restriction"})
017public class GraphicsUtils {
018
019        public static javafx.scene.image.Image convertBufferedImage2JavaFXImage(BufferedImage bf) {
020                WritableImage wr = null;
021                if (bf != null) {
022                        wr = new WritableImage(bf.getWidth(), bf.getHeight());
023                        PixelWriter pw = wr.getPixelWriter();
024                        for (int x = 0; x < bf.getWidth(); x++) {
025                                for (int y = 0; y < bf.getHeight(); y++) {
026                                        pw.setArgb(x, y, bf.getRGB(x, y));
027                                }
028                        }
029                }
030                return wr;
031        }
032
033        public static class PlatformHelper {
034
035        public static void run(Runnable treatment) {
036            if(treatment == null) throw new IllegalArgumentException("The treatment to perform can not be null");
037
038            if(Platform.isFxApplicationThread()) treatment.run();
039            else Platform.runLater(treatment);
040        }
041    }
042
043        public static BufferedImage buildMultiTiledCubemapFaceImage(BufferedImage[] tiles) {
044
045                long start = System.currentTimeMillis();
046
047          BufferedImage res = null;
048
049                int pixelBuffer = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?2:1;
050
051                tiles = cropMultiTiledImages(tiles, pixelBuffer);
052
053                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
054        int cols = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?4:2;
055
056        int chunkWidth, chunkHeight;
057
058        chunkWidth = tiles[0].getWidth();
059        chunkHeight = tiles[0].getHeight();
060
061        //Initializing the final image
062        BufferedImage img = new BufferedImage(chunkWidth*cols, chunkHeight*rows, BufferedImage.TYPE_INT_ARGB);
063
064        int num = 0;
065        for (int i = 0; i < rows; i++) {
066            for (int j = 0; j < cols; j++) {
067                // TODO: this makes the image a mirror image. why!?!
068                img.createGraphics().drawImage(tiles[num], chunkWidth * j, (chunkHeight * i), null);
069
070                // TODO: remove file test!
071                /*try {
072                                ImageIO.write(img, "jpeg", new File("/Users/renerr18/Desktop/TileImagesTest/tile16b" + Long.valueOf(System.currentTimeMillis()).toString() + "createGraphicsAfter.jpeg"));
073                                //ImageIO.write(res[i], "jpeg", outputfileAfter);
074                        } catch (IOException e) {
075                                // TODO Auto-generated catch block
076                                e.printStackTrace();
077                        }*/
078
079                int width = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510;
080                int height = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510;
081
082                // BufferedImage for mirror image
083                res = new BufferedImage(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510, StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510,
084                                                BufferedImage.TYPE_INT_ARGB);
085
086                // Create mirror image pixel by pixel
087                for (int y = 0; y < height; y++)
088                {
089                    for (int lx = 0, rx = width - 1; lx < width; lx++, rx--)
090                    {
091                        // lx starts from the left side of the image
092                        // rx starts from the right side of the image
093                        // lx is used since we are getting pixel from left side
094                        // rx is used to set from right side
095                        // get source pixel value
096                        int p = img.getRGB(lx, y);
097
098                        // set mirror image pixel value
099                        res.setRGB(rx, y, p);
100                    }
101                }
102                num++;
103            }
104        }
105
106        Logging.debug(I18n.tr("Image concatenated in {0} millisecs.",(System.currentTimeMillis()-start)));
107        return res;
108        }
109
110        public static BufferedImage rotateImage(BufferedImage bufImg) {
111                AffineTransform tx = AffineTransform.getScaleInstance(-1, -1);
112            tx.translate(-bufImg.getWidth(null), -bufImg.getHeight(null));
113            AffineTransformOp op = new AffineTransformOp(tx,
114                AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
115            bufImg = op.filter(bufImg, null);
116            return bufImg;
117        }
118
119        private static BufferedImage[] cropMultiTiledImages(BufferedImage[] tiles, int pixelBuffer) {
120
121                long start = System.currentTimeMillis();
122
123          BufferedImage[] res = new BufferedImage[tiles.length];
124
125                        for(int i=0; i<tiles.length;i++) {
126                                if(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {
127                                        res[i] = tiles[i].getSubimage(pixelBuffer, pixelBuffer, 256-pixelBuffer, 256-pixelBuffer);
128                                } else {
129                                        res[i] = tiles[i].getSubimage(pixelBuffer, pixelBuffer, 256-pixelBuffer, 256-pixelBuffer);
130                                }
131                        }
132
133                Logging.debug("Images cropped in {0} millisecs.",(System.currentTimeMillis()-start));
134
135                return res;
136        }
137}