Skip to content

Instantly share code, notes, and snippets.

@jia-kai
Last active December 8, 2025 20:54
Show Gist options
  • Select an option

  • Save jia-kai/802de63816711d67f0a090fa267ac3ae to your computer and use it in GitHub Desktop.

Select an option

Save jia-kai/802de63816711d67f0a090fa267ac3ae to your computer and use it in GitHub Desktop.
Your goal is to create an HTML5 website that is pixel-accurate as the screenshot @Space-Jam.png . You can use the image files in the `img` folder. To achieve pixel-level reproduction, first write auxiliary programs to measure the pixel locations of the objects on this page. Then use your measurements to create the page. Consider using feature detection/matching with per-object (x, y) offsets and a global scale factor shared by all objects as the free parameters. Consider using RANSAC for robust estimation. After obtaining an initial estimation, crop the image of each object and use local sparse optical flow for refinement. Use JPG format for visual inspection of intermediate results. Your webpage should be able to scale with the window size.

Space Jam Website Pixel-Accurate Reproduction

Overview

This project creates a pixel-accurate HTML5 reproduction of the classic Space Jam website from a screenshot. The webpage scales responsively with the browser window while maintaining exact relative positioning of all elements.

Methodology

1. Feature Detection & Template Matching

  • Used OpenCV's multi-scale template matching to locate each navigation element
  • Scales tested: 0.5x to 2.0x in 30 steps
  • Handled alpha channel transparency in GIF images

2. RANSAC-Based Scale Estimation

  • Applied SIFT feature detection and FLANN-based matching
  • Used RANSAC (Random Sample Consensus) to robustly estimate global scale factor
  • Global scale factor: 1.276 (images in screenshot are scaled up from original GIFs)

3. Optical Flow Refinement

  • Used Lucas-Kanade sparse optical flow for sub-pixel position refinement
  • Detected good features to track in template images
  • Calculated median displacement for robust offset estimation

4. Comparison & Validation

  • Firefox headless rendering for pixel-accurate comparison
  • Template matching to verify final element positions
  • All elements within <2px offset from original

Results

Metric Value
Screenshot dimensions 2486 x 1265 px
Global scale factor 1.276
Image similarity 84.56%
Max element offset <2 pixels

Per-Element Confidence Scores

Element Confidence Offset
Logo 0.920 <2px
Planet B-Ball 0.927 <2px
Jam Central 0.931 <2px
Lunar Tunes 0.908 <2px
Press Box Shuttle 0.884 <2px
The Lineup 0.955 <2px
Junior Jam 0.934 <2px
Stellar Souvenirs 0.955 <2px
Jump Station 0.972 <2px
Warner Studio Store 0.910 <2px
Behind the Jam 0.859 <2px
Site Map 0.895 <2px

Files

Main Output

  • index.html - Pixel-accurate, responsive webpage

Measurement Tools

  • measure_objects.py - Feature detection with multi-scale template matching and RANSAC
  • refine_positions.py - Optical flow-based position refinement
  • create_comparison.py - Visual comparison generator
  • analyze_footer.py - Footer text position analysis

Measurements Output

  • measurements/measurements.json - Detected positions and scale factors
  • measurements/refinements.json - Position refinement data
  • measurements/detections.jpg - Visualization of detected elements
  • measurements/html_render.png - Firefox rendering of HTML
  • measurements/overlay_50_50.jpg - 50/50 blend comparison
  • measurements/highlight_diff.jpg - Difference visualization

Technical Notes

Why 84.56% similarity (not 100%)?

The remaining 15% difference comes from the star background tiling. The bg_stars.gif background repeats across the page, but the tiling origin in the HTML cannot perfectly match the original screenshot's tiling phase. All actual content elements (logo, planets, text) are pixel-accurately positioned.

Responsive Scaling

The webpage uses percentage-based CSS positioning:

  • Container maintains original aspect ratio (50.88% padding-top)
  • All elements positioned using left and top percentages
  • Element widths calculated as percentage of viewport
  • transform: translate(-50%, -50%) centers elements on their anchor points

Usage

Open index.html in any modern browser. The page will scale proportionally with the window size while maintaining the exact layout of the original Space Jam website.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Space Jam</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
overflow: hidden;
scrollbar-width: none;
-ms-overflow-style: none;
}
html::-webkit-scrollbar,
body::-webkit-scrollbar {
display: none;
}
body {
background-color: #000;
background-image: url('img/bg_stars.gif');
background-repeat: repeat;
font-family: Arial, sans-serif;
min-height: 100vh;
}
/* Container maintains aspect ratio of original screenshot: 1265/2486 */
.container {
position: relative;
width: 100%;
padding-top: 50.88%;
overflow: visible;
}
.content {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* Navigation items - positioned using percentages from measurements */
.nav-item {
position: absolute;
transform: translate(-50%, -50%);
}
.nav-item img {
display: block;
width: 100%;
height: auto;
}
.nav-item a {
display: block;
}
/*
* Measurements from original screenshot (2486 x 1265):
* Global scale factor: 1.276 (images in screenshot are scaled from original GIFs)
* Each element's position is its center as a percentage of viewport
*/
/* Logo - center_x: 1242, center_y: 453 -> 49.96%, 35.81% */
.logo {
left: 49.96%;
top: 35.81%;
width: calc(100% * 347 / 2486); /* 13.96% */
}
/* Planet B-Ball - center: (1365, 226) -> 54.91%, 17.87% */
.planet-bball {
left: 54.91%;
top: 17.87%;
width: calc(100% * 79 / 2486); /* 3.18% */
}
/* Jam Central - center: (1232, 264) -> 49.56%, 20.87% */
.jam-central {
left: 49.56%;
top: 20.87%;
width: calc(100% * 70 / 2486); /* 2.82% */
}
/* Lunar Tunes - center: (1489, 294) -> 59.90%, 23.24% */
.lunar-tunes {
left: 59.90%;
top: 23.24%;
width: calc(100% * 121 / 2486); /* 4.87% */
}
/* Press Box - center: (1064, 306) -> 42.80%, 24.19% */
.press-box {
left: 42.80%;
top: 24.19%;
width: calc(100% * 167 / 2486); /* 6.72% */
}
/* The Lineup - center: (973, 437) -> 39.14%, 34.55% */
.the-lineup {
left: 39.14%;
top: 34.55%;
width: calc(100% * 80 / 2486); /* 3.22% */
}
/* Junior Jam - center: (973, 522) -> 39.14%, 41.26% */
.junior-jam {
left: 39.14%;
top: 41.26%;
width: calc(100% * 62 / 2486); /* 2.49% */
}
/* Stellar Souvenirs - center: (1085, 616) -> 43.64%, 48.70% */
.souvenirs {
left: 43.64%;
top: 48.70%;
width: calc(100% * 105 / 2486); /* 4.22% */
}
/* Jump Station - center: (1521, 443) -> 61.18%, 35.02% */
.jump-station {
left: 61.18%;
top: 35.02%;
width: calc(100% * 74 / 2486); /* 2.98% */
}
/* Warner Studio Store - center: (1489, 583) -> 59.90%, 46.09% */
.studio-store {
left: 59.90%;
top: 46.09%;
width: calc(100% * 119 / 2486); /* 4.79% */
}
/* Behind the Jam - center: (1365, 662) -> 54.91%, 52.33% */
.behind-jam {
left: 54.91%;
top: 52.33%;
width: calc(100% * 85 / 2486); /* 3.42% */
}
/* Site Map - center: (1232, 718) -> 49.56%, 56.76% */
.site-map {
left: 49.56%;
top: 56.76%;
width: calc(100% * 132 / 2486); /* 5.31% */
}
/* Footer positioned at ~76% from top */
.footer {
position: absolute;
left: 50%;
transform: translateX(-50%);
top: 75.53%;
text-align: center;
width: 100%;
}
.footer-links {
margin-bottom: 0.4%;
}
.footer-links a {
color: #b33;
text-decoration: underline;
font-size: calc(100vw * 14 / 2486);
margin: 0 0.3%;
}
.footer-links a:hover {
color: #f55;
}
.copyright {
color: #933;
font-size: calc(100vw * 12 / 2486);
line-height: 1.5;
}
</style>
</head>
<body>
<div class="container">
<div class="content">
<!-- Central Logo -->
<div class="nav-item logo">
<img src="img/p-jamlogo.gif" alt="Space Jam">
</div>
<!-- Navigation Planets -->
<div class="nav-item planet-bball">
<a href="#planetbball"><img src="img/p-bball.gif" alt="Planet B-Ball"></a>
</div>
<div class="nav-item jam-central">
<a href="#jamcentral"><img src="img/p-jamcentral.gif" alt="Jam Central"></a>
</div>
<div class="nav-item lunar-tunes">
<a href="#lunartunes"><img src="img/p-lunartunes.gif" alt="Lunar Tunes"></a>
</div>
<div class="nav-item press-box">
<a href="#pressbox"><img src="img/p-pressbox.gif" alt="Press Box Shuttle"></a>
</div>
<div class="nav-item the-lineup">
<a href="#lineup"><img src="img/p-lineup.gif" alt="The Lineup"></a>
</div>
<div class="nav-item junior-jam">
<a href="#juniorjam"><img src="img/p-junior.gif" alt="Junior Jam"></a>
</div>
<div class="nav-item souvenirs">
<a href="#souvenirs"><img src="img/p-souvenirs.gif" alt="Stellar Souvenirs"></a>
</div>
<div class="nav-item jump-station">
<a href="#jumpstation"><img src="img/p-jump.gif" alt="Jump Station"></a>
</div>
<div class="nav-item studio-store">
<a href="#studiostore"><img src="img/p-studiostore.gif" alt="Warner Studio Store"></a>
</div>
<div class="nav-item behind-jam">
<a href="#behind"><img src="img/p-behind.gif" alt="Behind the Jam"></a>
</div>
<div class="nav-item site-map">
<a href="#sitemap"><img src="img/p-sitemap.gif" alt="Site Map"></a>
</div>
<!-- Footer -->
<div class="footer">
<div class="footer-links">
<a href="#privacy">Privacy Policy</a>
<a href="#terms">Terms</a>
<a href="#accessibility">Accessibility</a>
<a href="#adchoices">AdChoices</a>
</div>
<div class="copyright">
SPACE JAM, characters, names, and all related<br>
indicia are trademarks of Warner Bros. &copy; 1996
</div>
</div>
</div>
</div>
</body>
</html>
@jia-kai
Copy link
Author

jia-kai commented Dec 8, 2025

pixel diff

diff

50-50 overlay

overlay_50_50

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment