diff --git a/assets/tiled_flipped.tmx b/assets/tiled_flipped.tmx
new file mode 100644
index 0000000000000000000000000000000000000000..b27c0757f8ac48934b4041db29ea6c7a6aed8b08
--- /dev/null
+++ b/assets/tiled_flipped.tmx
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.2" tiledversion="1.2.5" orientation="orthogonal" renderorder="right-down" width="2" height="2" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
+ <tileset firstgid="1" source="tilesheet.tsx"/>
+ <layer id="1" name="Tile Layer 1" width="2" height="2">
+  <data encoding="csv">
+3758096387,1073741827,
+2147483651,536870915
+</data>
+ </layer>
+</map>
diff --git a/src/lib.rs b/src/lib.rs
index be48dd690a9b0f973ce86c55709e0c04245d49dd..6879b68693b168a70b5d4a0cfbfbe7d64696511f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -511,8 +511,6 @@ impl Tileset {
 #[derive(Debug, PartialEq, Clone)]
 pub struct Tile {
     pub id: u32,
-    pub flip_h: bool,
-    pub flip_v: bool,
     pub images: Vec<Image>,
     pub properties: Properties,
     pub objectgroup: Option<ObjectGroup>,
@@ -521,12 +519,6 @@ pub struct Tile {
     pub probability: f32,
 }
 
-const FLIPPED_HORIZONTALLY_FLAG: u32 = 0x8;
-const FLIPPED_VERTICALLY_FLAG: u32 = 0x4;
-const FLIPPED_DIAGONALLY_FLAG: u32 = 0x2;
-const ALL_FLIP_FLAGS: u32 =
-    FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG;
-
 impl Tile {
     fn new<R: Read>(
         parser: &mut EventReader<R>,
@@ -544,12 +536,6 @@ impl Tile {
             TiledError::MalformedAttributes("tile must have an id with the correct type".to_string())
         );
 
-        let flags = (id & ALL_FLIP_FLAGS) >> 28;
-        let id: u32 = id & !ALL_FLIP_FLAGS;
-        let diagon = flags & FLIPPED_DIAGONALLY_FLAG == FLIPPED_DIAGONALLY_FLAG;
-        let flip_h = (flags & FLIPPED_HORIZONTALLY_FLAG == FLIPPED_HORIZONTALLY_FLAG) ^ diagon;
-        let flip_v = (flags & FLIPPED_VERTICALLY_FLAG == FLIPPED_VERTICALLY_FLAG) ^ diagon;
-
         let mut images = Vec::new();
         let mut properties = HashMap::new();
         let mut objectgroup = None;
@@ -574,8 +560,6 @@ impl Tile {
         });
         Ok(Tile {
             id,
-            flip_h,
-            flip_v,
             images,
             properties,
             objectgroup,
@@ -623,6 +607,39 @@ impl Image {
     }
 }
 
+/// Stores the proper tile gid, along with how it is flipped.
+// Maybe PartialEq and Eq should be custom, so that it ignores tile-flipping?
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct LayerTile {
+    pub gid: u32,
+    pub flip_h: bool,
+    pub flip_v: bool,
+    pub flip_d: bool,
+}
+
+const FLIPPED_HORIZONTALLY_FLAG: u32 = 0x80000000;
+const FLIPPED_VERTICALLY_FLAG: u32 = 0x40000000;
+const FLIPPED_DIAGONALLY_FLAG: u32 = 0x20000000;
+const ALL_FLIP_FLAGS: u32 =
+    FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG;
+
+impl LayerTile {
+    pub fn new(id: u32) -> LayerTile {
+        let flags = id & ALL_FLIP_FLAGS;
+        let gid = id & !ALL_FLIP_FLAGS;
+        let flip_d = flags & FLIPPED_DIAGONALLY_FLAG == FLIPPED_DIAGONALLY_FLAG; // Swap x and y axis (anti-diagonally) [flips over y = -x line]
+        let flip_h = flags & FLIPPED_HORIZONTALLY_FLAG == FLIPPED_HORIZONTALLY_FLAG; // Flip tile over y axis
+        let flip_v = flags & FLIPPED_VERTICALLY_FLAG == FLIPPED_VERTICALLY_FLAG; // Flip tile over x axis
+
+        LayerTile {
+            gid,
+            flip_h,
+            flip_v,
+            flip_d,
+        }
+    }
+}
+
 #[derive(Debug, PartialEq, Clone)]
 pub struct Layer {
     pub name: String,
@@ -630,7 +647,7 @@ pub struct Layer {
     pub visible: bool,
     /// The tiles are arranged in rows. Each tile is a number which can be used
     ///  to find which tileset it belongs to and can then be rendered.
-    pub tiles: Vec<Vec<u32>>,
+    pub tiles: Vec<Vec<LayerTile>>,
     pub properties: Properties,
     pub layer_index: u32,
 }
@@ -971,7 +988,7 @@ fn parse_data<R: Read>(
     parser: &mut EventReader<R>,
     attrs: Vec<OwnedAttribute>,
     width: u32,
-) -> Result<Vec<Vec<u32>>, TiledError> {
+) -> Result<Vec<Vec<LayerTile>>, TiledError> {
     let ((e, c), ()) = get_attrs!(
         attrs,
         optionals: [
@@ -989,7 +1006,7 @@ fn parse_data<R: Read>(
             ))
         }
         (Some(e), None) => match e.as_ref() {
-            "base64" => return parse_base64(parser).map(|v| convert_to_u32(&v, width)),
+            "base64" => return parse_base64(parser).map(|v| convert_to_tile(&v, width)),
             "csv" => return decode_csv(parser),
             e => return Err(TiledError::Other(format!("Unknown encoding format {}", e))),
         },
@@ -997,12 +1014,12 @@ fn parse_data<R: Read>(
             ("base64", "zlib") => {
                 return parse_base64(parser)
                     .and_then(decode_zlib)
-                    .map(|v| convert_to_u32(&v, width))
+                    .map(|v| convert_to_tile(&v, width))
             }
             ("base64", "gzip") => {
                 return parse_base64(parser)
                     .and_then(decode_gzip)
-                    .map(|v| convert_to_u32(&v, width))
+                    .map(|v| convert_to_tile(&v, width))
             }
             (e, c) => {
                 return Err(TiledError::Other(format!(
@@ -1054,11 +1071,11 @@ fn decode_gzip(data: Vec<u8>) -> Result<Vec<u8>, TiledError> {
     Ok(data)
 }
 
-fn decode_csv<R: Read>(parser: &mut EventReader<R>) -> Result<Vec<Vec<u32>>, TiledError> {
+fn decode_csv<R: Read>(parser: &mut EventReader<R>) -> Result<Vec<Vec<LayerTile>>, TiledError> {
     loop {
         match try!(parser.next().map_err(TiledError::XmlDecodingError)) {
             XmlEvent::Characters(s) => {
-                let mut rows: Vec<Vec<u32>> = Vec::new();
+                let mut rows: Vec<Vec<LayerTile>> = Vec::new();
                 for row in s.split('\n') {
                     if row.trim() == "" {
                         continue;
@@ -1067,6 +1084,7 @@ fn decode_csv<R: Read>(parser: &mut EventReader<R>) -> Result<Vec<Vec<u32>>, Til
                         row.split(',')
                             .filter(|v| v.trim() != "")
                             .map(|v| v.replace('\r', "").parse().unwrap())
+                            .map(|id| LayerTile::new(id))
                             .collect(),
                     );
                 }
@@ -1082,7 +1100,7 @@ fn decode_csv<R: Read>(parser: &mut EventReader<R>) -> Result<Vec<Vec<u32>>, Til
     }
 }
 
-fn convert_to_u32(all: &Vec<u8>, width: u32) -> Vec<Vec<u32>> {
+fn convert_to_tile(all: &Vec<u8>, width: u32) -> Vec<Vec<LayerTile>> {
     let mut data = Vec::new();
     for chunk in all.chunks((width * 4) as usize) {
         let mut row = Vec::new();
@@ -1092,6 +1110,7 @@ fn convert_to_u32(all: &Vec<u8>, width: u32) -> Vec<Vec<u32>> {
                 + ((chunk[start + 2] as u32) << 16)
                 + ((chunk[start + 1] as u32) << 8)
                 + chunk[start] as u32;
+            let n = LayerTile::new(n);
             row.push(n);
         }
         data.push(row);
diff --git a/tests/lib.rs b/tests/lib.rs
index bf4b2739235e27e8bc437ab69fda5dce2e24c327..f5e8bd64a6d1549fded8d6a410a7770e8054eee4 100644
--- a/tests/lib.rs
+++ b/tests/lib.rs
@@ -79,3 +79,27 @@ fn test_object_group_property() {
     };
     assert!(prop_value);
 }
+
+#[test]
+fn test_flipped_gid() {
+    let r = read_from_file_with_path(&Path::new("assets/tiled_flipped.tmx")).unwrap();
+    let t1 = r.layers[0].tiles[0][0];
+    let t2 = r.layers[0].tiles[0][1];
+    let t3 = r.layers[0].tiles[1][0];
+    let t4 = r.layers[0].tiles[1][1];
+    assert_eq!(t1.gid, t2.gid);
+    assert_eq!(t2.gid, t3.gid);
+    assert_eq!(t3.gid, t4.gid);
+    assert!(t1.flip_d);
+    assert!(t1.flip_h);
+    assert!(t1.flip_v);
+    assert!(!t2.flip_d);
+    assert!(!t2.flip_h);
+    assert!(t2.flip_v);
+    assert!(!t3.flip_d);
+    assert!(t3.flip_h);
+    assert!(!t3.flip_v);
+    assert!(t4.flip_d);
+    assert!(!t4.flip_h);
+    assert!(!t4.flip_v);
+}