Skip to content

Commit

Permalink
Add ColorPacker
Browse files Browse the repository at this point in the history
  • Loading branch information
knokko committed Oct 25, 2024
1 parent fcdd89d commit b6137cd
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 0 deletions.
7 changes: 7 additions & 0 deletions docs/methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,13 @@ to encode the given set into a `PointerBuffer` that is allocated
on the given `MemoryStack`. This is for instance useful for
populating `ppEnabledLayerNames`.

### Color packing
The `ColorPacker` class provides a `rgb` and `argb` method that
can be used to pack 8-bit red, green, blue, and alpha components
into a (32-bit) `int`. It also provides methods to extract
the red, green, blue, and alpha components from the `int`s that
it has produced.

### pNext chains
You can use `NextChain.findAddress(pNext, sType)` to find the
memory address of the struct with the given `sType` in the
Expand Down
83 changes: 83 additions & 0 deletions src/main/java/com/github/knokko/boiler/utilities/ColorPacker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.github.knokko.boiler.utilities;

/**
* Helper class to pack RGB(A) colors into a single <b>int</b>. This is similar to what <i>java.awt.Color</i> does,
* but the component order is different. The advantage of this class over <i>java.awt.Color</i>,
* is that no objects need to be allocated, you don't need to ship <i>java.desktop</i>,
* and you don't risk triggering AWT on macOS, which could sabotage GLFW.
*/
public class ColorPacker {

/**
* Packs red, green, blue, and alpha into an integer. The red component will be stored in the least-significant
* 8 bits, the green component will be stored in the next 8 bits, etc...
*/
public static int rgba(byte red, byte green, byte blue, byte alpha) {
return unsigned(red) | (unsigned(green) << 8) | (unsigned(blue) << 16) | (unsigned(alpha) << 24);
}

/**
* Packs red, green, blue, and alpha into an integer. The red component will be stored in the least-significant
* 8 bits, the green component will be stored in the next 8 bits, etc...<br>
*
* You can give the parameters either in the range [-128, 127] or [0, 255].
*/
public static int rgba(int red, int green, int blue, int alpha) {
return rgba((byte) red, (byte) green, (byte) blue, (byte) alpha);
}

/**
* Packs red, green, and blue into an integer. The red component will be stored in the least-significant
* 8 bits, the green component will be stored in the next 8 bits, and the blue component will be stored next to
* green. The 8 most-significant bits will be set to 1, making the stored color opaque.
*/
public static int rgb(byte red, byte green, byte blue) {
return rgba(red, green, blue, (byte) 255);
}

/**
* Packs red, green, and blue into an integer. The red component will be stored in the least-significant
* 8 bits, the green component will be stored in the next 8 bits, and the blue component will be stored next to
* green. The 8 most-significant bits will be set to 1, making the stored color opaque.<br>
*
* You can give the parameters either in the range [-128, 127] or [0, 255].
*/
public static int rgb(int red, int green, int blue) {
return rgba(red, green, blue, 255);
}

/**
* Extracts the red component from a rgba value generated by the <i>rgba</i> method
*/
public static byte red(int rgba) {
return (byte) rgba;
}

/**
* Extracts the green component from a rgba value generated by the <i>rgba</i> method
*/
public static byte green(int rgba) {
return (byte) (rgba >> 8);
}

/**
* Extracts the blue component from a rgba value generated by the <i>rgba</i> method
*/
public static byte blue(int rgba) {
return (byte) (rgba >> 16);
}

/**
* Extracts the alpha component from a rgba value generated by the <i>rgba</i> method
*/
public static byte alpha(int rgba) {
return (byte) (rgba >> 24);
}

/**
* Converts a <b>byte</b> (in the range [-128, 127]) to an <b>int</b> in the range [0, 255]
*/
public static int unsigned(byte value) {
return value & 0xFF;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.github.knokko.boiler.utilities;

import org.junit.jupiter.api.Test;

import static com.github.knokko.boiler.utilities.ColorPacker.*;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class TestColorPacker {

@Test
public void testSimplePackingRGBA() {
assertEquals(0, rgba(0, 0, 0, 0));
assertEquals(-1, rgba(255, 255, 255, 255));
assertEquals(-1, rgba(-1, -1, -1, -1));
assertEquals(-1, rgba((byte) 255, (byte) 255, (byte) 255, (byte) 255));
assertEquals(-1, rgba((byte) -1, (byte) -1, (byte) -1, (byte) -1));

int high = rgba((byte) 255, (byte) 254, (byte) 253, (byte) 252);
assertEquals(high, rgba(255, 254, 253, 252));
assertEquals(high, rgba(-1, -2, -3, -4));
assertEquals((byte) 255, red(high));
assertEquals((byte) 254, green(high));
assertEquals((byte) 253, blue(high));
assertEquals((byte) 252, alpha(high));
assertEquals(255, unsigned(red(high)));
assertEquals(254, unsigned(green(high)));
assertEquals(253, unsigned(blue(high)));
assertEquals(252, unsigned(alpha(high)));

int low = rgba((byte) 1, (byte) 2, (byte) 3, (byte) 4);
assertEquals(low, rgba(1, 2, 3, 4));
assertEquals(1, red(low));
assertEquals(2, green(low));
assertEquals(3, blue(low));
assertEquals(4, alpha(low));
assertEquals(1, unsigned(red(low)));
assertEquals(2, unsigned(green(low)));
assertEquals(3, unsigned(blue(low)));
assertEquals(4, unsigned(alpha(low)));
}

@Test
public void testSimplePackingRGB() {
assertEquals(rgba(0, 0, 0, 255), rgb(0, 0, 0));
assertEquals(rgba(0, 0, 0, 255), rgb((byte) 0, (byte) 0, (byte) 0));
assertEquals(-1, rgb(255, -1, 255));
assertEquals(-1, rgb((byte) -1, (byte) 255, (byte) -1));
assertEquals(rgba(250, 251, 252, 255), rgb(250, 251, 252));
assertEquals(rgba(250, 251, 252, 255), rgb((byte) 250, (byte) 251, (byte) 252));
assertEquals(rgba(250, 251, 252, 255), rgb(-6, -5, -4));
assertEquals(rgba(1, 2, 3, 255), rgb(1, 2, 3));
assertEquals(rgba(1, 2, 3, 255), rgb((byte) 1, (byte) 2, (byte) 3));
}
}

0 comments on commit b6137cd

Please sign in to comment.