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}