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.io.File; 008import java.io.IOException; 009 010import javax.imageio.ImageIO; 011 012import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties; 013import org.openstreetmap.josm.tools.Logging; 014 015import javafx.application.Platform; 016import javafx.scene.image.PixelWriter; 017import javafx.scene.image.WritableImage; 018 019@SuppressWarnings({ "restriction"}) 020public class GraphicsUtils { 021 022 public static javafx.scene.image.Image convertBufferedImage2JavaFXImage(BufferedImage bf) { 023 WritableImage wr = null; 024 if (bf != null) { 025 wr = new WritableImage(bf.getWidth(), bf.getHeight()); 026 PixelWriter pw = wr.getPixelWriter(); 027 for (int x = 0; x < bf.getWidth(); x++) { 028 for (int y = 0; y < bf.getHeight(); y++) { 029 pw.setArgb(x, y, bf.getRGB(x, y)); 030 } 031 } 032 } 033 return wr; 034 } 035 036 public static class PlatformHelper { 037 038 public static void run(Runnable treatment) { 039 if(treatment == null) throw new IllegalArgumentException("The treatment to perform can not be null"); 040 041 if(Platform.isFxApplicationThread()) treatment.run(); 042 else Platform.runLater(treatment); 043 } 044 } 045 046 public static BufferedImage buildMultiTiledCubemapFaceImage(BufferedImage[] tiles) { 047 048 BufferedImage res = null; 049 050 int pixelBuffer = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?2:1; 051 052 tiles = cropMultiTiledImages(tiles, pixelBuffer); 053 054 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 055 int cols = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?4:2; 056 057 // TODO: images still not backwards after cropping 058 /*for(int i=0; i<tiles.length;i++) { 059 File outputfileBefore = new File("/Users/renerr18/Desktop/TileImagesTest/tile16" + Long.valueOf(System.currentTimeMillis()).toString() + "CroppingAfter.jpeg"); 060 //File outputfileAfter= new File("/Users/renerr18/Desktop/TileImagesTest/tile16" + Long.valueOf(System.currentTimeMillis()).toString() + "ImageAfter" + Integer.valueOf(i).toString() + ".jpeg"); 061 try { 062 ImageIO.write(tiles[i], "jpeg", outputfileBefore); 063 //ImageIO.write(res[i], "jpeg", outputfileAfter); 064 } catch (IOException e) { 065 // TODO Auto-generated catch block 066 e.printStackTrace(); 067 } 068 }*/ 069 070 071 072 073 int chunkWidth, chunkHeight; 074 075 chunkWidth = tiles[0].getWidth(); 076 chunkHeight = tiles[0].getHeight(); 077 078 //Initializing the final image 079 BufferedImage img = new BufferedImage(chunkWidth*cols, chunkHeight*rows, BufferedImage.TYPE_INT_ARGB); 080 081 int num = 0; 082 for (int i = 0; i < rows; i++) { 083 for (int j = 0; j < cols; j++) { 084 img.createGraphics().drawImage(tiles[num], chunkWidth * j, chunkHeight * i, null); 085 // TODO: build images without making them backwards, so no flipping is required 086 // (Change previous line?) 087 // images are reversed, flip them 088 // TODO: flip image - drawImage produces backwards images 089 /*AffineTransform tx = AffineTransform.getScaleInstance(-1, 1); 090 tx.translate(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1018:512, 0); 091 AffineTransformOp op = new AffineTransformOp(tx, 092 AffineTransformOp.TYPE_NEAREST_NEIGHBOR); 093 res = op.filter(img, null);*/ 094 095 // BufferedImage for mirror image 096 097 int width = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510; 098 int height = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510; 099 100 res = new BufferedImage(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510, StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510, 101 BufferedImage.TYPE_INT_ARGB); 102 103 // Create mirror image pixel by pixel 104 for (int y = 0; y < height; y++) 105 { 106 for (int lx = 0, rx = width - 1; lx < width; lx++, rx--) 107 { 108 // lx starts from the left side of the image 109 // rx starts from the right side of the image 110 // lx is used since we are getting pixel from left side 111 // rx is used to set from right side 112 // get source pixel value 113 int p = img.getRGB(lx, y); 114 115 // set mirror image pixel value 116 res.setRGB(rx, y, p); 117 } 118 } 119 num++; 120 } 121 } 122 123 Logging.info("Image concatenated....."); 124 125 File outputfileBefore = new File("/Users/renerr18/Desktop/TileImagesTest/tile16" + Long.valueOf(System.currentTimeMillis()).toString() + "StitchingAfter.jpeg"); 126 //File outputfileAfter= new File("/Users/renerr18/Desktop/TileImagesTest/tile16" + Long.valueOf(System.currentTimeMillis()).toString() + "ImageAfter" + Integer.valueOf(i).toString() + ".jpeg"); 127 try { 128 ImageIO.write(res, "jpeg", outputfileBefore); 129 //ImageIO.write(res[i], "jpeg", outputfileAfter); 130 } catch (IOException e) { 131 // TODO Auto-generated catch block 132 e.printStackTrace(); 133 } 134 135 return res; 136 } 137 138 public static BufferedImage rotateImage(BufferedImage bufImg) { 139 AffineTransform tx = AffineTransform.getScaleInstance(-1, -1); 140 tx.translate(-bufImg.getWidth(null), -bufImg.getHeight(null)); 141 AffineTransformOp op = new AffineTransformOp(tx, 142 AffineTransformOp.TYPE_NEAREST_NEIGHBOR); 143 bufImg = op.filter(bufImg, null); 144 return bufImg; 145 } 146 147 private static BufferedImage[] cropMultiTiledImages(BufferedImage[] tiles, int pixelBuffer) { 148 149 BufferedImage[] res = new BufferedImage[tiles.length]; 150 151 for(int i=0; i<tiles.length;i++) { 152 // TODO: compare and, if necessary, fix cropping! 153 if(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) { 154 res[i] = tiles[i].getSubimage(pixelBuffer, pixelBuffer, 256-pixelBuffer, 256-pixelBuffer); 155 /*File outputfileBefore = new File("/Users/renerr18/Desktop/TileImagesTest/tile16" + Long.valueOf(System.currentTimeMillis()).toString() + "ImageBefore" + Integer.valueOf(i).toString() + ".jpeg"); 156 File outputfileAfter= new File("/Users/renerr18/Desktop/TileImagesTest/tile16" + Long.valueOf(System.currentTimeMillis()).toString() + "ImageAfter" + Integer.valueOf(i).toString() + ".jpeg"); 157 try { 158 ImageIO.write(tiles[i], "jpeg", outputfileBefore); 159 ImageIO.write(res[i], "jpeg", outputfileAfter); 160 } catch (IOException e) { 161 // TODO Auto-generated catch block 162 e.printStackTrace(); 163 }*/ 164 } else { 165 res[i] = tiles[i].getSubimage(pixelBuffer, pixelBuffer, 256-pixelBuffer, 256-pixelBuffer); 166 /*File outputfileBefore = new File("/Users/renerr18/Desktop/TileImagesTest/tile4" + Long.valueOf(System.currentTimeMillis()).toString() + "ImageBefore" + Integer.valueOf(i).toString() + ".jpeg"); 167 File outputfileAfter= new File("/Users/renerr18/Desktop/TileImagesTest/tile4" + Long.valueOf(System.currentTimeMillis()).toString() + "ImageAfter" + Integer.valueOf(i).toString() + ".jpeg"); 168 try { 169 ImageIO.write(tiles[i], "jpeg", outputfileBefore); 170 ImageIO.write(res[i], "jpeg", outputfileAfter); 171 } catch (IOException e) { 172 // TODO Auto-generated catch block 173 e.printStackTrace(); 174 }*/ 175 } 176 } 177 return res; 178 } 179}