Skip to content

Commit 481f80f

Browse files
committed
Docs & Benchmark: Update JMH benchmarks with Surface Pro 8 i5-1135G7 numbers, expand API Quick Reference and Reference manual
1 parent 7f2d973 commit 481f80f

4 files changed

Lines changed: 170 additions & 19 deletions

File tree

README.md

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,28 +115,64 @@ Standard Java `BufferedImage` operations suffer from heavy heap allocation overh
115115

116116
## Performance Benchmarks
117117

118-
In the official [JMH Benchmark](examples/Benchmark), `FastImage` measured throughput for full 1080p (1920x1080) frame processing:
118+
In the official [JMH Benchmark](examples/Benchmark), `FastImage` measured throughput for full 1080p (1920×1080) to 720p (1280×720) frame processing:
119119

120120
```text
121-
Benchmark Mode Cnt Score Error Units
122-
JMH_Image.benchmarkFastImageResize thrpt 2 19.521 ops/s
123-
JMH_Image.benchmarkFastImageKawaseBlur thrpt 2 17.942 ops/s
121+
Benchmark Mode Cnt Score Units
122+
Benchmark.benchmarkFastImageResizeNearest thrpt 2 642.614 ops/s
123+
Benchmark.benchmarkFastImageResizeAreaAverage thrpt 2 199.345 ops/s
124+
Benchmark.benchmarkFastImageResizeBilinear thrpt 2 127.117 ops/s
125+
Benchmark.benchmarkFastImageResizeBicubic thrpt 2 37.105 ops/s
126+
Benchmark.benchmarkFastImageKawaseBlur thrpt 2 24.451 ops/s
124127
```
125128

126129
> [!NOTE]
127-
> **Environment & Setup**: Measured on an Intel Core i7 with Windows 11. `FastImage` resizes 1080p full HD uncompressed image buffers to 720p at **19.5+ full operations per second** with **zero JVM Garbage Collection allocations**.
130+
> **Environment & Setup**: Measured on an 11th Gen Intel Core i5-1135G7 (Microsoft Surface Pro 8) running Windows 11 with JDK 21. `FastImage` processes full 1080p uncompressed frames at up to **640+ operations per second** (Point) and **199+ operations per second** (OpenMP-accelerated Area-Average Anti-Aliasing) with **zero JVM Garbage Collection allocations**.
128131
129132
---
130133

131134
## API Quick Reference
132135

136+
### Factory & Memory Wrapping
133137
| Method | Description | Path |
134138
|--------|-------------|------|
135-
| `create(width, height)` | Creates an off-heap `FastImage` instance. | [Reference 📖](docs/REFERENCE.md#create) |
136-
| `resize(newW, newH)` | AVX2 SIMD bilinear image scaling. | [Reference 📖](docs/REFERENCE.md#resize) |
139+
| `create(width, height)` | Allocates an unmanaged off-heap ARGB pixel buffer. | [Reference 📖](docs/REFERENCE.md#create) |
140+
| `fromBufferedImage(image)` | Converts a Java `BufferedImage` to `FastImage`. | [Reference 📖](docs/REFERENCE.md#frombufferedimage) |
141+
| `fromPixels(pixels, width, height)` | Creates an instance directly from an `int[]` array. | [Reference 📖](docs/REFERENCE.md#frompixels) |
142+
| `wrap(address, width, height)` | Zero-copy wrap of raw native 64-bit address. | [Reference 📖](docs/REFERENCE.md#wrap) |
143+
| `wrap(Pointer, width, height)` | Zero-copy wrap of a `FastPointer` handle. | [Reference 📖](docs/REFERENCE.md#wrap) |
144+
| `wrap(ByteBuffer, width, height)` | Zero-copy wrap of a direct `java.nio.ByteBuffer`. | [Reference 📖](docs/REFERENCE.md#wrap) |
145+
146+
### Resampling & Geometry
147+
| Method | Description | Path |
148+
|--------|-------------|------|
149+
| `resize(newW, newH)` | Native AVX2 SIMD bilinear image scaling. | [Reference 📖](docs/REFERENCE.md#resize) |
150+
| `resizeNearest(newW, newH)` | Ultra-fast Nearest-Neighbor (point) scaling. | [Reference 📖](docs/REFERENCE.md#resizenearest) |
137151
| `resizeBicubic(newW, newH)` | Ultra-sharp Catmull-Rom Bicubic spline resampling. | [Reference 📖](docs/REFERENCE.md#resizebicubic) |
138-
| `resizeAreaAverage(newW, newH)` | Area-Average Anti-Aliasing downsampler. | [Reference 📖](docs/REFERENCE.md#resizeareaaverage) |
139-
| `blurKawase(radius, passes)` | High-speed Dual-Kawase blur filter. | [Reference 📖](docs/REFERENCE.md#blurkawase) |
152+
| `resizeAreaAverage(newW, newH)` | OpenMP-accelerated Area-Average downsampler. | [Reference 📖](docs/REFERENCE.md#resizeareaaverage) |
153+
| `crop(x, y, width, height)` | Crops sub-region into a new `FastImage`. | [Reference 📖](docs/REFERENCE.md#crop) |
154+
| `flipHorizontal()` / `flipVertical()` | Flips image along X or Y axis in-place. | [Reference 📖](docs/REFERENCE.md#flip) |
155+
156+
### Convolutions & Blur Filters
157+
| Method | Description | Path |
158+
|--------|-------------|------|
159+
| `blurKawase(radius, passes)` | High-speed multi-pass Kawase blur filter. | [Reference 📖](docs/REFERENCE.md#blurkawase) |
160+
| `blurDualKawase(radius)` | Premium 2-pass Dual-Kawase down/upsample blur. | [Reference 📖](docs/REFERENCE.md#blurdualkawase) |
161+
| `blurGaussian(radius)` | Smooth separable Gaussian blur. | [Reference 📖](docs/REFERENCE.md#blurgaussian) |
162+
| `blurStack(radius)` | CSS `backdrop-filter` grade stack blur. | [Reference 📖](docs/REFERENCE.md#blurstack) |
163+
| `blurBox(radius)` | Fast box blur filter. | [Reference 📖](docs/REFERENCE.md#blurbox) |
164+
| `blurMipmapped(radius)` | Large-radius hierarchical down/upsample blur. | [Reference 📖](docs/REFERENCE.md#blurmipmapped) |
165+
166+
### Color Operations & Export
167+
| Method | Description | Path |
168+
|--------|-------------|------|
169+
| `grayscale()` | Vectorized luminance weighting to monochrome. | [Reference 📖](docs/REFERENCE.md#grayscale) |
170+
| `adjustBrightness(factor)` | Scales pixel luminance (`1.0` = normal). | [Reference 📖](docs/REFERENCE.md#brightness) |
171+
| `adjustContrast(factor)` | Adjusts image contrast ratio. | [Reference 📖](docs/REFERENCE.md#contrast) |
172+
| `toBufferedImage()` | Converts native pixels to standard `BufferedImage`. | [Reference 📖](docs/REFERENCE.md#tobufferedimage) |
173+
| `getPixels(int[] dest)` | Fills a pre-allocated Java `int[]` array. | [Reference 📖](docs/REFERENCE.md#getpixels) |
174+
| `getDirectBuffer()` | Returns a direct `ByteBuffer` view of native memory. | [Reference 📖](docs/REFERENCE.md#getdirectbuffer) |
175+
| `getPointer()` | Returns a `fastpointer.Pointer` to native memory. | [Reference 📖](docs/REFERENCE.md#getpointer) |
140176

141177
---
142178

docs/REFERENCE.md

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,84 @@ Ultra-sharp Catmull-Rom Bicubic spline resampling. Delivers maximum visual fidel
5050

5151
---
5252

53+
### `resizeNearest`
54+
```java
55+
public FastImage resizeNearest(int newWidth, int newHeight)
56+
```
57+
Ultra-fast Nearest-Neighbor (point sampling) scaling kernel. Ideal for pixel art, retro rendering, or maximum framerate downsampling.
58+
59+
---
60+
5361
### `resizeAreaAverage`
5462
```java
5563
public FastImage resizeAreaAverage(int targetWidth, int targetHeight)
5664
```
57-
High-quality Anti-Aliasing downsampler using SIMD box area averaging. Eliminates jagged edges and moiré patterns when scaling down desktop or camera feeds.
65+
High-quality Anti-Aliasing downsampler using OpenMP multi-threaded box area averaging. Eliminates jagged edges and moiré patterns when scaling down desktop or camera feeds.
66+
67+
---
68+
69+
### `crop`
70+
```java
71+
public FastImage crop(int x, int y, int width, int height)
72+
```
73+
Extracts a sub-region into a new `FastImage` instance.
74+
75+
---
76+
77+
### `flipHorizontal` / `flipVertical`
78+
```java
79+
public FastImage flipHorizontal()
80+
public FastImage flipVertical()
81+
```
82+
Flips the image buffer along the horizontal or vertical axis in-place.
5883

5984
---
6085

6186
### `blurKawase`
6287
```java
6388
public FastImage blurKawase(float radius, int passes)
6489
```
65-
Applies high-speed Dual-Kawase blur filtering (ideal for UI translucent overlays).
90+
Applies multi-pass Kawase blur filtering (ideal for UI translucent overlays).
91+
92+
---
93+
94+
### `blurDualKawase`
95+
```java
96+
public FastImage blurDualKawase(float radius)
97+
```
98+
Applies high-speed 2-pass Dual-Kawase downsampling and upsampling blur.
99+
100+
---
101+
102+
### `blurGaussian`
103+
```java
104+
public FastImage blurGaussian(float radius)
105+
```
106+
Applies smooth separable Gaussian blur kernel.
107+
108+
---
109+
110+
### `blurStack`
111+
```java
112+
public FastImage blurStack(float radius)
113+
```
114+
Applies CSS `backdrop-filter` grade fast stack blur.
115+
116+
---
117+
118+
### `blurBox`
119+
```java
120+
public FastImage blurBox(float radius)
121+
```
122+
Applies fast box blur.
123+
124+
---
125+
126+
### `blurMipmapped`
127+
```java
128+
public FastImage blurMipmapped(float radius)
129+
```
130+
Applies hierarchical down/upsample blur for very large radii (100+ pixels).
66131

67132
---
68133

@@ -74,10 +139,50 @@ Converts color image pixels to grayscale using AVX2 SIMD luminance weighting.
74139

75140
---
76141

77-
## 3. Export API
142+
### `adjustBrightness`
143+
```java
144+
public FastImage adjustBrightness(float factor)
145+
```
146+
Scales luminance of all pixels (`1.0` = original brightness).
147+
148+
---
149+
150+
### `adjustContrast`
151+
```java
152+
public FastImage adjustContrast(float factor)
153+
```
154+
Adjusts image contrast ratio centered around mid-gray (`128`).
155+
156+
---
157+
158+
## 3. Export & Interop API
78159

79160
### `toBufferedImage`
80161
```java
81162
public BufferedImage toBufferedImage()
82163
```
83164
Creates a standard Java `BufferedImage` representation from the native pixel memory.
165+
166+
---
167+
168+
### `getPixels`
169+
```java
170+
public void getPixels(int[] destinationBuffer)
171+
```
172+
Direct zero-allocation copy into a caller-supplied pre-allocated `int[]` array.
173+
174+
---
175+
176+
### `getDirectBuffer`
177+
```java
178+
public ByteBuffer getDirectBuffer()
179+
```
180+
Exposes the native memory address as a direct `java.nio.ByteBuffer` with zero copies.
181+
182+
---
183+
184+
### `getPointer`
185+
```java
186+
public Pointer getPointer()
187+
```
188+
Returns a `fastpointer.Pointer` wrapper around the native physical memory address.

examples/Benchmark/pom.xml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,7 @@
2626
<dependency>
2727
<groupId>com.github.andrestubbe</groupId>
2828
<artifactId>FastImage</artifactId>
29-
<version>0.1.1</version>
30-
</dependency>
31-
<dependency>
32-
<groupId>com.github.andrestubbe</groupId>
33-
<artifactId>FastSIMD</artifactId>
34-
<version>main-SNAPSHOT</version>
29+
<version>0.1.4</version>
3530
</dependency>
3631
<dependency>
3732
<groupId>org.openjdk.jmh</groupId>

examples/Benchmark/src/main/java/fastimage/benchmark/Benchmark.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,25 @@ public void setup() {
2121
}
2222

2323
@org.openjdk.jmh.annotations.Benchmark
24-
public Object benchmarkFastImageResize() {
24+
public Object benchmarkFastImageResizeBilinear() {
2525
return srcImage.resize(1280, 720);
2626
}
2727

28+
@org.openjdk.jmh.annotations.Benchmark
29+
public Object benchmarkFastImageResizeNearest() {
30+
return srcImage.resizeNearest(1280, 720);
31+
}
32+
33+
@org.openjdk.jmh.annotations.Benchmark
34+
public Object benchmarkFastImageResizeBicubic() {
35+
return srcImage.resizeBicubic(1280, 720);
36+
}
37+
38+
@org.openjdk.jmh.annotations.Benchmark
39+
public Object benchmarkFastImageResizeAreaAverage() {
40+
return srcImage.resizeAreaAverage(1280, 720);
41+
}
42+
2843
@org.openjdk.jmh.annotations.Benchmark
2944
public Object benchmarkFastImageKawaseBlur() {
3045
return srcImage.blurKawase(3.0f, 2);

0 commit comments

Comments
 (0)