summaryrefslogtreecommitdiff
path: root/src/lowlevel/image.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lowlevel/image.rs')
-rw-r--r--src/lowlevel/image.rs139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/lowlevel/image.rs b/src/lowlevel/image.rs
index 5374b8c..6747e69 100644
--- a/src/lowlevel/image.rs
+++ b/src/lowlevel/image.rs
@@ -1,5 +1,8 @@
+use crate::{ensure_element, ensure_tag_name, get_attribute};
+use anyhow::anyhow;
use rgb::RGB8;
+#[derive(Debug, PartialEq)]
pub enum ImageSource {
External {
/// The reference to the tileset image file (Tiled supports most common image formats). Only used if the image is not embedded.
@@ -16,6 +19,7 @@ pub enum ImageSource {
},
}
+#[derive(Debug, PartialEq)]
pub struct Image {
pub source: ImageSource,
/// Defines a specific color that is treated as transparent (example value: “#FF00FF” for magenta).
@@ -26,3 +30,138 @@ pub struct Image {
/// The image height in pixels (optional)
pub height: Option<usize>,
}
+
+impl Image {
+ pub fn from_xml(node: roxmltree::Node) -> anyhow::Result<Image> {
+ ensure_element!(node);
+ ensure_tag_name!(node, "image");
+
+ let width: Option<usize> = match node.attribute("width") {
+ Some(s) => Some(s.parse()?),
+ None => None,
+ };
+
+ let height: Option<usize> = match node.attribute("height") {
+ Some(s) => Some(s.parse()?),
+ None => None,
+ };
+
+ let transparent_color: Option<RGB8> = if let Some(s) = node.attribute("trans") {
+ {
+ let mut c = s.trim_start_matches("#").chars();
+ if let Some(color) = read_color::rgb(&mut c) {
+ Ok(Some(RGB8 {
+ r: color[0],
+ g: color[1],
+ b: color[2],
+ }))
+ } else {
+ Err(anyhow!("could not parse color"))
+ }
+ }?
+ } else {
+ None
+ };
+
+ let image_source = match node.attribute("source") {
+ Some(s) => Ok(ImageSource::External {
+ source: s.to_owned(),
+ }),
+ None => {
+ // embedded
+ let _format = get_attribute!(node, "format")?;
+
+ // let xmldata_node = match node.children().find(|&c| c.has_tag_name("data")) {
+ // Some(node) => super::data::EncodedData::from_xml(node)?,
+ // None => Err(anyhow!("data element of embeded image not found")),
+ // };
+
+ // TODO
+
+ Err(anyhow!("embeded images are not implemented yet"))
+ }
+ }?;
+ Ok(Image {
+ source: image_source,
+ transparent_color,
+ width,
+ height,
+ })
+ }
+}
+
+#[cfg(test)]
+mod parse_image {
+ use crate::lowlevel::image::*;
+ use crate::parse_property_test;
+
+ #[test]
+ fn image_with_dimensions() {
+ parse_property_test!(
+ Image,
+ r##"<image source="beach_tileset.png" width="576" height="416"/>"##,
+ Image {
+ source: ImageSource::External {
+ source: "beach_tileset.png".to_owned()
+ },
+ transparent_color: None,
+ width: Some(576),
+ height: Some(416)
+ }
+ );
+ }
+
+ #[test]
+ fn image_without_dimensions() {
+ parse_property_test!(
+ Image,
+ r##"<image source="perspective_walls.png"/>"##,
+ Image {
+ source: ImageSource::External {
+ source: "perspective_walls.png".to_owned()
+ },
+ transparent_color: None,
+ width: None,
+ height: None
+ }
+ );
+ }
+
+ #[test]
+ fn image_with_transparency_color() {
+ parse_property_test!(
+ Image,
+ r##"<image source="sewer_tileset.png" trans="ff00ff" width="192" height="217"/>"##,
+ Image {
+ source: ImageSource::External {
+ source: "sewer_tileset.png".to_owned()
+ },
+ transparent_color: Some(RGB8 {
+ r: 255,
+ g: 0,
+ b: 255
+ }),
+ width: Some(192),
+ height: Some(217)
+ }
+ );
+ parse_property_test!(
+ Image,
+ r##"<image source="sewer_tileset.png" trans="#ff00ff" width="192" height="217"/>"##,
+ Image {
+ source: ImageSource::External {
+ source: "sewer_tileset.png".to_owned()
+ },
+ transparent_color: Some(RGB8 {
+ r: 255,
+ g: 0,
+ b: 255
+ }),
+ width: Some(192),
+ height: Some(217)
+ }
+ );
+ }
+
+ // TODO test embeded image
+}