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