A Java graphics effects library inspired by the demoscene of the 80s and 90s. Produces animated images from pixel sources, tile maps, and chainable effects — with no dependency on any GUI toolkit.
| Effect | Method | Description |
|---|---|---|
| Horizontal scroll | scrollH(ParamInt offset) |
Shifts the source horizontally |
| Vertical scroll | scrollV(ParamInt offset) |
Shifts the source vertically |
| Bilinear zoom | zoom(ParamDouble factor) |
Zoom in/out centred on the Stage |
| Explicit-centre zoom | zoom(ParamDouble factor, ParamDouble cx, ParamDouble cy) |
Explicit centre |
| Rotation | rotate(ParamDouble angle) |
Clockwise rotation, Stage centre |
| Explicit-centre rotation | rotate(ParamDouble angle, ParamDouble cx, ParamDouble cy) |
Explicit centre |
// 1. Pixel sources
TileSet tileSet = new TileSet(spriteSheet, 16, 16);
TileMap background = new TileMap(tileSet, 40, 30, TileMap.EdgePolicy.WRAP);
background.setTiles(0, 0, levelData);
ImageSource overlay = new ImageSource(overlayImage);
// 2. Mutable parameters (updated each frame)
ParamInt bgScroll = new ParamInt(0);
ParamInt fgScroll = new ParamInt(0);
ParamDouble fgZoom = new ParamDouble(1.0);
// 3. Pipeline (built once, reused every frame)
EffectPipeline pipeline = new EffectPipeline()
.addSource(background)
.scrollH(bgScroll)
.addSource(overlay)
.transparentColor(0xFF00FF00) // color key: transparent green
.scrollH(fgScroll)
.zoom(fgZoom)
.build();
// 4. Stage (output buffer)
Stage stage = new Stage(640, 480); // black background by default
// 5. Animation loop
while (running) {
bgScroll.add(1);
fgScroll.add(3);
pipeline.render(stage);
// Display — your choice of toolkit
Graphics g = canvas.getGraphics();
g.drawImage(stage.getImage(), 0, 0, null);
}PixelSource ← interface: any pixel source
├── ImageSource ← wraps a BufferedImage
└── TileMap ← tile grid (WRAP / CLIP / FEED)
└── TileSet ← spritesheet split into fixed-size tiles
ParamInt ← mutable discrete parameter (pixel offset, ...)
ParamDouble ← mutable continuous parameter (zoom factor, angle, ...)
EffectPipeline ← effect chain — stateless, renders into a Stage
Stage ← 32-bit ARGB pixel buffer — output to the toolkit of your choice
StagePool ← pool of N stages for double/triple buffering
Orchestrator ← render loop on a dedicated thread, paced at targetFps
FrameCallback ← interface: callback invoked once per frame before rendering
PerformanceSampler ← optional tumbling-window accumulator for FPS and render-time stats
- Portable — no dependency on Swing, JavaFX, or SWT. The output is a
BufferedImage, displayable in any toolkit or exportable to a file. - Stateless — the pipeline is built once, reused every frame.
Only
ParamInt/ParamDoublevalues change between frames. - Direct array access — pixels are read and written via the underlying
int[]array (DataBufferInt), bypassinggetRGB/setRGB. - Bilinear by default — zoom and rotation use bilinear interpolation. The integer path (pure scroll) short-circuits interpolation.
For each pixel (x, y) of the Stage:
- Initial value:
stage.getBackgroundColor()(opaque black by default) - For each layer, in order:
- Transforms compute the source coordinate
(sx, sy) - If the source is bounded (
CLIP/FEED) and(sx, sy)is out of bounds → no write - If the source pixel matches the layer's
transparentColor→ no write - Otherwise → the source pixel overwrites the current Stage value
- Transforms compute the source coordinate
| Value | Out-of-bounds behaviour |
|---|---|
WRAP |
Coordinates wrapped modulo the source dimensions (Math.floorMod) |
CLIP |
IndexOutOfBoundsException — the pipeline never crosses the boundary |
FEED |
Same runtime behaviour as CLIP — signals semantically that tiles are fed dynamically |
Examples are located in fr.dufrenoy.imagefx.examples. Each is a standalone
fullscreen application (AWT, no Swing). Press SPACE to quit.
| Class | Effect | Image |
|---|---|---|
FleursDemoExample |
Continuous rotation + sinusoidal zoom (mandala effect) | fleurs.jpg |
PaysageDemoExample |
Multi-directional scrolling on a 3:2 Lissajous curve | paysage_montagne.jpg |
ShadowDemo |
5-layer parallax inspired by Shadow of the Beast — gradient sky + moon, clouds, ochre rock spires, slate menhirs | generative |
<dependency>
<groupId>fr.dufrenoy.imagefx</groupId>
<artifactId>denise4j</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency># Compile and run tests
mvn clean install
# Run tests only
mvn test
# Formal JML verification (requires OpenJML — Linux/macOS)
mvn verify -P openjml-unix
# Formal JML verification (Windows via WSL)
mvn verify -P openjml-windowsRequirements: Java 11+, Maven 3.8+
- Deformations (wave, distortion, tunnel, plasma)
- Palette operations (cycling, fading, remapping)
- Advanced compositing (blending, masking, overlay)
GNU Lesser General Public License v3 — see LICENCE.