summaryrefslogblamecommitdiff
path: root/src/lowlevel/image.rs
blob: 7b08bccedb6d342b130c2f0582d1dac7ab58f52e (plain) (tree)
1
2
3
4
5

                                                            

              
                           















                                                                                                                                             
                           









                                                                                                           

















                                                                                        
                                                              



















































































































                                                                                                
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.
        source: String,
    },

    /// Embedded images with a data child element
    ///
    /// Note that it is not currently possible to use Tiled to create maps with embedded image data, even though the TMX format supports this
    Embedded {
        /// . Valid values are file extensions like png, gif, jpg, bmp, etc.
        format: String,
        data: super::data::EncodedData,
    },
}

#[derive(Debug, PartialEq)]
pub struct Image {
    pub source: ImageSource,
    /// Defines a specific color that is treated as transparent (example value: “#FF00FF” for magenta).
    /// Including the “#” is optional and Tiled leaves it out for compatibility reasons. (optional)
    pub transparent_color: Option<RGB8>,
    /// The image width in pixels (optional, used for tile index correction when the image changes)
    pub width: Option<usize>,
    /// 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
}