gdx-studio

#libgdx#java#desktop

git clone https://git.pyrossh.dev/gdx-studio

An IDE for creating Games using libgdx and Java supported on all platforms Android, iOS, Desktop


src_libs/com/badlogic/gdx/tools/imagepacker/ColorBleedEffect.java

package com.badlogic.gdx.tools.imagepacker;

import com.badlogic.gdx.tools.imagepacker.ColorBleedEffect.Mask.MaskIterator;

import java.awt.image.BufferedImage;
import java.util.NoSuchElementException;

/** @author Ruben Garat
 * @author Ariel Coppes
 * @author Nathan Sweet */
public class ColorBleedEffect {
	static int TO_PROCESS = 0;
	static int IN_PROCESS = 1;
	static int REALDATA = 2;
	static int[][] offsets = { {-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}};

	ARGBColor color = new ARGBColor();

	public BufferedImage processImage (BufferedImage image, int maxIterations) {
		int width = image.getWidth();
		int height = image.getHeight();

		BufferedImage processedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		int[] rgb = image.getRGB(0, 0, width, height, null, 0, width);
		Mask mask = new Mask(rgb);

		int iterations = 0;
		int lastPending = -1;
		while (mask.pendingSize > 0 && mask.pendingSize != lastPending && iterations < maxIterations) {
			lastPending = mask.pendingSize;
			executeIteration(rgb, mask, width, height);
			iterations++;
		}

		processedImage.setRGB(0, 0, width, height, rgb, 0, width);
		return processedImage;
	}

	private void executeIteration (int[] rgb, Mask mask, int width, int height) {
		MaskIterator iterator = mask.new MaskIterator();
		while (iterator.hasNext()) {
			int pixelIndex = iterator.next();
			int x = pixelIndex % width;
			int y = pixelIndex / width;
			int r = 0, g = 0, b = 0;
			int count = 0;

			for (int i = 0, n = offsets.length; i < n; i++) {
				int[] offset = offsets[i];
				int column = x + offset[0];
				int row = y + offset[1];

				if (column < 0 || column >= width || row < 0 || row >= height) continue;

				int currentPixelIndex = getPixelIndex(width, column, row);
				if (mask.getMask(currentPixelIndex) == REALDATA) {
					color.argb = rgb[currentPixelIndex];
					r += color.red();
					g += color.green();
					b += color.blue();
					count++;
				}
			}

			if (count != 0) {
				color.setARGBA(0, r / count, g / count, b / count);
				rgb[pixelIndex] = color.argb;
				iterator.markAsInProgress();
			}
		}

		iterator.reset();
	}

	private int getPixelIndex (int width, int x, int y) {
		return y * width + x;
	}

	static class Mask {
		int[] data, pending, changing;
		int pendingSize, changingSize;

		Mask (int[] rgb) {
			data = new int[rgb.length];
			pending = new int[rgb.length];
			changing = new int[rgb.length];
			ARGBColor color = new ARGBColor();
			for (int i = 0; i < rgb.length; i++) {
				color.argb = rgb[i];
				if (color.alpha() == 0) {
					data[i] = TO_PROCESS;
					pending[pendingSize] = i;
					pendingSize++;
				} else
					data[i] = REALDATA;
			}
		}

		int getMask (int index) {
			return data[index];
		}

		int removeIndex (int index) {
			if (index >= pendingSize) throw new IndexOutOfBoundsException(String.valueOf(index));
			int value = pending[index];
			pendingSize--;
			pending[index] = pending[pendingSize];
			return value;
		}

		class MaskIterator {
			private int index;

			boolean hasNext () {
				return index < pendingSize;
			}

			int next () {
				if (index >= pendingSize) throw new NoSuchElementException(String.valueOf(index));
				return pending[index++];
			}

			void markAsInProgress () {
				index--;
				changing[changingSize] = removeIndex(index);
				changingSize++;
			}

			void reset () {
				index = 0;
				for (int i = 0; i < changingSize; i++) {
					int index = changing[i];
					data[index] = REALDATA;
				}
				changingSize = 0;
			}
		}
	}

	static class ARGBColor {
		int argb = 0xff000000;

		public int red () {
			return (argb >> 16) & 0xFF;
		}

		public int green () {
			return (argb >> 8) & 0xFF;
		}

		public int blue () {
			return (argb >> 0) & 0xFF;
		}

		public int alpha () {
			return (argb >> 24) & 0xff;
		}

		public void setARGBA (int a, int r, int g, int b) {
			if (a < 0 || a > 255 || r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255)
				throw new IllegalArgumentException("Invalid RGBA: " + r + ", " + g + "," + b + "," + a);
			argb = ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | ((b & 0xFF) << 0);
		}
	}
}