Add Color class

This commit is contained in:
JeremyStar™ 2024-09-28 17:08:35 +02:00
parent f81d27060a
commit 26294b3fa0
Signed by: JeremyStarTM
GPG key ID: E366BAEF67E4704D

View file

@ -0,0 +1,300 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Authors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.engine.base.type;
import de.staropensource.engine.base.EngineConfiguration;
import de.staropensource.engine.base.utility.Math;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Range;
import java.nio.ByteBuffer;
import java.util.HexFormat;
import java.util.Locale;
/**
* A class dedicated to colors.
* Uses the RGBA format, but can also interpret
* the RGB, HEX and HSV color formats.
*
* @since v1-alpha6
*/
@Getter
@Setter
@SuppressWarnings({ "JavadocDeclaration" })
public final class Color {
/**
* Contains the red color value.
*
* @since v1-alpha6
* -- GETTER --
* Returns the red color value.
*
* @return red color value
* @since v1-alpha6
* -- SETTER --
* Sets the red color value.
*
* @param red new red color value
* @since v1-alpha6
*/
private @Range(from = 0, to = 255) int red;
/**
* Contains the green color value.
*
* @since v1-alpha6
* -- GETTER --
* Returns the green color value.
*
* @return green color value
* @since v1-alpha6
* -- SETTER --
* Sets the green color value.
*
* @param green new green color value
* @since v1-alpha6
*/
private @Range(from = 0, to = 255) int green;
/**
* Contains the blue color value.
*
* @since v1-alpha6
* -- GETTER --
* Returns the blue color value.
*
* @return blue color value
* @since v1-alpha6
* -- SETTER --
* Sets the blue color value.
*
* @param blue new blue color value
* @since v1-alpha6
*/
private @Range(from = 0, to = 255) int blue;
/**
* Contains the alpha channel value.
*
* @since v1-alpha6
* -- GETTER --
* Returns the alpha channel value.
*
* @return alpha channel value
* @since v1-alpha6
* -- SETTER --
* Sets the alpha channel value.
*
* @param red new alpha channel value
* @since v1-alpha6
*/
private @Range(from = 0, to = 255) int alpha;
/**
* Creates a new instance.
*
* @param red red color value
* @param green green color value
* @param blue blue color value
* @param alpha alpha channel value
* @since v1-alpha6
*/
private Color(int red, int green, int blue, int alpha) {
this.red = Math.boundNumber(0, 255, red);
this.green = Math.boundNumber(0, 255, green);
this.blue = Math.boundNumber(0, 255, blue);
this.alpha = Math.boundNumber(0, 255, alpha);
}
/**
* Converts the a set of numbers in
* the RGBA format into a new instance.
*
* @param red red color value
* @param blue blue color value
* @param green green color value
* @param alpha alpha color value
* @return new {@link Color} instance
* @since v1-alpha6
*/
public static @NotNull Color fromRGBA(@Range(from = 0, to = 255) int red, @Range(from = 0, to = 255) int green,
@Range(from = 0, to = 255) int blue, @Range(from = 0, to = 255) int alpha) {
return new Color(red, green, blue, alpha);
}
/**
* Converts the an array of numbers in
* the RGBA format into a new instance.
*
* @param intArray integer array
* @return new {@link Color} instance
* @throws IndexOutOfBoundsException if the array contains more or less than four integers
* @since v1-alpha6
*/
public static @NotNull Color fromRGBA(int @NotNull [] intArray) {
if (intArray.length != 4)
throw new StringIndexOutOfBoundsException("Can't contains more or less than four integers");
return new Color(intArray[0], intArray[1], intArray[2], intArray[3]);
}
/**
* Converts the a set of numbers in
* the RGB format into a new instance.
*
* @param red red color value
* @param blue blue color value
* @param green green color value
* @return new {@link Color} instance
* @since v1-alpha6
*/
public static @NotNull Color fromRGB(@Range(from = 0, to = 255) int red, @Range(from = 0, to = 255) int green,
@Range(from = 0, to = 255) int blue) {
return new Color(red, green, blue, 255);
}
/**
* Converts the an array of numbers in
* the RGBA format into a new instance.
*
* @param intArray integer array
* @return new {@link Color} instance
* @throws IndexOutOfBoundsException if the array contains more or less than four integers
* @since v1-alpha6
*/
public static @NotNull Color fromRGB(int @NotNull [] intArray) {
if (intArray.length != 3)
throw new StringIndexOutOfBoundsException("Can't contains more or less than four integers");
return new Color(intArray[0], intArray[1], intArray[2], 255);
}
/**
* Converts an array of bytes into a new instance.
*
* @param bytes byte array
* @return new {@link Color} instance
* @throws IndexOutOfBoundsException if the array contains less than three or more than four bytes
* @since v1-alpha6
*/
public static @NotNull Color fromBytes(byte @NotNull [] bytes) throws IndexOutOfBoundsException {
if (bytes.length == 3)
return new Color(bytes[0] & 0xFF, bytes[1] & 0xFF, bytes[2] & 0xFF, 255);
else if (bytes.length == 4)
return new Color(bytes[0] & 0xFF, bytes[1] & 0xFF, bytes[2] & 0xFF, bytes[3] & 0xFF);
else
throw new StringIndexOutOfBoundsException("Can't contain less than three or more than four bytes");
}
/**
* Converts a hex string into a new instance.
*
* @param hexString hex string
* @return new {@link Color} instance
* @throws IndexOutOfBoundsException if the string contains less than three or more than four bytes
* @since v1-alpha6
*/
public static @NotNull Color fromHex(@NotNull String hexString) throws IndexOutOfBoundsException {
return fromBytes(HexFormat.of().parseHex(hexString));
}
/**
* Creates an identical copy of this instance.
*
* @return identical copy
* @since v1-alpha6
*/
@SneakyThrows
public @NotNull Color clone() {
return (Color) super.clone();
}
/**
* Returns a string representation of this instance.
*
* @return string representation
* @since v1-alpha6
*/
@Override
public @NotNull String toString() {
return (EngineConfiguration.getInstance().isHideFullTypePath()
? getClass().getName().replace(getClass().getPackage() + ".", "")
: getClass().getName())
+ "(r=" + red + " g=" + green + " b=" + blue + " a=" + alpha + ")";
}
/**
* Converts the colors represented by
* this instance into an integer array
* in the RGBA format.
*
* @return {@code int} array with RGBA values
* @since v1-alpha6
*/
public int @NotNull [] toRGBA() {
return new int[]{ red, green, blue, alpha };
}
/**
* Converts the colors represented by
* this instance into an integer array
* in the RGB format.
*
* @return {@code int} array with RGB values
* @since v1-alpha6
*/
public int @NotNull [] toRGB() {
return new int[]{ red, green, blue };
}
/**
* Converts the colors represented by
* this instance into a byte array.
*
* @param includeAlpha whether to include alpha or not
* @return RGBA or RGB format as a byte array
* @since v1-alpha6
*/
public byte @NotNull [] toBytes(boolean includeAlpha) {
ByteBuffer buffer = ByteBuffer.allocate(includeAlpha ? 4 : 3);
buffer
.put((byte) red)
.put((byte) green)
.put((byte) blue);
if (includeAlpha)
buffer.put((byte) alpha);
return buffer.array();
}
/**
* Converts the colors represented by
* this instance into the hex format.
*
* @param includeAlpha whether to include alpha or not
* @return RGBA or RGB format as a hex string
* @since v1-alpha6
*/
public @NotNull String toHex(boolean includeAlpha) {
return HexFormat.of().formatHex(toBytes(includeAlpha)).toUpperCase(Locale.ROOT);
}
}