Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.moebiusgames.xcylin.threed.texture;
- import com.jme3.texture.Image;
- import com.jme3.util.BufferUtils;
- import com.jme3.util.NativeObject;
- import com.moebiusgames.xcylin.js.JavaScriptSandboxWhitelisted;
- import com.moebiusgames.xcylin.js.JavaScriptSandboxWhitelistedMethod;
- import java.awt.Color;
- import java.nio.ByteBuffer;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * A paintable image
- * @author Florian Frankenberger
- */
- @JavaScriptSandboxWhitelisted
- public class PaintableImage extends Image {
- private final ByteBuffer buffer;
- private final List<NativeObject> notifyOnUpdate = new ArrayList<>();
- private boolean flippedY;
- /**
- * ctor
- * @param original the original image to copy (it will be copied 1:1 regardless of flippedY setting)
- * @param flippedY if set to true then all pixel operations will use height - y instead of y
- */
- public PaintableImage(Image original, boolean flippedY) {
- this(original.getWidth(), original.getHeight(), flippedY);
- //make sure we duplicate 1:1 and not flip it on the way
- this.flippedY = false;
- copyFromImage(original, 0, 0, original.getWidth(), original.getHeight(), 0, 0);
- this.flippedY = true;
- }
- /**
- * ctor
- * @param width
- * @param height
- * @param flippedY if set to true then all pixel operations will use height - y instead of y
- */
- public PaintableImage(int width, int height, boolean flippedY) {
- super(Format.RGBA8, width, height, null);
- this.flippedY = flippedY;
- buffer = BufferUtils.createByteBuffer(width * height * 4);
- this.setData(buffer);
- }
- /**
- * ctor
- * @param width
- * @param height
- * @param flippedY if set to true then all pixel operations will use height - y instead of y
- * @param bgColor
- */
- public PaintableImage(int width, int height, boolean flippedY, Color bgColor) {
- this(width, height, flippedY);
- this.fillArea(0, 0, width - 1, height - 1, bgColor);
- }
- public synchronized void addUpdateListener(NativeObject nativeObject) {
- if (nativeObject == null) {
- throw new IllegalArgumentException("null argument given");
- }
- this.notifyOnUpdate.add(nativeObject);
- }
- @JavaScriptSandboxWhitelistedMethod
- @Override
- public int getWidth() {
- return super.getWidth();
- }
- @JavaScriptSandboxWhitelistedMethod
- @Override
- public int getHeight() {
- return super.getHeight();
- }
- public ByteBuffer getBuffer() {
- return this.buffer;
- }
- /**
- * sets a pixel at the given position
- *
- * @param x
- * @param y
- * @param color
- */
- @JavaScriptSandboxWhitelistedMethod
- public void setPixel(int x, int y, Color color) {
- this.setPixel(x, y, color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
- }
- /**
- * sets a pixel at the given position
- *
- * @param x
- * @param y
- * @param red
- * @param green
- * @param blue
- * @param alpha
- */
- private void setPixel(int x, int y, int red, int green, int blue, int alpha) {
- int index = getIndex(x, y);
- buffer.put(index, (byte) red);
- buffer.put(index + 1, (byte) green);
- buffer.put(index + 2, (byte) blue);
- buffer.put(index + 3, (byte) alpha);
- this.setUpdateNeeded();
- }
- /**
- * returns a pixel at the given position
- *
- * @param x
- * @param y
- * @return
- */
- @JavaScriptSandboxWhitelistedMethod
- public Color getPixel(int x, int y) {
- int index = getIndex(x, y);
- return new Color(
- toInt(buffer.get(index)),
- toInt(buffer.get(index+1)),
- toInt(buffer.get(index+2)),
- toInt(buffer.get(index+3))
- );
- }
- /**
- * fills the are with the given color
- *
- * @param x1
- * @param y1
- * @param x2
- * @param y2
- * @param color
- */
- @JavaScriptSandboxWhitelistedMethod
- public void fillArea(int x1, int y1, int x2, int y2, Color color) {
- for (int x = x1; x <= x2; ++x) {
- for (int y = y1; y <= y2; ++y) {
- this.setPixel(x, y, color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
- }
- }
- }
- /**
- * copies a part of the source image to this image (and converts it to the correct
- * color format)
- *
- * @param sourceImage
- * @param sourceX1
- * @param sourceY1
- * @param sourceX2
- * @param sourceY2
- * @param targetX
- * @param targetY
- */
- @JavaScriptSandboxWhitelistedMethod
- public void copyFromImage(Image sourceImage, int sourceX1, int sourceY1, int sourceX2, int sourceY2, int targetX, int targetY) {
- if (sourceImage.getDepth() > 1) {
- throw new IllegalArgumentException("only works with 2d images");
- }
- // System.out.println("copy " + sourceX1 + "x" + sourceY1 + " - " + sourceX2 + "x" + sourceY2 + " to " + targetX + ", " + targetY);
- ByteBuffer source = sourceImage.getData(0);
- ByteBuffer target = buffer;
- for (int x = sourceX1; x < sourceX2; ++x) {
- for (int y = sourceY1; y < sourceY2; ++y) {
- byte r = (byte) 0;
- byte g = (byte) 0;
- byte b = (byte) 0;
- byte a = (byte) 0xFF;
- switch (sourceImage.getFormat()) {
- case BGR8:
- int sourceIndexBGR8 = (x + y * sourceImage.getWidth()) * 3;
- r = source.get(sourceIndexBGR8 + 2);
- g = source.get(sourceIndexBGR8 + 1);
- b = source.get(sourceIndexBGR8);
- break;
- case RGB8:
- int sourceIndexRGB8 = (x + y * sourceImage.getWidth()) * 3;
- r = source.get(sourceIndexRGB8);
- g = source.get(sourceIndexRGB8 + 1);
- b = source.get(sourceIndexRGB8 + 2);
- break;
- case RGBA8:
- int sourceIndexRGBA8 = (x + y * sourceImage.getWidth()) * 4;
- r = source.get(sourceIndexRGBA8);
- g = source.get(sourceIndexRGBA8 + 1);
- b = source.get(sourceIndexRGBA8 + 2);
- a = source.get(sourceIndexRGBA8 + 3);
- break;
- case ABGR8:
- int sourceIndexABGR8 = (x + y * sourceImage.getWidth()) * 4;
- a = source.get(sourceIndexABGR8);
- b = source.get(sourceIndexABGR8 + 1);
- g = source.get(sourceIndexABGR8 + 2);
- r = source.get(sourceIndexABGR8 + 3);
- break;
- default:
- throw new IllegalArgumentException("image type " + sourceImage.getFormat().toString() + " is not supported.");
- }
- int targetIndex = getIndex(targetX + (x - sourceX1), targetY + (y - sourceY1));
- target.put(targetIndex, r);
- target.put(targetIndex + 1, g);
- target.put(targetIndex + 2, b);
- target.put(targetIndex + 3, a);
- }
- }
- this.setUpdateNeeded();
- }
- @Override
- public synchronized void setUpdateNeeded() {
- super.setUpdateNeeded();
- //neccessary because super calls this in constructor obviously
- //causing a NPE
- if (this.notifyOnUpdate != null) {
- for (NativeObject object : this.notifyOnUpdate) {
- object.setUpdateNeeded();
- }
- }
- }
- /**
- * returns the buffer's index position for the given
- * x and y coordinates.
- *
- * @param x
- * @param y
- * @return
- */
- public int getIndex(int x, int y) {
- if (flippedY) {
- return (x + ((this.getHeight() - 1) - y) * width) * 4;
- } else {
- return (x + y * width) * 4;
- }
- }
- private static int toInt(byte b) {
- return b & 0xFF;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement