    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}