How to use it¶
Compile from Source Code¶
You will need JDK 11 or newer and a C/C++ toolchain (GCC or MSVC) installed.
git clone https://github.com/manticore-projects/fpng-java.git
cd fpng-java
gradle build
Build Dependencies¶
FPNG-Java (SSE2 encoder, always safe to load):
<dependency>
<groupId>com.manticore-projects.tools</groupId>
<artifactId>fpng-java</artifactId>
<version>1.4.1</version>
</dependency>
repositories {
mavenCentral()
}
dependencies {
implementation 'com.manticore-projects.tools:fpng-java:1.4.1'
}
FPNGE-Java (AVX2 encoder, only load on supported hardware):
<dependency>
<groupId>com.manticore-projects.tools</groupId>
<artifactId>fpnge-java</artifactId>
<version>1.4.1</version>
</dependency>
repositories {
mavenCentral()
}
dependencies {
implementation 'com.manticore-projects.tools:fpnge-java:1.4.1'
}
Java Usage¶
Basic Encoding¶
import com.manticore.tools.FPNGEncoder;
import java.awt.image.BufferedImage;
// Encode a BufferedImage to PNG bytes (3 or 4 channels)
byte[] pngBytes = FPNGEncoder.encode(image, 4, 0);
Automatic Encoder Selection (SSE2 vs AVX2)¶
The SSE2 encoder (FPNG) is always safe to load on any x86-64 CPU. The AVX2 encoder (FPNGE) must only be loaded if the CPU supports it — otherwise the native library will crash on load.
Use the hasAVX2() probe from the FPNG library to decide at runtime:
import com.manticore.tools.FPNGEncoder;
import com.manticore.tools.FPNGEEncoder;
// Initialise FPNG (always safe) and probe CPU features
FPNGEncoder.ENCODER.fpng_init();
boolean useAVX2 = FPNGEncoder.ENCODER.hasAVX2() != 0;
// Encode using the best available encoder
byte[] pngBytes;
if (useAVX2) {
pngBytes = FPNGEEncoder.encode(image, 4, FPNGE_COMPRESS_LEVEL_DEFAULT);
} else {
pngBytes = FPNGEncoder.encode(image, 4, 0);
}
Extracting Raw Pixel Bytes¶
Both encoders accept the raw byte[] from Java’s DataBufferByte directly. The C side handles the channel swap from Java’s native ABGR/BGR format to RGBA/RGB.
If your BufferedImage is already TYPE_4BYTE_ABGR or TYPE_3BYTE_BGR, you can extract the backing array with zero copy:
import java.awt.image.DataBufferByte;
byte[] raw = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
For images in other formats (e.g. TYPE_INT_ARGB), convert first:
BufferedImage converted = new BufferedImage(
image.getWidth(), image.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
Graphics g = converted.getGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
byte[] raw = ((DataBufferByte) converted.getRaster().getDataBuffer()).getData();
Publishing to Maven Central¶
Credentials go in ~/.gradle/gradle.properties:
sonatypeUsername=<your-central-portal-token-username>
sonatypePassword=<your-central-portal-token-password>
Then publish:
./gradlew publish