JsFractalZoom
Fractal zoomer and splash codec written in JavaScript
Install / Use
/learn @RockingShip/JsFractalZoomREADME
layout: home title: "jsFractalZoom - Fractal zoomer and splash codec written in JavaScript" image: assets/favimage-840x472.jpg
[click on image to start zoomer]

jsFractalZoom
Fractal zoomer written in JavaScript
There is also an image gallery.
Instead of an ad with tracking...
Like to donate some appreciation for the use or inspiration this gives you?
Welcome to the Wonderful World of rendering on demand
when insufficient resources force you to prioritize which pixels to render first
Experience the fractal zoomer
Jump to https://rockingship.github.io/jsFractalZoom
How to use:
- press the enlarge button in the top right (or F11) to enable full-screen.
- fly around in high speed to nice places.
- adjust the "density" using the mouse-wheel to help focus.
- drag the image by holding down the mouse-wheel to a photogenic position.
- staying static allows for faster loading speed.
- the loading is "complete" when the "complete" indicator reached "1" (located in the top bar).
- the control panel can be resized using the bottom left resize button.
Saving:
- saves as a PNG file.
- the panels and text will be removed in the image.
- the navigation and setting from capture are stored in the PNG file.
- drop the PNG on the zoomer page to load the stored information.
Saving a multi-monitor desktop wallpaper:
- find nice location
- press "URL" to copy setting
- paste in URL bar and add
&w=<width>&h=<height>at the end. Replace<width>and<height>with your total multi-monitor dimensions. - load new URL
- wait until "complete" reaches 1
- save
- enjoy your new wallpaper!
Tips for using in 4K:
- switch to the HD (1080p) browser resolution for faster navigation.
- switch to 4K for maximum quality.
For desktop use (primary design target):
- use "ctrl+" /"ctrl-" to chang display resolution. For highest quality match resolution to your screen.
- left mouse button: zoom in
- right mouse button: zoom out
- press mouse wheel to drag
- turn mouse wheel to focus (adjusts "density" setting)
For touchscreen use:
- enable full-screen mode, hold phone horizontally if buttons are too small.
- can be used both portrait and landscape mode.
- disable rotate in the zoomer menu for better performance.
- use 1 finger to drag.
- use 2 fingers to zoom: stretch to zoom in, pinch to zoom out. For unobstructed viewing while zooming you can release 1 finger.
- use 3 finger to focus: release one finger and pinch or stretch with the remaining two to adjust "density".
Table of contents
- Welcome to the Wonderful World of (fractal
- Experience the fractal zoomer
- The fractal
zoomer - Rulers
- Coordinates
- Directional vector
- States
- Phased Locked Loop
- Backing store
- Rotation
memcpy()- Application components
- History
- Manifest
- Source code
- Versioning
- License
- Acknowledgments
The fractal zoomer
zoomer is a rendering engine that paints pixels on demand.
Pixels are repositioned/duplicated until they drift too far away while moving and are recalculated.
Two sample implementations are included: an interactive fractal navigator and a non-interactive fractal viewer.
It is also used to display transverse Mercator projection with the ccbc project.
zoomer utilises a state machine using phase-locked-loops to construct frames.
This means that frame construction is split into different steps where timing metrics predict how long each step takes.
Timer predictions allows the event queue to maximize computations while the user interface stays responsive.
Three coordinate systems are also used throughout construction.
Implementation wise, the only requirement is to supply:
/**
* This is done for every pixel. optimize well!
* Easy extendable for 3D.
* Return the pixel value for the given floating point coordinate.
* Zoomer will use it to fill integer pixel positions.
* The positions are ordered in decreasing significance.
*
* @param {Zoomer} zoomer - 😊
* @param {ZoomerFrame} frame - Pixels/Palette/Rotate
* @param {float} x - X coordinate
* @param {float} y - Y coordinate
* @return {int} - Pixel value
*/
onUpdatePixel: (zoomer, frame, x, y) => {
[YourCodeHere];
}
Rulers
Rulers contain pixel metadata and are used to determine "hot"/"cold" regions with lots/less of changes.
Hot regions which focus on action are calculated first which cools them down.
Cooler regions focus on quality.
Rulers are created by comparing the last rendered frame with the next desired frame.
The goal is to maximize the amount of hot pixels (representing significant scene changes) before the frame construction time limit expires.
Rulers are used to implement the following:
-
Metadata for pixel storage.
See below. -
Create lookup tables for
memcpy_indexed().
Every pixel of a new frame is inherited from the previous frame.
Rulers indicate the source location that are the best choice based on pixel drift.
Scaling/shifting allows dynamic and seamless changing of frame size. This makes it possible to have arbitrary sized key-frames. -
Scan-line scoring and ordering.
Determines the sequence in which scan-rows/columns are processed.
Rulers contain the following information:
-
Exact coordinate.
The coordinates used to calculate the pixel value. -
Drifted coordinate.
Original coordinates of pixels in cooler areas that drift without being recalculated. -
Score.
The pixel with the highest score is calculated first.
The default value is the difference between exact/drifted coordinates. -
Source location within the previous frame.
New frames are initially populated with drifted pixels that are closest to their exact coordinates.
There are rulers for every dimensional axis.
Initial frame population performs scaling and shifting which introduces motion-blur.
Scan-line calculations determines exact pixel values for coordinates which introduces sharpness.
NOTE: Determining the ordering of scan-lines is determined exclusive by ruler metrics and not pixels values.
Coordinates
Pixel values use three different types of coordinates:
-
x,y (float) formula coordinate
These coordinates are used to access the data model. -
i,j (int) backing store location
The index/position with the data arrays. -
u,v (int) screen position
The position on the screen after backing store extraction and rotation.
Which unit is applicable depends on the position in the data path:
formula
<-xy->backingStore<-ij->clip/rotation<-uv->screen/canvas
Directional vector
The directional vector is what you see and how you move.
This is a different concept than the motion vector used for macro blocks.
Updating the vector is user-defined, the engine considers it read-only.
The vector consists of three components:
-
The x,y coordinates.
The coordinate of the screen center pixel. The current implementation is 2D and is easy extendable to 3D. -
Radius.
The radius resembles the imaginary circle that is fully visible.
For landscape this is the top/bottom height, for portrait the left/right width. -
Angle.
The rotation with the screen center pixel as anchor.
States
zoomer is a timed state machine to construct frames.
Frame construction has been split into phases/states.
The states are:
-
COPY(New frame)
Construct rulers for copying/scaling/shifting pixels from the previous frame.
Copy pixels using anindexed memcpy().
Determine calculation order of rows/columns. -
UPDATE(Calculate blurry pixels)
Update key pixels along an axis (row/column) called a scanline.
Key pixels are pixels that have been marked as scanned across all axis.
Flood fill neighbours to create motion blur usinginterleaved memcpy(). -
RENDER(RGBA frame buffer) Copy pixel values from the backing store to an RGBA storage.
Optional colour palette is applied.
Apply rotation where/when necessary usingangled memcpy(). -
PAINT(Forward to display) Write RGBA storage to the display.
Most probably the display is a canvas and written to usingputImageData().
putImageData()can be CPU intensive and has therefore a dedicated state.
State timings:
The COPY, UPDATE and PAINT states are run from the main event queue, RENDER is done by web-workers.
The duration of a complete frame is max(COPY+UPDATE+PAINT,RENDER).
The Phased Locked Loop should tune COPY+UPDATE+PAINT to equal the requested frame rate
Running on an AMD FX-8320E, state durations (mSec) have been grossly averaged in the following table:
| platform | COPY | UPDATE | RENDER | PAINT | MAX FPS | |:
