From b1c3ff2d2835aa97f14e16d6a37d0e371f4646a4 Mon Sep 17 00:00:00 2001 From: Robert Vokac Date: Tue, 1 Oct 2024 17:13:34 +0200 Subject: [PATCH] Added new class Color III --- .../pixelgamelibrary/api/graphics/Color.java | 155 ++++++++++++++---- .../api/graphics/Color4BitPalette.java | 83 ++++++++++ .../api/graphics/ColorDepth.java | 58 +++++++ .../api/graphics/ColorMode.java | 29 ++++ .../api/graphics/Texture.java | 2 + 5 files changed, 296 insertions(+), 31 deletions(-) create mode 100644 src/main/java/com/pixelgamelibrary/api/graphics/Color4BitPalette.java create mode 100644 src/main/java/com/pixelgamelibrary/api/graphics/ColorDepth.java create mode 100644 src/main/java/com/pixelgamelibrary/api/graphics/ColorMode.java diff --git a/src/main/java/com/pixelgamelibrary/api/graphics/Color.java b/src/main/java/com/pixelgamelibrary/api/graphics/Color.java index 2eb386c..f2272c9 100644 --- a/src/main/java/com/pixelgamelibrary/api/graphics/Color.java +++ b/src/main/java/com/pixelgamelibrary/api/graphics/Color.java @@ -19,6 +19,12 @@ /////////////////////////////////////////////////////////////////////////////////////////////// package com.pixelgamelibrary.api.graphics; +import com.pixelgamelibrary.api.PixelException; +import static com.pixelgamelibrary.api.graphics.ColorDepth.BITS_16; +import static com.pixelgamelibrary.api.graphics.ColorDepth.BITS_24; +import static com.pixelgamelibrary.api.graphics.ColorDepth.BITS_32; +import static com.pixelgamelibrary.api.graphics.ColorDepth.BITS_4; +import static com.pixelgamelibrary.api.graphics.ColorDepth.BITS_8; import lombok.Data; /** @@ -79,6 +85,15 @@ public final class Color { float iFloat = i; return iFloat / BITS_IN_ONE_BYTE; } + + // Counts distance between two colors + public static double colorDistance(Color c1, Color c2) { + float rDiff = c2.getRed() - c1.getRed(); + float gDiff = c2.getGreen() - c1.getGreen(); + float bDiff = c2.getBlue() - c1.getBlue(); + return Math.sqrt(rDiff * rDiff + gDiff * gDiff + bDiff * bDiff); + } + // Default alpha value for colors public static final float DEFAULT_ALPHA = 1f; @@ -192,6 +207,10 @@ public final class Color { intElementToFloat(alpha)); } + public double distanceTo(Color anotherColor) { + return colorDistance(this, anotherColor); + } + /** * Blends this color with the specified color by multiplying their * respective components. @@ -407,74 +426,148 @@ public final class Color { return floatElementToInt(alpha); } + /** + * Converts the color components to 16-bit representation. The red and blue + * components are each reduced to 5 bits, while the green component is + * reduced to 6 bits. The conversion is done by shifting the integer values + * right to discard the lower bits. This method modifies the existing color + * instance. + */ public void set16Bit() { - this.red = floatElementToInt(this.red) >> 3; // 5 bitů - this.green = floatElementToInt(this.green) >> 2; // 6 bitů - this.blue = floatElementToInt(this.blue) >> 3; // 5 bitů + this.red = floatElementToInt(this.red) >> 3; // 5 bits for red + this.green = floatElementToInt(this.green) >> 2; // 6 bits for green + this.blue = floatElementToInt(this.blue) >> 3; // 5 bits for blue } + /** + * Converts the color components to 8-bit representation. All color + * components are shifted to utilize the maximum possible values within the + * limits of 3 bits for red and green (maximum value of 7) and 2 bits for + * blue (maximum value of 3). This method modifies the existing color + * instance. + */ public void set8Bit() { -this.red = floatElementToInt(this.red) >> 5; // 3 bity (max 7) -this.green = floatElementToInt(this.green) >> 5; // 3 bity (max 7) -this.blue = floatElementToInt(this.blue) >> 6; // 2 bity (max 3) + this.red = floatElementToInt(this.red) >> 5; // 3 bits for red (max 7) + this.green = floatElementToInt(this.green) >> 5; // 3 bits for green (max 7) + this.blue = floatElementToInt(this.blue) >> 6; // 2 bits for blue (max 3) } + /** + * Converts the color components to 4-bit representation. Each color + * component is reduced to 2 bits, allowing for values from 0 to 3. This is + * achieved by shifting the integer values right to discard the lower bits. + * This method modifies the existing color instance. + */ public void set4Bit() { - this.red = floatElementToInt(this.red) >> 1; // 2 bitů - this.green = floatElementToInt(this.green) >> 1; // 2 bitů - this.blue = floatElementToInt(this.blue) >> 1; // 2 bitů + this.red = floatElementToInt(this.red) >> 1; // 2 bits for red + this.green = floatElementToInt(this.green) >> 1; // 2 bits for green + this.blue = floatElementToInt(this.blue) >> 1; // 2 bits for blue } public void setWhiteBlack8Bit() { int grayscale = (int) ((red + green + blue) / 3 * 255); - this.red = this.green = this.blue = grayscale / 255f; // Černobílý + this.red = this.green = this.blue = grayscale / 255f; } public void setWhiteBlack4Bit() { int grayscale = (int) ((red + green + blue) / 3 * 15); - this.red = this.green = this.blue = grayscale / 15f; // Černobílý + this.red = this.green = this.blue = grayscale / 15f; } public void setWhiteBlack2Bit() { int grayscale = (int) ((red + green + blue) / 3 * 3); - this.red = this.green = this.blue = grayscale / 3f; // Černobílý + this.red = this.green = this.blue = grayscale / 3f; } public void setWhiteBlack1Bit() { int grayscale = (int) ((red + green + blue) / 3 * 1); - this.red = this.green = this.blue = grayscale / 1f; // Černobílý + this.red = this.green = this.blue = grayscale / 1f; } - public int getByteRepresentation16Bit() { - return (floatElementToInt(this.red) << 11) | (floatElementToInt(this.green) << 5) | floatElementToInt(this.blue); + public void setWithBitCount(int bitCount) { + ColorDepth colorDepth = ColorDepth.from(bitCount); + switch (colorDepth) { + case BITS_32: + return; + case BITS_24: + return; + case BITS_16: + set16Bit(); + break; + case BITS_8: + set8Bit(); + break; + case BITS_4: + set4Bit(); + break; + default: + throw new PixelException("Unsupported color depth: " + bitCount); + } } - public int getByteRepresentation8Bit() { - return (floatElementToInt(this.red) << 4) | (floatElementToInt(this.green) << 2) | floatElementToInt(this.blue); + public void setWhiteBlackWithBitCount(int bitCount) { + + switch (bitCount) { + case 8: + setWhiteBlack8Bit(); + break; + case 4: + setWhiteBlack4Bit(); + break; + case 2: + setWhiteBlack2Bit(); + break; + case 1: + setWhiteBlack1Bit(); + break; + default: + throw new PixelException("Unsupported bit count: " + bitCount); + } } - public int getByteRepresentation4Bit() { - return (floatElementToInt(this.red) << 2) | (floatElementToInt(this.green) << 1) | floatElementToInt(this.blue); + public void set(ColorMode colorMode, int bitCount) { + if (colorMode == ColorMode.COLOR) { + setWithBitCount(bitCount); + return; + } + + if (colorMode == ColorMode.BLACK_AND_WHITE) { + setWhiteBlackWithBitCount(bitCount); + return; + } + throw new PixelException("Unsupported ColorMode: " + colorMode); } - public int getByteRepresentationWhiteBlack8Bit() { - int grayscale = (int) ((red + green + blue) / 3 * 255); - return grayscale; + public byte[] getByteRepresentation32Bit() { + return null;//todo } - public int getByteRepresentationWhiteBlack4Bit() { - int grayscale = (int) ((red + green + blue) / 3 * 15); - return grayscale; + public byte[] getByteRepresentation24Bit() { + return null;//todo } - public int getByteRepresentationWhiteBlack2Bit() { - int grayscale = (int) ((red + green + blue) / 3 * 3); - return grayscale; + public byte[] getByteRepresentation16Bit() { + return null;//todo } - public int getByteRepresentationWhiteBlack1Bit() { - int grayscale = (int) ((red + green + blue) / 3 * 1); - return grayscale; + public byte[] getByteRepresentation8Bit() { + return null;//todo + } + + public byte[] getByteRepresentation4Bit() { + return null;//todo + } + + public byte[] getByteRepresentation2Bit() { + return null;//todo + } + + public byte[] getByteRepresentation1Bit() { + return null;//todo + } + + public byte[] getByteRepresentation(ColorMode colorMode, int bitCount) { + return null;//todo } @Override diff --git a/src/main/java/com/pixelgamelibrary/api/graphics/Color4BitPalette.java b/src/main/java/com/pixelgamelibrary/api/graphics/Color4BitPalette.java new file mode 100644 index 0000000..7e45c68 --- /dev/null +++ b/src/main/java/com/pixelgamelibrary/api/graphics/Color4BitPalette.java @@ -0,0 +1,83 @@ +package com.pixelgamelibrary.api.graphics; + +/////////////////////////////////////////////////////////////////////////////////////////////// +// Pixel: Game library. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +///////////////////////////////////////////////////////////////////////////////////////////////package com.pixelgamelibrary.api.graphics; +/** + * + * @author robertvokac + */ +public class Color4BitPalette { + + private Color4BitPalette() { + //Not meant to be instantiated. + } + public static final Color BLACK = new Color(0, 0, 0); + public static final Color BLUE = new Color(0, 0, 255); + public static final Color GREEN = new Color(0, 255, 0); + public static final Color CYAN = new Color(0, 255, 255); + public static final Color RED = new Color(255, 0, 0); + public static final Color MAGENTA = new Color(255, 0, 255); + public static final Color YELLOW = new Color(255, 255, 0); + public static final Color WHITE = new Color(255, 255, 255); + public static final Color GRAY = new Color(128, 128, 128); + public static final Color DARK_BLUE = new Color(0, 0, 128); + public static final Color DARK_GREEN = new Color(0, 128, 0); + public static final Color DARK_CYAN = new Color(0, 128, 128); + public static final Color DARK_RED = new Color(128, 0, 0); + public static final Color DARK_MAGENTA = new Color(128, 0, 128); + public static final Color DARK_YELLOW = new Color(128, 128, 0); + public static final Color LIGHT_GRAY = new Color(192, 192, 192); + + // Define a color palette for 4-bit graphics (16 colors) + private static final Color[] COLORS_4BIT_PALETTE = { + Color4BitPalette.BLACK, + Color4BitPalette.BLUE, + Color4BitPalette.GREEN, + Color4BitPalette.CYAN, + Color4BitPalette.RED, + Color4BitPalette.MAGENTA, + Color4BitPalette.YELLOW, + Color4BitPalette.WHITE, + Color4BitPalette.GRAY, + Color4BitPalette.DARK_BLUE, + Color4BitPalette.DARK_GREEN, + Color4BitPalette.DARK_CYAN, + Color4BitPalette.DARK_RED, + Color4BitPalette.DARK_MAGENTA, + Color4BitPalette.DARK_YELLOW, + Color4BitPalette.LIGHT_GRAY + }; + + public static Color findClosestColor(Color color) { + Color closestColor = null; + double minDistance = Double.MAX_VALUE; + + for (Color paletteColor : COLORS_4BIT_PALETTE) { + double distance = paletteColor.distanceTo(color); + if (distance < minDistance) { + minDistance = distance; + closestColor = paletteColor; + } + } + + return closestColor; + } + +} diff --git a/src/main/java/com/pixelgamelibrary/api/graphics/ColorDepth.java b/src/main/java/com/pixelgamelibrary/api/graphics/ColorDepth.java new file mode 100644 index 0000000..77f83ce --- /dev/null +++ b/src/main/java/com/pixelgamelibrary/api/graphics/ColorDepth.java @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Pixel: Game library. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.pixelgamelibrary.api.graphics; + +import com.pixelgamelibrary.api.PixelException; +import lombok.Getter; + +/** + * + * @author robertvokac + */ +public enum ColorDepth { + BITS_32(32), + BITS_24(24), + BITS_16(16), + BITS_8(8), + BITS_4(4); + + @Getter + private final int bitCount; + + ColorDepth(int bitCount) { + this.bitCount = bitCount; + } + public static ColorDepth from(int bitCount) { + switch (bitCount) { + case 32: + return BITS_32; + case 24: + return BITS_24; + case 16: + return BITS_16; + case 8: + return BITS_8; + case 4: + return BITS_4; + default: + throw new PixelException("Unsupported bit depth"); + } + } +} diff --git a/src/main/java/com/pixelgamelibrary/api/graphics/ColorMode.java b/src/main/java/com/pixelgamelibrary/api/graphics/ColorMode.java new file mode 100644 index 0000000..edbbf1f --- /dev/null +++ b/src/main/java/com/pixelgamelibrary/api/graphics/ColorMode.java @@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Pixel: Game library. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.pixelgamelibrary.api.graphics; + +/** + * + * @author robertvokac + */ +public enum ColorMode { + COLOR, + BLACK_AND_WHITE; +} diff --git a/src/main/java/com/pixelgamelibrary/api/graphics/Texture.java b/src/main/java/com/pixelgamelibrary/api/graphics/Texture.java index 70ddc97..bd648fb 100644 --- a/src/main/java/com/pixelgamelibrary/api/graphics/Texture.java +++ b/src/main/java/com/pixelgamelibrary/api/graphics/Texture.java @@ -27,4 +27,6 @@ package com.pixelgamelibrary.api.graphics; public interface Texture { void makeColorTransparent(int r, int g, int b); void scale(double d); + void setColorMode(ColorMode colorMode, int bitCount); + }