Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/1TSnakers/ProgressiveImageLoader/llms.txt

Use this file to discover all available pages before exploring further.

ProgressiveImageLoader needs more than one copy of your image — it needs a sequence of copies at different quality levels, ordered from worst to best. The loader displays the lowest-quality version almost instantly (because it is a tiny file), then transparently upgrades the display as each higher-quality version finishes downloading. Preparing this sequence correctly is the single most important step before writing any JavaScript.

What you need

A valid image sequence is simply an array of paths pointing to the same subject rendered at increasing quality levels:
Array positionQuality levelRole
images[0]Most degraded (smallest file)Shown immediately while others load
images[1..n-2]Intermediate levelsProgressive upgrades
images[n-1]Full quality (largest file)Final display state
The files can live anywhere your page can reach via a URL path. Their names do not matter to the library — only their order in the array matters.

Option A — Create image variants manually

You can produce the sequence with any image editor (Photoshop, GIMP, Squoosh, etc.). The technique is flexible: you might export the same source image at multiple JPEG quality settings, resize it to progressively larger pixel dimensions, or combine both approaches. A practical three-step manual workflow:
  1. Thumbnail — resize to ~10 % of the original pixel dimensions and save as a heavily compressed file (e.g. 5–15 KB).
  2. Mid-quality — resize to ~50 % of the original dimensions or export at medium compression quality (e.g. 50–100 KB).
  3. Full quality — the original or lightly compressed source file.
Pass the resulting paths as ["thumbnail.png", "mid.png", "full.png"] to the images option.
Even with a manual approach, aim to make the first file in the sequence as small as possible — ideally under 10 KB. The speed at which the user sees something depends entirely on how fast that first file downloads.

Option B — Use the bundled image_ruiner.py script

The repository ships a Python helper script at images/image_ruiner.py that automates the entire sequence-generation workflow. It uses Pillow to create multiple downscaled versions of a source image, optionally stamps each frame with a quality-reduction label, and writes an image_list.js module you can import directly into your HTML.

Function signature

def pixel_degrade_png(
    image_path,                              # path to source image (relative to /images)
    output_dir="pixel_degraded_pngs",        # output directory (relative to /images)
    steps=8,                                 # number of degradation steps
    label_size=60,                           # font size for the percentage label
    font_file="GoogleSansCode-Regular.ttf",  # path to .ttf font file (relative to /images)
    label_prefix="Quality reduced by: ",     # prefix text on the label overlay
    show_label=True,                         # whether to draw labels on the images
):
The script produces steps + 1 files (0 % through 100 % degradation) and reverses the list before writing image_list.js, so the exported array already runs from most-degraded to least-degraded — the exact order ProgressiveImageLoader expects.

Step-by-step workflow

1

Install Pillow

The script requires the Pillow imaging library. Install it into your Python environment:
pip install Pillow
2

Place your source image in the images/ directory

Copy your full-quality source image into the images/ folder alongside image_ruiner.py. The default entry point in the script expects a file named sample.png:
images/
├── image_ruiner.py
├── sample.png          ← your source image goes here
└── GoogleSansCode-Regular.ttf
If you use a different filename, update the image_path argument in the __main__ block at the bottom of the script, or call the function directly with your filename.
3

Run the script

Execute the script from inside the images/ directory:
cd images
python image_ruiner.py
Using the default settings, this call is equivalent to:
pixel_degrade_png(
    image_path="sample.png",
    output_dir="pixel_degraded_pngs",
    steps=8,
    label_size=40,
    font_file="GoogleSansCode-Regular.ttf",
    label_prefix="Quality reduced by: ",
    show_label=True
)
4

Inspect the output

After the script completes you will find two new outputs:images/pixel_degraded_pngs/ — a directory containing 9 PNG files (for the default steps=8):
pixel_degraded_pngs/
├── degraded_000.png   # 0% quality reduction  = full quality (largest file)
├── degraded_012.png   # 12% quality reduction
├── degraded_025.png   # 25% quality reduction
├── degraded_037.png   # 37% quality reduction
├── degraded_050.png   # 50% quality reduction
├── degraded_062.png   # 62% quality reduction
├── degraded_075.png   # 75% quality reduction
├── degraded_087.png   # 87% quality reduction
└── degraded_100.png   # 100% quality reduction = most degraded (smallest file)
images/image_list.js — a JavaScript module with a pre-ordered array:
const imageList = [
  "images/pixel_degraded_pngs/degraded_100.png",  // most degraded — first
  "images/pixel_degraded_pngs/degraded_087.png",
  "images/pixel_degraded_pngs/degraded_075.png",
  "images/pixel_degraded_pngs/degraded_062.png",
  "images/pixel_degraded_pngs/degraded_050.png",
  "images/pixel_degraded_pngs/degraded_037.png",
  "images/pixel_degraded_pngs/degraded_025.png",
  "images/pixel_degraded_pngs/degraded_012.png",
  "images/pixel_degraded_pngs/degraded_000.png",  // full quality — last
];

export default imageList;
5

Import image_list.js in your HTML

Use a type="module" script tag to import the generated list and pass it directly to the loader:
<script type="module">
  import imageList from "./images/image_list.js";

  new ProgressiveImageLoader({
    container: document.getElementById("image-container"),
    images: imageList,
    width: 1250,
    fadeDuration: 500,
    disableCache: false
  });
</script>

Understanding the naming convention

The numeric suffix in each filename represents the percentage of quality reduction applied to the original image, not a quality score:

degraded_000.png

0 % quality reduction — identical to the source image. This is the full-quality version and always goes last in the images array.

degraded_100.png

100 % quality reduction — the most aggressively downscaled version. This tiny file loads fastest and always goes first in the images array.
The script achieves degradation by resizing the image down using nearest-neighbour interpolation (Image.NEAREST), which produces a pixelated, blocky appearance rather than a blurry one. At 100 % reduction the image is scaled to just 10 % of its original pixel dimensions. There is no JPEG re-compression involved — all outputs are PNGs.

Correct array ordering — a reminder

Regardless of whether you prepare images manually or with the script, the images array passed to ProgressiveImageLoader must always run from least quality to most quality:
// ✅ Correct — worst first, best last
images: [
  "degraded_100.png",  // tiny, loads immediately
  "degraded_050.png",
  "degraded_000.png",  // full quality, loads last
]

// ❌ Incorrect — reversed order defeats progressive loading
images: [
  "degraded_000.png",
  "degraded_050.png",
  "degraded_100.png",
]
The loader only upgrades — it will never display a lower-index image once a higher-index one has loaded. If you accidentally reverse the order, the full-quality image will be requested first and the degraded versions will never be shown.

Build docs developers (and LLMs) love