The pin moves to the July 2004 Blue Marble Next Generation variant with shaded relief and ocean-floor bathymetry -- the rendering NASA's own maps lead with, and the one that gives the planet its texture instead of a flat dark ocean. Same publication family, same single pinned image, new URL, new digest, new first-capture time. The capture also cuts one level deeper: local zoom 6, a 16384×8192 picture the 21600-wide source still fills with real detail, encoded at JPEG quality 85 -- measured against quality 90, the two are visually indistinguishable tile for tile, and the finished bundle lands at 21 MiB against 24 at 90, inside the 25 MiB budget with room kept. The world's ground is unchanged: the raster still fills the top half of the world square and zoom 6 is simply detail past the world-pixel resolution, the way every deep pyramid in the corpus is.
- commit
- 1171ebc4feb8eb6f0f545dd7994bc60eca1ecac9
- parent
- 7e3826a506e027eae8f3f0d02cb6d5fb4544ed58
- author
- Dami <dami.etoile@gmail.com>
- kind
- feat risk score 2.0 of 3, Jev's estimate
| M | docs/ | 2 | +- |
| M | docs/ | 2 | +- |
| M | included/ | 36 | ++++++++++++++++++------------- |
| D | included/ | bin | |
| A | included/ | bin | |
| M | internal/ | 31 | +++++++++++++++----------- |
| M | internal/ | 6 | +++--- |
| M | main_test.go | 13 | ++++++----- |
@@ -43,7 +43,7 @@ idempotent install.
4343 4444 - A first launch opens onto a world, and the empty-library card becomes a4545 state most readers never see.46-- The repository carries a ~5 MiB binary artifact, regenerable byte for byte46+- The repository carries a ~21 MiB binary artifact, regenerable byte for byte4747 from the pin by `make included-earth`, with its provenance and recipe beside4848 it in `included/README.md`.4949 - The e2e registry gains its first volume with real rasters, so the data@@ -310,7 +310,7 @@ single pinned publication rather than a live endpoint.
310310 The crawler half (`internal/generate/crawl/bluemarble.go`) is the one place311311 the pinned URL, digest and capture time are spelled. It fetches the source312312 image exactly once into the staged archive, refuses any digest but the pinned313-one, cuts the reference level through the deterministic fixed-point313+one, cuts the pyramid's deepest level through the deterministic fixed-point314314 Catmull-Rom resampler beside it, and records the capture under the pinned315315 time, so the archive — and everything stamped downstream of it — reproduces on316316 any machine. `included/README.md` is the recipe and the provenance, and@@ -16,12 +16,12 @@ collections, no features, and no runtime network dependency of any kind.
1616 1717 | Fact | Value |1818 |---|---|19-| Product | Blue Marble: Next Generation, July 2004 — NASA Earth Observatory's global, cloud-free, true-color base map |20-| Product page | <https://science.nasa.gov/earth/earth-observatory/blue-marble-next-generation/base-map/> |21-| Source image | <https://assets.science.nasa.gov/content/dam/science/esd/eo/images/bmng/bmng-base/july/world.200407.3x21600x10800.jpg> |19+| Product | Blue Marble: Next Generation w/ Topography and Bathymetry, July 2004 — NASA Earth Observatory's global, cloud-free, true-color composite with shaded relief and ocean-floor bathymetry |20+| Product page | <https://science.nasa.gov/earth/earth-observatory/blue-marble-next-generation/base-topography-bathymetry/> |21+| Source image | <https://assets.science.nasa.gov/content/dam/science/esd/eo/images/bmng/bmng-topography-bathymetry/july/world.topo.bathy.200407.3x21600x10800.jpg> |2222 | Source dimensions | 21600 × 10800 |23-| Source SHA-256 | `dea8b4dc8a4f93f5f8bce0c8c85a508a178e7901e9ed8e6bf86e6ce7ef6d61e2` |24-| First captured | `2026-08-03T14:30:39Z` |23+| Source SHA-256 | `d225f1f35a6448a4d1d8f6de6e48f3433e470085b70a35800e64f384f269a7b0` |24+| First captured | `2026-08-03T15:27:26Z` |2525 | Credit | NASA Earth Observatory |2626 2727 NASA imagery is free of copyright. NASA's media guidelines ask that the credit@@ -32,17 +32,23 @@ runtime-URL prohibition holds for this volume exactly as for any other.
3232 3333 ## Derivation3434 35-The pinned source is downsampled to the 8192 × 4096 reference level — the top36-half of the world square, the shared whole-sphere equirectangular window35+The pinned source is downsampled to the pyramid's deepest level — local zoom36+6, a 16384 × 8192 picture the 21600-wide source still fills with real detail —37+through the deterministic fixed-point Catmull-Rom resampler in38+`internal/generate/crawl/resample.go` (`catmull-rom-fixed15`), cut into39+256-pixel tiles, and encoded as JPEG at quality **85**40+(`internal/generate/crawl/bluemarble.go` is the one place both settings are41+spelled). The world's ground is unchanged by the depth: the raster fills the42+top half of the world square, the shared whole-sphere equirectangular window3743 (`atlas.geometry.equirect.px = 0,0,8192,4096`,38-`atlas.geometry.equirect.deg = -180,90,180,-90`) — through the deterministic39-fixed-point Catmull-Rom resampler in `internal/generate/crawl/resample.go`40-(`catmull-rom-fixed15`), cut into 256-pixel tiles, and encoded as JPEG at41-quality **90** (`internal/generate/crawl/bluemarble.go` is the one place that42-setting is spelled). The ordinary tile lane derives every shallower level,43-coverage, bounds and stamps from that reference level, and the ordinary compose44-lane writes and validates the bundle. The full extent survives uncropped, and45-tiles are stored, not deflated, as format v3 requires.44+`atlas.geometry.equirect.deg = -180,90,180,-90`), and zoom 6 is simply detail45+past the world-pixel resolution, the way every deep pyramid in the corpus is.46+The ordinary tile lane folds the reference level and everything shallower down47+from the cut and derives coverage, bounds and stamps; the ordinary compose lane48+writes and validates the bundle. The full extent survives uncropped, tiles are49+stored, not deflated, as format v3 requires, and the finished file is ~21 MiB —50+inside the 25 MiB budget the included volume keeps so the executable stays51+portable.4652 4753 ## Regeneration4854 Binary file.
Binary file.
@@ -59,17 +59,19 @@ type blueMarblePin struct {
5959 Quality int6060 }6161 62-// blueMarble is the shipped pin: Blue Marble Next Generation, July 2004, as63-// published by NASA Earth Observatory. included/README.md is the recipe that64-// carries these same facts for a person.62+// blueMarble is the shipped pin: Blue Marble Next Generation with topography63+// and bathymetry, July 2004, as published by NASA Earth Observatory -- the64+// variant whose shaded relief and ocean floor give the planet its texture,65+// which is also the rendering NASA's own maps lead with. included/README.md is66+// the recipe that carries these same facts for a person.6567 var blueMarble = blueMarblePin{66- Page: "https://science.nasa.gov/earth/earth-observatory/blue-marble-next-generation/base-map/",67- Asset: "https://assets.science.nasa.gov/content/dam/science/esd/eo/images/bmng/bmng-base/july/world.200407.3x21600x10800.jpg",68- SHA256: "dea8b4dc8a4f93f5f8bce0c8c85a508a178e7901e9ed8e6bf86e6ce7ef6d61e2",69- CapturedAt: "2026-08-03T14:30:39Z",68+ Page: "https://science.nasa.gov/earth/earth-observatory/blue-marble-next-generation/base-topography-bathymetry/",69+ Asset: "https://assets.science.nasa.gov/content/dam/science/esd/eo/images/bmng/bmng-topography-bathymetry/july/world.topo.bathy.200407.3x21600x10800.jpg",70+ SHA256: "d225f1f35a6448a4d1d8f6de6e48f3433e470085b70a35800e64f384f269a7b0",71+ CapturedAt: "2026-08-03T15:27:26Z",7072 Width: 21600,7173 Height: 10800,72- Quality: 90,74+ Quality: 85,7375 }7476 7577 // blueMarbleResampler names the cut for the capture body: the resampler beside@@ -77,9 +79,12 @@ var blueMarble = blueMarblePin{
7779 // is cut renames this, and the renamed policy reads as a new capture.7880 const blueMarbleResampler = "catmull-rom-fixed15"7981 80-// blueMarbleZoom is the reference level the source is cut to: the level whose81-// pixels are the world square's own, holding the whole 8192×4096 picture.82-const blueMarbleZoom = doc.SyntheticZoom82+// blueMarbleZoom is the level the source is cut to: one deeper than the83+// reference level whose pixels are the world square's own, so the pyramid84+// holds a 16384×8192 picture the 21600-wide source still fills with real85+// detail. The deriver folds the reference level and everything shallower down86+// from this cut.87+const blueMarbleZoom = doc.SyntheticZoom + 18388 8489 // blueMarbleIDBit marks Blue Marble identities in the archive register, beside8590 // the bits the other sources' identities carry.@@ -184,7 +189,7 @@ func verifyBlueMarble(data []byte, pin blueMarblePin) error {
184189 }185190 186191 // writeBlueMarble derives the capture from verified source bytes: the image187-// decoded, held to its declared size, cut to the reference level through the192+// decoded, held to its declared size, cut to the capture level through the188193 // deterministic resampler, tiled, and recorded -- and the capture body written189194 // last, carrying the product's identity and the policy the cut was made under.190195 func writeBlueMarble(store *Archive, worldDir string, worldID int64, pin blueMarblePin, source []byte, log *slog.Logger) error {@@ -240,7 +245,7 @@ func writeBlueMarble(store *Archive, worldDir string, worldID int64, pin blueMar
240245 body, err := json.MarshalIndent(blueMarbleCapture{241246 Source: nasabluemarble.SourceName,242247 Body: nasabluemarble.Body,243- Product: "Blue Marble: Next Generation, July 2004",248+ Product: "Blue Marble: Next Generation w/ Topography and Bathymetry, July 2004",244249 Credit: "NASA Earth Observatory",245250 AssetSHA256: pin.SHA256,246251 Width: pin.Width,@@ -21,13 +21,13 @@ import (
2121 // the digest decides which bytes are accepted, the capture time decides the2222 // bundle's name, and the credit is what NASA asks a republisher to keep.2323 func TestBlueMarblePinsTheSpecifiedPublication(t *testing.T) {24- if blueMarble.Asset != "https://assets.science.nasa.gov/content/dam/science/esd/eo/images/bmng/bmng-base/july/world.200407.3x21600x10800.jpg" {24+ if blueMarble.Asset != "https://assets.science.nasa.gov/content/dam/science/esd/eo/images/bmng/bmng-topography-bathymetry/july/world.topo.bathy.200407.3x21600x10800.jpg" {2525 t.Errorf("asset URL %q is not the pinned publication", blueMarble.Asset)2626 }27- if blueMarble.SHA256 != "dea8b4dc8a4f93f5f8bce0c8c85a508a178e7901e9ed8e6bf86e6ce7ef6d61e2" {27+ if blueMarble.SHA256 != "d225f1f35a6448a4d1d8f6de6e48f3433e470085b70a35800e64f384f269a7b0" {2828 t.Errorf("digest %q is not the pinned digest", blueMarble.SHA256)2929 }30- if blueMarble.CapturedAt != "2026-08-03T14:30:39Z" {30+ if blueMarble.CapturedAt != "2026-08-03T15:27:26Z" {3131 t.Errorf("capture time %q is not the recorded first capture", blueMarble.CapturedAt)3232 }3333 if blueMarble.Width != 21600 || blueMarble.Height != 10800 {@@ -113,7 +113,7 @@ func TestIncludedEarthIsAValidOrdinaryBundle(t *testing.T) {
113113 if m.Worlds[0].Points != 0 || m.Worlds[0].Paths != 0 || m.Worlds[0].Areas != 0 {114114 t.Errorf("the manifest counts features on a raster-only world: %+v", m.Worlds[0])115115 }116- if m.Version.CreatedAt != "2026-08-03T14:30:39Z" {116+ if m.Version.CreatedAt != "2026-08-03T15:27:26Z" {117117 t.Errorf("createdAt %s is not the pinned capture time", m.Version.CreatedAt)118118 }119119 }@@ -135,12 +135,12 @@ func TestIncludedEarthDeclaresTheWholeSphere(t *testing.T) {
135135 if lens.Name != "Blue Marble" {136136 t.Errorf("lens %q", lens.Name)137137 }138- if lens.MinZoom != 0 || lens.MaxZoom != 5 || lens.FullZoom != 5 || lens.SourceZoom != 5 {139- t.Errorf("zooms min %d max %d full %d source %d, want 0/5/5/5",138+ if lens.MinZoom != 0 || lens.MaxZoom != 6 || lens.FullZoom != 6 || lens.SourceZoom != 6 {139+ t.Errorf("zooms min %d max %d full %d source %d, want 0/6/6/6",140140 lens.MinZoom, lens.MaxZoom, lens.FullZoom, lens.SourceZoom)141141 }142- if len(lens.Formats) != 6 {143- t.Errorf("%d formats for 6 levels", len(lens.Formats))142+ if len(lens.Formats) != 7 {143+ t.Errorf("%d formats for 7 levels", len(lens.Formats))144144 }145145 for _, format := range lens.Formats {146146 if format != "jpg" {@@ -190,7 +190,7 @@ func TestIncludedEarthPyramidOpensAtEveryLevel(t *testing.T) {
190190 t.Fatalf("%s is compressed; format v3 stores tiles", name)191191 }192192 }193- wantPerLevel := map[string]int{"0": 1, "1": 2, "2": 8, "3": 32, "4": 128, "5": 512}193+ wantPerLevel := map[string]int{"0": 1, "1": 2, "2": 8, "3": 32, "4": 128, "5": 512, "6": 2048}194194 for level, want := range wantPerLevel {195195 if perLevel[level] != want {196196 t.Errorf("level %s holds %d tiles, want %d", level, perLevel[level], want)@@ -200,6 +200,7 @@ func TestIncludedEarthPyramidOpensAtEveryLevel(t *testing.T) {
200200 for _, name := range []string{201201 "tiles/earth/0/0/0.jpg", "tiles/earth/1/1/0.jpg", "tiles/earth/2/3/1.jpg",202202 "tiles/earth/3/7/3.jpg", "tiles/earth/4/15/7.jpg", "tiles/earth/5/31/15.jpg",203+ "tiles/earth/6/63/31.jpg",203204 } {204205 data, err := reader.ReadEntry(name)205206 if err != nil {