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