Advertisement
entrusc

PaintableImage.java

Mar 25th, 2015
25
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.33 KB | None | 0 0
  1. package com.moebiusgames.xcylin.threed.texture;
  2.  
  3. import com.jme3.texture.Image;
  4. import com.jme3.util.BufferUtils;
  5. import com.jme3.util.NativeObject;
  6. import com.moebiusgames.xcylin.js.JavaScriptSandboxWhitelisted;
  7. import com.moebiusgames.xcylin.js.JavaScriptSandboxWhitelistedMethod;
  8. import java.awt.Color;
  9. import java.nio.ByteBuffer;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12.  
  13. /**
  14.  * A paintable image
  15.  * @author Florian Frankenberger
  16.  */
  17. @JavaScriptSandboxWhitelisted
  18. public class PaintableImage extends Image {
  19.  
  20.     private final ByteBuffer buffer;
  21.     private final List<NativeObject> notifyOnUpdate = new ArrayList<>();
  22.  
  23.     private boolean flippedY;
  24.  
  25.     /**
  26.      * ctor
  27.      * @param original the original image to copy (it will be copied 1:1 regardless of flippedY setting)
  28.      * @param flippedY if set to true then all pixel operations will use height - y instead of y
  29.      */
  30.     public PaintableImage(Image original, boolean flippedY) {
  31.         this(original.getWidth(), original.getHeight(), flippedY);
  32.  
  33.         //make sure we duplicate 1:1 and not flip it on the way
  34.         this.flippedY = false;
  35.         copyFromImage(original, 0, 0, original.getWidth(), original.getHeight(), 0, 0);
  36.         this.flippedY = true;
  37.     }
  38.  
  39.     /**
  40.      * ctor
  41.      * @param width
  42.      * @param height
  43.      * @param flippedY if set to true then all pixel operations will use height - y instead of y
  44.      */
  45.     public PaintableImage(int width, int height, boolean flippedY) {
  46.         super(Format.RGBA8, width, height, null);
  47.         this.flippedY = flippedY;
  48.         buffer = BufferUtils.createByteBuffer(width * height * 4);
  49.         this.setData(buffer);
  50.     }
  51.  
  52.     /**
  53.      * ctor
  54.      * @param width
  55.      * @param height
  56.      * @param flippedY if set to true then all pixel operations will use height - y instead of y
  57.      * @param bgColor
  58.      */
  59.     public PaintableImage(int width, int height, boolean flippedY, Color bgColor) {
  60.         this(width, height, flippedY);
  61.         this.fillArea(0, 0, width - 1, height - 1, bgColor);
  62.     }
  63.  
  64.     public synchronized void addUpdateListener(NativeObject nativeObject) {
  65.         if (nativeObject == null) {
  66.             throw new IllegalArgumentException("null argument given");
  67.         }
  68.         this.notifyOnUpdate.add(nativeObject);
  69.     }
  70.  
  71.     @JavaScriptSandboxWhitelistedMethod
  72.     @Override
  73.     public int getWidth() {
  74.         return super.getWidth();
  75.     }
  76.  
  77.     @JavaScriptSandboxWhitelistedMethod
  78.     @Override
  79.     public int getHeight() {
  80.         return super.getHeight();
  81.     }
  82.  
  83.     public ByteBuffer getBuffer() {
  84.         return this.buffer;
  85.     }
  86.  
  87.     /**
  88.      * sets a pixel at the given position
  89.      *
  90.      * @param x
  91.      * @param y
  92.      * @param color
  93.      */
  94.     @JavaScriptSandboxWhitelistedMethod
  95.     public void setPixel(int x, int y, Color color) {
  96.         this.setPixel(x, y, color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
  97.     }
  98.  
  99.     /**
  100.      * sets a pixel at the given position
  101.      *
  102.      * @param x
  103.      * @param y
  104.      * @param red
  105.      * @param green
  106.      * @param blue
  107.      * @param alpha
  108.      */
  109.     private void setPixel(int x, int y, int red, int green, int blue, int alpha) {
  110.         int index = getIndex(x, y);
  111.         buffer.put(index, (byte) red);
  112.         buffer.put(index + 1, (byte) green);
  113.         buffer.put(index + 2, (byte) blue);
  114.         buffer.put(index + 3, (byte) alpha);
  115.         this.setUpdateNeeded();
  116.     }
  117.  
  118.     /**
  119.      * returns a pixel at the given position
  120.      *
  121.      * @param x
  122.      * @param y
  123.      * @return
  124.      */
  125.     @JavaScriptSandboxWhitelistedMethod
  126.     public Color getPixel(int x, int y) {
  127.         int index = getIndex(x, y);
  128.  
  129.         return new Color(
  130.                 toInt(buffer.get(index)),
  131.                 toInt(buffer.get(index+1)),
  132.                 toInt(buffer.get(index+2)),
  133.                 toInt(buffer.get(index+3))
  134.                 );
  135.     }
  136.  
  137.     /**
  138.      * fills the are with the given color
  139.      *
  140.      * @param x1
  141.      * @param y1
  142.      * @param x2
  143.      * @param y2
  144.      * @param color
  145.      */
  146.     @JavaScriptSandboxWhitelistedMethod
  147.     public void fillArea(int x1, int y1, int x2, int y2, Color color) {
  148.         for (int x = x1; x <= x2; ++x) {
  149.             for (int y = y1; y <= y2; ++y) {
  150.                 this.setPixel(x, y, color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
  151.             }
  152.         }
  153.     }
  154.  
  155.     /**
  156.      * copies a part of the source image to this image (and converts it to the correct
  157.      * color format)
  158.      *
  159.      * @param sourceImage
  160.      * @param sourceX1
  161.      * @param sourceY1
  162.      * @param sourceX2
  163.      * @param sourceY2
  164.      * @param targetX
  165.      * @param targetY
  166.      */
  167.     @JavaScriptSandboxWhitelistedMethod
  168.     public void copyFromImage(Image sourceImage, int sourceX1, int sourceY1, int sourceX2, int sourceY2, int targetX, int targetY) {
  169.         if (sourceImage.getDepth() > 1) {
  170.             throw new IllegalArgumentException("only works with 2d images");
  171.         }
  172.  
  173. //        System.out.println("copy " + sourceX1 + "x" + sourceY1 + " - " + sourceX2 + "x" + sourceY2 + " to " + targetX + ", " + targetY);
  174.  
  175.         ByteBuffer source = sourceImage.getData(0);
  176.         ByteBuffer target = buffer;
  177.  
  178.         for (int x = sourceX1; x < sourceX2; ++x) {
  179.             for (int y = sourceY1; y < sourceY2; ++y) {
  180.                 byte r = (byte) 0;
  181.                 byte g = (byte) 0;
  182.                 byte b = (byte) 0;
  183.                 byte a = (byte) 0xFF;
  184.                 switch (sourceImage.getFormat()) {
  185.                     case BGR8:
  186.                         int sourceIndexBGR8 = (x + y * sourceImage.getWidth()) * 3;
  187.                         r = source.get(sourceIndexBGR8 + 2);
  188.                         g = source.get(sourceIndexBGR8 + 1);
  189.                         b = source.get(sourceIndexBGR8);
  190.                         break;
  191.                     case RGB8:
  192.                         int sourceIndexRGB8 = (x + y * sourceImage.getWidth()) * 3;
  193.                         r = source.get(sourceIndexRGB8);
  194.                         g = source.get(sourceIndexRGB8 + 1);
  195.                         b = source.get(sourceIndexRGB8 + 2);
  196.                         break;
  197.                     case RGBA8:
  198.                         int sourceIndexRGBA8 = (x + y * sourceImage.getWidth()) * 4;
  199.                         r = source.get(sourceIndexRGBA8);
  200.                         g = source.get(sourceIndexRGBA8 + 1);
  201.                         b = source.get(sourceIndexRGBA8 + 2);
  202.                         a = source.get(sourceIndexRGBA8 + 3);
  203.                         break;
  204.                     case ABGR8:
  205.                         int sourceIndexABGR8 = (x + y * sourceImage.getWidth()) * 4;
  206.                         a = source.get(sourceIndexABGR8);
  207.                         b = source.get(sourceIndexABGR8 + 1);
  208.                         g = source.get(sourceIndexABGR8 + 2);
  209.                         r = source.get(sourceIndexABGR8 + 3);
  210.                         break;
  211.                     default:
  212.                         throw new IllegalArgumentException("image type " + sourceImage.getFormat().toString() + " is not supported.");
  213.                 }
  214.  
  215.                 int targetIndex = getIndex(targetX + (x - sourceX1), targetY + (y - sourceY1));
  216.                 target.put(targetIndex, r);
  217.                 target.put(targetIndex + 1, g);
  218.                 target.put(targetIndex + 2, b);
  219.                 target.put(targetIndex + 3, a);
  220.             }
  221.         }
  222.  
  223.         this.setUpdateNeeded();
  224.     }
  225.  
  226.     @Override
  227.     public synchronized void setUpdateNeeded() {
  228.         super.setUpdateNeeded();
  229.  
  230.         //neccessary because super calls this in constructor obviously
  231.         //causing a NPE
  232.         if (this.notifyOnUpdate != null) {
  233.             for (NativeObject object : this.notifyOnUpdate) {
  234.                 object.setUpdateNeeded();
  235.             }
  236.         }
  237.     }
  238.  
  239.     /**
  240.      * returns the buffer's index position for the given
  241.      * x and y coordinates.
  242.      *
  243.      * @param x
  244.      * @param y
  245.      * @return
  246.      */
  247.     public int getIndex(int x, int y) {
  248.         if (flippedY) {
  249.             return (x + ((this.getHeight() - 1) - y) * width) * 4;
  250.         } else {
  251.             return (x + y * width) * 4;
  252.         }
  253.     }
  254.  
  255.     private static int toInt(byte b) {
  256.         return b & 0xFF;
  257.     }
  258.  
  259. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement