예제 #1
0
 public MaterialInfo(
     BgfBitmap Texture,
     string TextureName,
     string MaterialName,          
     V2 ScrollSpeed)
 {
     this.Texture = Texture;
     this.TextureName = TextureName;
     this.MaterialName = MaterialName;
     this.ScrollSpeed = ScrollSpeed;
 }
예제 #2
0
        protected void Calculate(
            ObjectBase Data,
            BgfBitmap MainFrame,
            bool UseViewerFrame = true,
            bool ApplyYOffset = true,
            byte RootHotspotIndex = 0,
            Real Quality = DEFAULTQUALITY,
            bool ScalePow2 = false,
            uint Width = 0,
            uint Height = 0,
            bool CenterVertical = false,
            bool CenterHorizontal = false)
        {
            BgfBitmap mainFrame = MainFrame;
            BgfFile mainResource = Data.Resource;
            byte mainColor = Data.ColorTranslation;
            BgfBitmap subOvFrame;
            BgfBitmapHotspot subOvHotspot;
            SubOverlay subOvParent;
            BgfBitmap subOvParentFrame;
            BgfBitmapHotspot subOvParentHotspot;
            bool rootSpotFound = false;

            // use custom compose root (suboverlay=mainoverlay)
            // if it's not found, fallback to full compose
            if (RootHotspotIndex > 0)
            {
                SubOverlay subOv = Data.GetSubOverlayByHotspot(RootHotspotIndex);

                if (subOv != null)
                {
                    rootSpotFound = true;

                    if (UseViewerFrame)
                        mainFrame = subOv.ViewerFrame;
                    else
                        mainFrame = subOv.FrontFrame;

                    mainResource = subOv.Resource;
                    mainColor = subOv.ColorTranslation;
                }
            }

            if (mainFrame != null && mainResource != null)
            {
                Bgf = mainFrame;
                BgfColor = mainColor;
                size.X = (Real)mainFrame.Width / (Real)mainResource.ShrinkFactor;
                size.Y = (Real)mainFrame.Height / (Real)mainResource.ShrinkFactor;
                origin.X = (Real)mainFrame.XOffset / (Real)mainResource.ShrinkFactor;
                origin.Y = (Real)mainFrame.YOffset / (Real)mainResource.ShrinkFactor;
                MaxShrink = mainResource.ShrinkFactor;

                // used to calculate the boundingbox
                V2 min = new V2(Origin.X, Origin.Y);
                V2 max = (ApplyYOffset) ? 
                    new V2(Size.X, Size.Y) : 
                    new V2(Origin.X + Size.X, Origin.Y + Size.Y);

                Real x, y;

                // walk suboverlay structure
                foreach (SubOverlay subOv in Data.CurrentSubOverlays)
                {
                    if (UseViewerFrame)
                    {
                        subOvFrame = subOv.ViewerFrame;
                        subOvHotspot = subOv.ViewerHotspot;
                        subOvParent = subOv.ViewerParent;
                    }
                    else
                    {
                        subOvFrame = subOv.FrontFrame;
                        subOvHotspot = subOv.FrontHotspot;
                        subOvParent = subOv.FrontParent;
                    }

                    bool isSubRoot = (subOvParent != null && subOvParent.HotSpot == RootHotspotIndex);

                    if (subOv.Resource != null &&
                        subOvFrame != null &&
                        subOvHotspot != null &&
                        (RootHotspotIndex <= 0 || !rootSpotFound || isSubRoot))
                    {
                        SubOverlay.RenderInfo subOvInfo = new SubOverlay.RenderInfo();
                        
                        // save subov & bitmap
                        subOvInfo.SubOverlay = subOv;
                        subOvInfo.Bgf = subOvFrame;

                        // calculate the size of this suboverlay
                        subOvInfo.Size.X = (Real)subOvFrame.Width / (Real)subOv.Resource.ShrinkFactor;
                        subOvInfo.Size.Y = (Real)subOvFrame.Height / (Real)subOv.Resource.ShrinkFactor;

                        // update maxshrink if greater
                        if (subOv.Resource.ShrinkFactor > MaxShrink)
                            MaxShrink = subOv.Resource.ShrinkFactor;

                        // CASE 1: SubOverlay on mainoverlay
                        if (subOvParent == null || isSubRoot)
                        {
                            // calculate the origin of this suboverlay on the mainoverlay
                            subOvInfo.Origin.X = mainFrame.XOffset
                                + ((Real)subOvHotspot.X)
                                + ((Real)subOvFrame.XOffset);

                            subOvInfo.Origin.Y = mainFrame.YOffset
                                + ((Real)subOvHotspot.Y)
                                + ((Real)subOvFrame.YOffset);

                            subOvInfo.Origin.X /= mainResource.ShrinkFactor;
                            subOvInfo.Origin.Y /= mainResource.ShrinkFactor;

                            // determine type of hotspot
                            if (subOvHotspot.Index < 0)
                                subOvInfo.HotspotType = HotSpotType.HOTSPOT_UNDER;
                            else
                                subOvInfo.HotspotType = HotSpotType.HOTSPOT_OVER;
                        }

                        // CASE 2: SubOverlay on SubOverlay on MainOverlay
                        else
                        {
                            if (UseViewerFrame)
                            {
                                subOvParentFrame = subOvParent.ViewerFrame;
                                subOvParentHotspot = subOvParent.ViewerHotspot;
                            }
                            else
                            {
                                subOvParentFrame = subOvParent.FrontFrame;
                                subOvParentHotspot = subOvParent.FrontHotspot;
                            }

                            if (subOvParentHotspot != null &&
                                subOvParentFrame != null &&
                                subOvParent.Resource != null)
                            {
                                // calculate the origin of this suboverlay on the suboverlay on the mainoverlay
                                subOvInfo.Origin.X = 
                                    (mainFrame.XOffset +
                                    (Real)subOvParentHotspot.X +
                                    (Real)subOvParentFrame.XOffset) / (Real)mainResource.ShrinkFactor;

                                subOvInfo.Origin.X +=
                                    ((Real)subOvHotspot.X +
                                    (Real)subOvFrame.XOffset) / (Real)subOvParent.Resource.ShrinkFactor;

                                subOvInfo.Origin.Y = 
                                    (mainFrame.YOffset +
                                    (Real)subOvParentHotspot.Y +
                                    (Real)subOvParentFrame.YOffset) / (Real)mainResource.ShrinkFactor;

                                subOvInfo.Origin.Y +=
                                    ((Real)subOvHotspot.Y +
                                    (Real)subOvFrame.YOffset) / (Real)subOvParent.Resource.ShrinkFactor;

                                // determine type of nested hotspot
                                if (subOvParentHotspot.Index > 0 && subOvHotspot.Index > 0)
                                    subOvInfo.HotspotType = HotSpotType.HOTSPOT_OVEROVER;

                                else if (subOvParentHotspot.Index > 0 && subOvHotspot.Index < 0)
                                    subOvInfo.HotspotType = HotSpotType.HOTSPOT_OVERUNDER;

                                else if (subOvParentHotspot.Index < 0 && subOvHotspot.Index > 0)
                                    subOvInfo.HotspotType = HotSpotType.HOTSPOT_UNDEROVER;

                                else if (subOvParentHotspot.Index < 0 && subOvHotspot.Index < 0)
                                    subOvInfo.HotspotType = HotSpotType.HOTSPOT_UNDERUNDER;
                            }
                        }

                        // update max boundingbox
                        if (subOvInfo.Origin.X < min.X)
                            min.X = subOvInfo.Origin.X;

                        if (subOvInfo.Origin.Y < min.Y)
                            min.Y = subOvInfo.Origin.Y;

                        x = subOvInfo.Origin.X + subOvInfo.Size.X;
                        y = subOvInfo.Origin.Y + subOvInfo.Size.Y;

                        if (x > max.X)
                            max.X = x;

                        if (y > max.Y)
                            max.Y = y;

                        // save info for this suboverlay
                        SubBgf.Add(subOvInfo);
                    }
                }

                // get dimension from boundingbox
                dimension.X = Math.Abs(max.X - min.X);
                dimension.Y = Math.Abs(max.Y - min.Y);

                // move all origins so minimum hits 0/0
                // preparation for drawing (pixel origin is 0/0)
                Translate(-min);

                // get the center of the dimension box
                // this is also the center of our image after the translate above
                V2 bbCenter = dimension * 0.5f;

                // get the center of the main overlay
                V2 mainOriginCenter = Origin + (Size * 0.5f);

                // move the x center of the main overlay to the x center of dimensionbox
                V2 centerMove = new V2(bbCenter.X - mainOriginCenter.X, 0.0f);
                Translate(centerMove);

                // since this moves a part outside the dimension box
                // we need to add this size of the move to the dimension, 
                // to the right AND left side, so our centering above stays centered
                // then we remove to the center.
                V2 center = new V2(Math.Abs(centerMove.X), 0.0f);
                dimension.X += center.X * 2.0f;
                Translate(center);

                // scale so highest resolution resource has 1:1 ratio (no downscale)
                // and apply custom quality level
                Scale((Real)MaxShrink);

                // scale up to pow2 if set
                if (ScalePow2)
                {
                    Real maxQuality = Quality * QUALITYBASE;
                    Real ratioX = maxQuality / dimension.X;
                    Real ratioY = maxQuality / dimension.Y;

                    if (ratioX <= ratioY && ratioX < 1.0f)
                        Scale(ratioX);
                    else if (ratioX > ratioY && ratioY < 1.0f)
                        Scale(ratioY);

                    // get next power of 2 size
                    V2 pow2Size = new V2(
                        MathUtil.NextPowerOf2((uint)dimension.X),
                        MathUtil.NextPowerOf2((uint)dimension.Y));

                    // scale so we use at least all pixels either from upscaled width or height
                    ScaleToBox(pow2Size, CenterHorizontal, CenterVertical);
                }
                else if (Width > 0 && Height > 0)
                {
                    // use user given size
                    V2 userSize = new V2(Width, Height);

                    // scale so we use at least all pixels either from upscaled width or height
                    ScaleToBox(userSize, CenterHorizontal, CenterVertical);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Loads this BgfFile instance from XML/BMP
        /// </summary>
        /// <param name="Filename"></param>
        public void LoadXml(string Filename)
        {
            string path = Path.GetDirectoryName(Filename);

            // save raw filename without path or extensions
            Filename = Path.GetFileNameWithoutExtension(Filename);

            // init XML reader
            XmlReader reader = XmlReader.Create(Filename);

            // rootnode
            reader.ReadToFollowing("bgf");
            uint version = Convert.ToUInt32(reader["version"]);
            if (version >= BgfFile.VERSION9)
            {
                ShrinkFactor = Convert.ToUInt32(reader["shrink"]);

                // skip maxindices, we use dynamic getter
                // MaxIndices = Convert.ToUInt32(reader["maxindices"]);

                // frames
                reader.ReadToFollowing("frames");
                int FrameCount = Convert.ToInt32(reader["count"]);
                Frames.Capacity = FrameCount;
                for (int i = 0; i < FrameCount; i++)
                {
                    reader.ReadToFollowing("frame");
                    uint width = Convert.ToUInt32(reader["width"]);
                    uint height = Convert.ToUInt32(reader["height"]);
                    int xoffset = Convert.ToInt32(reader["xoffset"]);
                    int yoffset = Convert.ToInt32(reader["yoffset"]);
                    string file = reader["file"];

                    // hotspots
                    reader.ReadToFollowing("hotspots");
                    byte hotspotcount = Convert.ToByte(reader["count"]);
                    List<BgfBitmapHotspot> hotspots = new List<BgfBitmapHotspot>(hotspotcount);
                    for (int j = 0; j < hotspotcount; j++)
                    {
                        reader.ReadToFollowing("hotspot");
                        sbyte index = Convert.ToSByte(reader["index"]);
                        int x = Convert.ToInt32(reader["x"]);
                        int y = Convert.ToInt32(reader["y"]);

                        BgfBitmapHotspot hotspot = new BgfBitmapHotspot(index, x, y);
                        hotspots.Add(hotspot);
                    }

                    // load bitmap from file
                    Bitmap bmp = (Bitmap)Image.FromFile(path + "/" + file);

                    byte[] pixelData = BgfBitmap.BitmapToPixelData(bmp);
                    BgfBitmap bgfBitmap = new BgfBitmap(
                        (uint)i + 1,
                        version,
                        width,
                        height,
                        xoffset,
                        yoffset,
                        hotspots,
                        false,
                        0,
                        pixelData);

                    // cleanp temporary bitmap
                    bmp.Dispose();

                    Frames.Add(bgfBitmap);
                }

                // framesets
                reader.ReadToFollowing("framesets");
                int FrameSetCount = Convert.ToInt32(reader["count"]);
                FrameSets.Capacity = FrameSetCount;
                for (int i = 0; i < FrameSetCount; i++)
                {
                    reader.ReadToFollowing("frameset");
                    string[] indices = reader["indices"].Split(' ');
                    List<int> intIndices = new List<int>();
                    foreach (string index in indices)
                        intIndices.Add(Convert.ToInt32(index));

                    BgfFrameSet bgfFrameSet = new BgfFrameSet((uint)i + 1, intIndices);

                    FrameSets.Add(bgfFrameSet);
                }
            }
            else
                throw new Exception("Wrong format version: " + version + " (expected " + BgfFile.VERSION9 + ").");
        }
예제 #4
0
        public int ReadFrom(byte[] Buffer, int StartIndex = 0)
        {
            int cursor = StartIndex;

            uint signature = BitConverter.ToUInt32(Buffer, cursor);
            cursor += TypeSizes.INT;

            if (signature == SIGNATURE)
            {
                Version = BitConverter.ToUInt32(Buffer, cursor);
                cursor += TypeSizes.INT;

                // version has to be V9 or higher
                if (version >= VERSION9)
                {
                    // name string has always fixed length
                    Name = Encoding.Default.GetString(Buffer, cursor, NAMELENGTH);
                    cursor += NAMELENGTH;

                    uint frameCount = BitConverter.ToUInt32(Buffer, cursor);
                    cursor += TypeSizes.INT;

                    uint frameSetCount = BitConverter.ToUInt32(Buffer, cursor);
                    cursor += TypeSizes.INT;

                    // skip max indices, we use dynamic getter
                    cursor += TypeSizes.INT;

                    ShrinkFactor = BitConverter.ToUInt32(Buffer, cursor);
                    cursor += TypeSizes.INT;

                    Frames.Clear();
                    Frames.Capacity = (int)frameCount;
                    for (uint i = 0; i < frameCount; i++)
                    {
                        BgfBitmap bgfBitmap = new BgfBitmap(i + 1, version, Buffer, cursor);
                        cursor += bgfBitmap.ByteLength;

                        Frames.Add(bgfBitmap);
                    }

                    FrameSets.Clear();
                    FrameSets.Capacity = (int)frameSetCount;
                    for (uint i = 0; i < frameSetCount; i++)
                    {
                        BgfFrameSet frameSet = new BgfFrameSet(i + 1, Buffer, cursor);
                        cursor += frameSet.ByteLength;

                        FrameSets.Add(frameSet);
                    }
                }
                else
                    throw new Exception("Wrong file version: " + version + " (expected " + VERSION9 + " or higher).");
            }
            else
                throw new Exception("Wrong file signature: " + signature + " (expected " + SIGNATURE + ").");

            return cursor - StartIndex;
        }
예제 #5
0
        protected void OnFileDialogAddFrameFileOk(object sender, CancelEventArgs e)
        {
            // load bitmap from file
            Bitmap bitmap = new Bitmap(fdAddFrame.FileName);

            // get pixels
            byte[] pixelData = BgfBitmap.BitmapToPixelData(bitmap);

            // create BgfBitmap
            BgfBitmap bgfBitmap = new BgfBitmap(
                (uint)Program.CurrentFile.Frames.Count + 1,
                Program.CurrentFile.Version,
                (uint)bitmap.Width,
                (uint)bitmap.Height,
                0,
                0,
                new BgfBitmapHotspot[0],
                false,
                0,
                pixelData);

            // cleanp temporary bitmap
            bitmap.Dispose();
                          
            // add to frames
            Program.CurrentFile.Frames.Add(bgfBitmap);
        }
예제 #6
0
        /// <summary>
        /// Loads this BgfFile instance from XML/BMP
        /// </summary>
        /// <param name="Filename"></param>
        public void LoadXml(string Filename)
        {
            string path = Path.GetDirectoryName(Filename);

            // save raw filename without path or extensions
            Filename = Path.GetFileNameWithoutExtension(Filename);

            // init XML reader
            XmlReader reader = XmlReader.Create(Filename);

            // rootnode
            reader.ReadToFollowing("bgf");
            uint version = Convert.ToUInt32(reader["version"]);

            if (version >= BgfFile.VERSION9)
            {
                ShrinkFactor = Convert.ToUInt32(reader["shrink"]);

                // skip maxindices, we use dynamic getter
                // MaxIndices = Convert.ToUInt32(reader["maxindices"]);

                // frames
                reader.ReadToFollowing("frames");
                int FrameCount = Convert.ToInt32(reader["count"]);
                Frames.Capacity = FrameCount;
                for (int i = 0; i < FrameCount; i++)
                {
                    reader.ReadToFollowing("frame");
                    uint   width   = Convert.ToUInt32(reader["width"]);
                    uint   height  = Convert.ToUInt32(reader["height"]);
                    int    xoffset = Convert.ToInt32(reader["xoffset"]);
                    int    yoffset = Convert.ToInt32(reader["yoffset"]);
                    string file    = reader["file"];

                    // hotspots
                    reader.ReadToFollowing("hotspots");
                    byte hotspotcount = Convert.ToByte(reader["count"]);
                    List <BgfBitmapHotspot> hotspots = new List <BgfBitmapHotspot>(hotspotcount);
                    for (int j = 0; j < hotspotcount; j++)
                    {
                        reader.ReadToFollowing("hotspot");
                        sbyte index = Convert.ToSByte(reader["index"]);
                        int   x     = Convert.ToInt32(reader["x"]);
                        int   y     = Convert.ToInt32(reader["y"]);

                        BgfBitmapHotspot hotspot = new BgfBitmapHotspot(index, x, y);
                        hotspots.Add(hotspot);
                    }

                    // load bitmap from file
                    Bitmap bmp = (Bitmap)Image.FromFile(path + "/" + file);

                    byte[]    pixelData = BgfBitmap.BitmapToPixelData(bmp);
                    BgfBitmap bgfBitmap = new BgfBitmap(
                        (uint)i + 1,
                        version,
                        width,
                        height,
                        xoffset,
                        yoffset,
                        hotspots,
                        false,
                        0,
                        pixelData);

                    // cleanp temporary bitmap
                    bmp.Dispose();

                    Frames.Add(bgfBitmap);
                }

                // framesets
                reader.ReadToFollowing("framesets");
                int FrameSetCount = Convert.ToInt32(reader["count"]);
                FrameSets.Capacity = FrameSetCount;
                for (int i = 0; i < FrameSetCount; i++)
                {
                    reader.ReadToFollowing("frameset");
                    string[]   indices    = reader["indices"].Split(' ');
                    List <int> intIndices = new List <int>();
                    foreach (string index in indices)
                    {
                        intIndices.Add(Convert.ToInt32(index));
                    }

                    BgfFrameSet bgfFrameSet = new BgfFrameSet((uint)i + 1, intIndices);

                    FrameSets.Add(bgfFrameSet);
                }
            }
            else
            {
                throw new Exception("Wrong format version: " + version + " (expected " + BgfFile.VERSION9 + ").");
            }
        }
예제 #7
0
        public int ReadFrom(byte[] Buffer, int StartIndex = 0)
        {
            int cursor = StartIndex;

            uint signature = BitConverter.ToUInt32(Buffer, cursor);

            cursor += TypeSizes.INT;

            if (signature == SIGNATURE)
            {
                Version = BitConverter.ToUInt32(Buffer, cursor);
                cursor += TypeSizes.INT;

                // version has to be V9 or higher
                if (version >= VERSION9)
                {
                    // name string has always fixed length
                    Name    = Encoding.Default.GetString(Buffer, cursor, NAMELENGTH);
                    cursor += NAMELENGTH;

                    uint frameCount = BitConverter.ToUInt32(Buffer, cursor);
                    cursor += TypeSizes.INT;

                    uint frameSetCount = BitConverter.ToUInt32(Buffer, cursor);
                    cursor += TypeSizes.INT;

                    // skip max indices, we use dynamic getter
                    cursor += TypeSizes.INT;

                    ShrinkFactor = BitConverter.ToUInt32(Buffer, cursor);
                    cursor      += TypeSizes.INT;

                    Frames.Clear();
                    Frames.Capacity = (int)frameCount;
                    for (uint i = 0; i < frameCount; i++)
                    {
                        BgfBitmap bgfBitmap = new BgfBitmap(i + 1, version, Buffer, cursor);
                        cursor += bgfBitmap.ByteLength;

                        Frames.Add(bgfBitmap);
                    }

                    FrameSets.Clear();
                    FrameSets.Capacity = (int)frameSetCount;
                    for (uint i = 0; i < frameSetCount; i++)
                    {
                        BgfFrameSet frameSet = new BgfFrameSet(i + 1, Buffer, cursor);
                        cursor += frameSet.ByteLength;

                        FrameSets.Add(frameSet);
                    }
                }
                else
                {
                    throw new Exception("Wrong file version: " + version + " (expected " + VERSION9 + " or higher).");
                }
            }
            else
            {
                throw new Exception("Wrong file signature: " + signature + " (expected " + SIGNATURE + ").");
            }

            return(cursor - StartIndex);
        }
 public RenderInfo()
 {
     Origin = new V2(0.0f, 0.0f);
     Size = new V2(0.0f, 0.0f);
     Bgf = null;
     HotspotType = HotSpotType.HOTSPOT_NONE;
     SubOverlay = null;
 }
예제 #9
0
        /// <summary>
        /// Import a storyboard given a full path to the storyboard bmp. The XML file for
        /// the storyboard must have a matching filename with the XML extension, and be in
        /// the same directory.
        /// </summary>
        /// <param name="Filename"></param>
        /// <returns></returns>
        public bool ImportStoryboard(string Filename)
        {
            string path = Path.GetDirectoryName(Filename);
            // raw filename without path or extensions
            string xmlFilename = Path.GetFileNameWithoutExtension(Filename);

            // index for reading bmp data, incremented as we split the giant bmp
            uint readoffset = 0;

            // open bmp into one giant bitmap
            Bitmap bmp         = (Bitmap)Image.FromFile(Filename);
            uint   totalWidth  = (uint)bmp.Width;
            uint   totalHeight = (uint)bmp.Height;

            byte[] pixelData = BgfBitmap.BitmapToPixelData(bmp);

            // cleanp temporary bitmap
            bmp.Dispose();

            // init XML reader
            XmlReader reader = XmlReader.Create(Path.Combine(path, xmlFilename) + FileExtensions.XML);

            // read in xml file
            // rootnode
            reader.ReadToFollowing("bgf");
            uint version = Convert.ToUInt32(reader["version"]);

            if (version >= BgfFile.VERSION9)
            {
                ShrinkFactor = Convert.ToUInt32(reader["shrink"]);

                // skip maxindices, we use dynamic getter
                // MaxIndices = Convert.ToUInt32(reader["maxindices"]);

                // frames
                reader.ReadToFollowing("frames");
                int  FrameCount       = Convert.ToInt32(reader["count"]);
                uint savedTotalHeight = Convert.ToUInt32(reader["totalheight"]);
                uint savedTotalWidth  = Convert.ToUInt32(reader["totalwidth"]);
                // Saved dimensions must match those loaded for the storyboard bmp.
                if (savedTotalWidth != totalWidth || savedTotalHeight != totalHeight)
                {
                    return(false);
                }

                Frames.Capacity = FrameCount;
                for (int i = 0; i < FrameCount; i++)
                {
                    reader.ReadToFollowing("frame");
                    uint width   = Convert.ToUInt32(reader["width"]);
                    uint height  = Convert.ToUInt32(reader["height"]);
                    int  xoffset = Convert.ToInt32(reader["xoffset"]);
                    int  yoffset = Convert.ToInt32(reader["yoffset"]);

                    // hotspots
                    reader.ReadToFollowing("hotspots");
                    byte hotspotcount = Convert.ToByte(reader["count"]);
                    List <BgfBitmapHotspot> hotspots = new List <BgfBitmapHotspot>(hotspotcount);
                    for (int j = 0; j < hotspotcount; j++)
                    {
                        reader.ReadToFollowing("hotspot");
                        sbyte index = Convert.ToSByte(reader["index"]);
                        int   x     = Convert.ToInt32(reader["x"]);
                        int   y     = Convert.ToInt32(reader["y"]);

                        BgfBitmapHotspot hotspot = new BgfBitmapHotspot(index, x, y);
                        hotspots.Add(hotspot);
                    }

                    // get pixels for this frame from the single bmp
                    byte[] pixels      = new byte[height * width];
                    uint   writeoffset = 0;
                    for (int j = 0; j < height; ++j)
                    {
                        Wrapper.CopyMem(pixelData, (int)readoffset, pixels, (int)writeoffset, width);
                        readoffset  += totalWidth;
                        writeoffset += width;
                    }

                    BgfBitmap bgfBitmap = new BgfBitmap(
                        (uint)i + 1,
                        version,
                        width,
                        height,
                        xoffset,
                        yoffset,
                        hotspots,
                        false,
                        0,
                        pixels);

                    Frames.Add(bgfBitmap);
                }

                // framesets
                reader.ReadToFollowing("framesets");
                int FrameSetCount = Convert.ToInt32(reader["count"]);
                FrameSets.Capacity = FrameSetCount;
                for (int i = 0; i < FrameSetCount; i++)
                {
                    reader.ReadToFollowing("frameset");
                    string[]   indices    = reader["indices"].Split(' ');
                    List <int> intIndices = new List <int>();
                    foreach (string index in indices)
                    {
                        intIndices.Add(Convert.ToInt32(index));
                    }

                    BgfFrameSet bgfFrameSet = new BgfFrameSet((uint)i + 1, intIndices);

                    FrameSets.Add(bgfFrameSet);
                }
            }
            else
            {
                throw new Exception("Wrong format version: " + version + " (expected " + BgfFile.VERSION9 + ").");
            }

            return(true);
        }