Пример #1
0
        //CALL STACK: LoadData -> ReadLayerFromStream
        private static CompressedLayer _ReadLayerFromStream(BinaryReader br, BahnLib.ZoomFactor zoomFactor, GraphicVersion graphicVersion)
        {
            if (br == null)
            {
                throw new ArgumentNullException("br");
            }

            CompressedLayer l = new CompressedLayer();

            l.X0     = br.ReadInt16();
            l.Y0     = br.ReadInt16();
            l.Width  = br.ReadInt16();
            l.Height = br.ReadInt16();
            if (graphicVersion == GraphicVersion.Version2)
            {
                int         layerLength = br.ReadInt32();
                List <uint> data        = new List <uint>();
                for (int i = 0; i < layerLength; i++)
                {
                    data.Add(br.ReadUInt32());
                }
                l.LayerData = data.ToArray();
            }
            else if (graphicVersion < GraphicVersion.Version2)
            {
                uint[,] decompressedLayer = _ReadLayerFromStreamVersion0(br, l.Width, l.Height);
                l = CompressLayer(_FillLayer(decompressedLayer, l.X0, l.Y0, zoomFactor), zoomFactor);
            }
            else
            {
                throw new ArgumentOutOfRangeException("graphicVersion");
            }
            return(l);
        }
Пример #2
0
        private static void _WriteLayerToStream(CompressedLayer layer, BinaryWriter bw, BahnLib.ZoomFactor zoomFactor)
        {
            if (bw == null)
            {
                throw new ArgumentNullException("bw");
            }

            bw.Write(layer.X0);             //x0
            bw.Write(layer.Y0);             //y0
            bw.Write(layer.Width);          //width
            bw.Write(layer.Height);         //height
            bw.Write(layer.LayerData.Length);
            foreach (uint item in layer.LayerData)
            {
                bw.Write(item);
            }
        }
Пример #3
0
 /// <summary>
 /// Gets or sets a layer of the graphic. Null-value represents an empty or fully transparent layer.
 /// </summary>
 /// <param name="layerID">The LayerID</param>
 /// <returns>The layer</returns>
 public uint[, ] this[LayerID layerID]
 {
     get
     {
         if (!layersCompressed.ContainsKey(layerID))
         {
             uint[,] layer = new uint[Constants.ElementHeight * 8 * (byte)this.ZoomFactor, Constants.ElementWidth * 3 * (byte)this.ZoomFactor];
             for (int x = 0; x < layer.GetLength(Width); x++)
             {
                 for (int y = 0; y < layer.GetLength(Height); y++)
                 {
                     layer[y, x] = Constants.ColorTransparent;
                 }
             }
             return(layer);
         }
         return(DecompressLayer(this.layersCompressed[layerID], this.ZoomFactor));
     }
     set
     {
         if (value == null)
         {
             this.layersCompressed.Remove(layerID);
         }
         else
         {
             CompressedLayer compressedLayer = CompressLayer(value, this.ZoomFactor);
             if (compressedLayer == null)
             {
                 this.layersCompressed.Remove(layerID);
             }
             else
             {
                 this.layersCompressed[layerID] = compressedLayer;
             }
         }
     }
 }
Пример #4
0
        private static CompressedLayer CompressLayer(uint[,] decompressedLayer, ZoomFactor zoomFactor)
        {
            int layerWidth  = decompressedLayer.GetLength(Width);
            int layerHeight = decompressedLayer.GetLength(Height);
            int minx        = layerWidth;
            int miny        = layerHeight;
            int maxx        = 0;
            int maxy        = 0;

            for (int i = 0; i < layerHeight; i++)
            {
                for (int j = 0; j < layerWidth; j++)
                {
                    if (decompressedLayer[i, j] != Constants.ColorTransparent)
                    {
                        if (minx > j)
                        {
                            minx = j;
                        }
                        if (maxx < j)
                        {
                            maxx = j;
                        }
                        if (miny > i)
                        {
                            miny = i;
                        }
                        if (maxy < i)
                        {
                            maxy = i;
                        }
                    }
                }
            }
            if (maxx == 0 && maxy == 0)
            {
                return(null);
            }
            maxx++;
            maxy++;
            List <uint> pixels        = new List <uint>();
            int         trimmedHeight = maxy - miny;
            int         trimmedWidth  = maxx - minx;

            for (int i = 0; i < trimmedHeight; i++)
            {
                for (int j = 0; j < trimmedWidth; j++)
                {
                    pixels.Add(decompressedLayer[i + miny, j + minx]);
                }
            }
            short x0 = (short)(minx - Constants.ElementWidth * (int)zoomFactor);
            short y0 = (short)(miny - Constants.ElementHeight * (int)zoomFactor);

            List <uint> colors        = new List <uint>();
            int         colorposition = 0;

            while (colorposition < pixels.Count)
            {
                int  length    = 0;
                uint lastcolor = pixels[colorposition];
                for (; colorposition < pixels.Count; colorposition++)
                {
                    if (lastcolor != pixels[colorposition] || length > 256)
                    {
                        break;
                    }
                    length++;
                    lastcolor = pixels[colorposition];
                }
                if (length <= 1)
                {
                    colors.Add(lastcolor);
                }
                else if (lastcolor == Constants.ColorTransparent)
                {
                    colors.Add(Constants.ColorCompressedTransparent | (uint)(length - 2));
                }
                else if (((lastcolor & Constants.ColorLogic) != 0) && lastcolor != (uint)Pixel.PixelProperty.BehindGlass)
                {
                    uint color = lastcolor - Constants.ColorAsMin;
                    color = color << 8;
                    color = color | Constants.ColorCompressedSystemcolor;
                    colors.Add(color | (uint)(length - 2));
                }
                else
                {
                    colors.Add(Constants.ColorCompressed | (uint)(length - 2));
                    colors.Add(lastcolor);
                }
            }
            CompressedLayer layer = new CompressedLayer();

            layer.LayerData = colors.ToArray();
            layer.X0        = x0;
            layer.Y0        = y0;
            layer.Height    = (short)trimmedHeight;
            layer.Width     = (short)trimmedWidth;
            return(layer);
        }
Пример #5
0
        private static uint[,] DecompressLayer(CompressedLayer layer, ZoomFactor zoomFactor)
        {
            int         arrayPosition = 0;
            List <uint> colors        = new List <uint>();

            for (int i = 0; i < layer.LayerData.Length; i++)
            {
                uint item  = layer.LayerData[arrayPosition++];
                int  count = 0;
                if ((item & Constants.ColorAdditionalDataMask) == Constants.ColorCompressed)
                {
                    count = (int)(item & Constants.ColorMaskCompressedCount) + 2;
                    if ((item & Constants.ColorMaskCompressedTransparent) != 0)
                    {
                        // item is transparent
                        for (int k = 0; k < count; k++)
                        {
                            colors.Add(Constants.ColorTransparent);
                        }
                    }
                    else if ((item & Constants.ColorMaskCompressedSystemcolor) != 0)
                    {
                        // item is a system-color
                        for (int k = 0; k < count; k++)
                        {
                            colors.Add(((item & Constants.ColorMaskCompressedSFB) >> 8) + Constants.ColorAsMin);
                        }
                    }
                    else
                    {
                        // item is a color, may be a set of colors
                        uint wdhlen = ((item & Constants.ColorMaskCompressedLength) >> 8) + 1;
                        if (wdhlen > Constants.MaxRepeatedColorsLength)
                        {
                            throw new InvalidDataException("color repetition length out of range");
                        }
                        List <uint> buffer = new List <uint>();
                        for (int j = 0; j < wdhlen; j++)
                        {
                            buffer.Add(layer.LayerData[arrayPosition++]);
                            i++;
                        }
                        for (int j = 0; j < count; j++)
                        {
                            foreach (var b in buffer)
                            {
                                colors.Add(b);
                            }
                        }
                    }
                }
                else
                {
                    // not packed, single pixel
                    count = 1;
                    colors.Add(item);
                }
            }
            int height = Constants.ElementHeight * 8 * (int)zoomFactor;
            int width  = Constants.ElementWidth * 3 * (int)zoomFactor;

            uint[,] layerElement = new uint[height, width];
            int x0  = (int)(layer.X0 + Constants.ElementWidth * (int)zoomFactor);
            int y0  = (int)(layer.Y0 + Constants.ElementHeight * (int)zoomFactor);
            int _x0 = x0 + layer.Width;
            int _y0 = y0 + layer.Height;

            int position = 0;

            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    if (i >= y0 && i < _y0 && j >= x0 && j < _x0)
                    {
                        layerElement[i, j] = colors[position++];
                    }
                    else
                    {
                        layerElement[i, j] = Constants.ColorTransparent;
                    }
                }
            }
            return(layerElement);
        }
Пример #6
0
        internal static Graphic Load(BinaryReader br)
        {
            if (br == null)
            {
                throw new ArgumentNullException("br");
            }

            // Load Header
            Graphic graphic = new Graphic();

            while (br.ReadByte() != Constants.HeaderTextTerminator)
            {
            }                                                                                              //Headertext, can be skipped
            byte[] readIdentification = br.ReadBytes(3);                                                   //Read indentification string
            if (readIdentification[0] != 71 || readIdentification[1] != 90 || readIdentification[2] != 71) //identification string "GZG" ASCII-format
            {
                throw new InvalidDataException("wrong identification string");
            }

            byte zoomFactor = (byte)(br.ReadByte() - 48);             //Zoomfactor is read as ASCII-character, then "converted" to a byte

            //ASCII 0 => 48, ASCII 1 => 49, etc...
            switch (zoomFactor)
            {
            case 1:
            case 2:
            case 4:
                graphic.ZoomFactor = (ZoomFactor)zoomFactor;
                break;

            default:
                throw new InvalidDataException("unknown zoom factor");
            }
            ushort readMajorVersion = br.ReadUInt16();

            byte[] readMinorVersion = br.ReadBytes(2);
            if (readMajorVersion != Constants.GraphicFileFormat || readMinorVersion[0] != 0x00)
            {
                throw new InvalidDataException("wrong version");
            }
            switch (readMinorVersion[1])
            {
            case (byte)GraphicVersion.Version0:
            case (byte)GraphicVersion.Version1:
            case (byte)GraphicVersion.Version2:
                graphic.Version = (GraphicVersion)readMinorVersion[1];
                break;

            default:
                throw new InvalidDataException("wrong version");
            }

            int p = br.ReadInt32();             //Properties

            graphic.Properties = new GraphicProperties()
            {
                RawData = (GraphicProperties.Properties)p
            };

            //If either Smoke or Steam is set in the GraphicProperties
            if (graphic.Properties.HasParticles)
            {
                graphic.Properties.ParticleX     = br.ReadInt32();
                graphic.Properties.ParticleY     = br.ReadInt32();
                graphic.Properties.ParticleWidth = br.ReadInt32();
            }

            //If Clock is set in the GraphicProperties
            if (graphic.Properties.RawData.HasFlag(GraphicProperties.Properties.Clock))
            {
                if (graphic.Version == GraphicVersion.Version0)
                {
                    throw new InvalidDataException("Clock is set, but invalid for the version of the graphic");
                }
                br.ReadInt32();                 //skipping unused data (for future use)

                graphic.Properties.ClockProperties = (ClockProperties)br.ReadInt32();
                graphic.Properties.ClockX          = br.ReadInt32();
                graphic.Properties.ClockY          = br.ReadInt32();
                graphic.Properties.ClockZ          = (LayerID)br.ReadInt32();
                graphic.Properties.ClockWidth      = br.ReadInt32();
                graphic.Properties.ClockHeight     = br.ReadInt32();

                graphic.Properties.ClockColorHoursPointer   = br.ReadUInt32();
                graphic.Properties.ClockColorMinutesPointer = br.ReadUInt32();
                br.ReadInt32();                 //skipping unused data (for future use)
            }

            //If Cursor is set in the GraphicProperties
            if (graphic.Properties.RawData.HasFlag(GraphicProperties.Properties.Cursor))
            {
                if (graphic.Version < GraphicVersion.Version2)
                {
                    throw new InvalidDataException("Cursor is set, but invalid for the version of the graphic");
                }
                graphic.Properties.CursorNormalDirection  = (Direction)br.ReadInt32();
                graphic.Properties.CursorReverseDirection = (Direction)br.ReadInt32();
            }

            //If ColorInSchematicMode is set in the GraphicProperties
            if (graphic.Properties.RawData.HasFlag(GraphicProperties.Properties.ColorSchematicMode))
            {
                if (graphic.Version < GraphicVersion.Version2)
                {
                    throw new InvalidDataException("ColorSchematicMode is set, but invalid for the version of the graphic");
                }
                graphic.Properties.ColorInSchematicMode = br.ReadUInt32();
                br.ReadUInt32();                 //skipping unused data
            }

            //If DrivingWay is set in the GraphicProperties
            if (graphic.Properties.RawData.HasFlag(GraphicProperties.Properties.DrivingWay))
            {
                if (graphic.Version < GraphicVersion.Version2)
                {
                    throw new InvalidDataException("DrivingWay is set, but invalid for the version of the graphic");
                }
                graphic.DrivingWay = new List <DrivingWayElement>();
                int count = br.ReadInt32();
                for (int i = 0; i < count; i++)
                {
                    graphic.DrivingWay.Add(DrivingWayElement.FromBytes(br.ReadBytes(12)));
                }
            }

            int layercount = br.ReadInt16();

            br.ReadUInt16();             //skipping unknown data, see more in save-method
            char          c;
            StringBuilder sb = new StringBuilder();

            while ((c = br.ReadChar()) != Constants.UnicodeNull)
            {
                sb.Append(c);
            }
            graphic.InfoText = sb.ToString();

            // Load Data
            bool backgroundLayerExists = false;

            for (int i = 0; i < layercount; i++)
            {
                LayerID         id = (LayerID)br.ReadInt16();
                CompressedLayer compressedLayer = _ReadLayerFromStream(br, graphic.ZoomFactor, graphic.Version);
                if (id == LayerID.Background0)
                {
                    if (!backgroundLayerExists)
                    {
                        backgroundLayerExists = true;
                    }
                    else
                    {
                        id = LayerID.Background1;
                    }
                }
                graphic.layersCompressed.Add(id, compressedLayer);
            }

            return(graphic);
        }