示例#1
0
        protected void OnFrameRemoveClick(object sender, EventArgs e)
        {
            BgfBitmap bgfBitmap = SelectedFrame;

            if (bgfBitmap != null)
            {
                uint oldnum = bgfBitmap.Num;
                int  index  = dgFrames.Rows.IndexOf(dgFrames.SelectedRows[0]);

                if (index > -1)
                {
                    DialogResult = MessageBox.Show(STR_AREYOUSURE, STR_REMOVEFRAME, MessageBoxButtons.YesNo);
                    if (DialogResult == DialogResult.Yes)
                    {
                        if (Program.CurrentFile.IsFrameIndexLinkedInFrameSet(index))
                        {
                            MessageBox.Show(STR_ERRORSTILLINKED, "Error", MessageBoxButtons.OK);
                        }
                        else
                        {
                            Program.CurrentFile.Frames.Remove(bgfBitmap);

                            // adjust nums for rest
                            for (int i = (int)oldnum - 1; i < Program.CurrentFile.Frames.Count; i++)
                            {
                                Program.CurrentFile.Frames[i].Num--;
                            }
                        }
                    }
                }
            }
        }
示例#2
0
        protected void OnFrameDownClick(object sender, EventArgs e)
        {
            BgfBitmap bgfBitmap = SelectedFrame;

            if (bgfBitmap != null)
            {
                int index = dgFrames.Rows.IndexOf(dgFrames.SelectedRows[0]);

                if (index < dgFrames.Rows.Count - 1)
                {
                    // swap listitems
                    BgfBitmap temp = Program.CurrentFile.Frames[index + 1];
                    Program.CurrentFile.Frames[index + 1] = bgfBitmap;
                    Program.CurrentFile.Frames[index]     = temp;

                    // update selection
                    dgFrames.Rows[index + 1].Selected = true;

                    Program.CurrentFile.UpdateFrameIndexInFrameSets(index + 1, -1);
                    Program.CurrentFile.UpdateFrameIndexInFrameSets(index, index + 1);
                    Program.CurrentFile.UpdateFrameIndexInFrameSets(-1, index);

                    // adjust nums
                    Program.CurrentFile.Frames[index + 1].Num++;
                    Program.CurrentFile.Frames[index].Num--;

                    UpdateFrameNums();
                }
            }
        }
        /// <summary>
        /// Creates RenderInfo for a RoomObject
        /// </summary>
        /// <param name="Data"></param>
        /// <param name="UseViewerFrame"></param>
        /// <param name="ApplyYOffset"></param>
        /// <param name="RootHotspotIndex"></param>
        /// <param name="Quality"></param>
        /// <param name="ScalePow2"></param>
        /// <param name="Width"></param>
        /// <param name="Height"></param>
        /// <param name="CenterVertical"></param>
        /// <param name="CenterHorizontal"></param>
        /// <param name="IsCustomShrink"></param>
        /// <param name="CustomShrink"></param>
        public void Refresh(
            RoomObject Data,
            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,
            bool IsCustomShrink   = false,
            Real CustomShrink     = 1.0f)
        {
            Clear();

            BgfBitmap mainFrame = Data.ViewerFrame;

            if (!UseViewerFrame)
            {
                mainFrame = Data.FrontFrame;
            }

            Calculate(Data, mainFrame, UseViewerFrame, ApplyYOffset, RootHotspotIndex, Quality, ScalePow2, Width, Height, CenterVertical, CenterHorizontal, IsCustomShrink, CustomShrink);
        }
示例#4
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);
        }
示例#5
0
        protected void OnHotspotDownClick(object sender, EventArgs e)
        {
            BgfBitmapHotspot bgfHotspot = SelectedHotspot;

            if (bgfHotspot != null)
            {
                int index = dgHotspots.Rows.IndexOf(dgHotspots.SelectedRows[0]);

                if (index < dgHotspots.Rows.Count - 1)
                {
                    BgfBitmap bgfBitmap = SelectedFrame;

                    // swap listitems
                    if (bgfBitmap != null)
                    {
                        BgfBitmapHotspot temp = bgfBitmap.HotSpots[index + 1];
                        bgfBitmap.HotSpots[index + 1] = bgfHotspot;
                        bgfBitmap.HotSpots[index]     = temp;

                        // update selection
                        dgHotspots.Rows[index + 1].Selected = true;
                    }
                }
            }
        }
示例#6
0
 public RenderInfo()
 {
     Origin      = new V2(0.0f, 0.0f);
     Size        = new V2(0.0f, 0.0f);
     Bgf         = null;
     HotspotType = HotSpotType.HOTSPOT_NONE;
     SubOverlay  = null;
 }
示例#7
0
        protected void OnHotspotAddClick(object sender, EventArgs e)
        {
            BgfBitmap bgfBitmap = SelectedFrame;

            if (bgfBitmap != null)
            {
                bgfBitmap.HotSpots.Add(new BgfBitmapHotspot());
            }
        }
示例#8
0
        protected void OnResizeEnd(object sender, EventArgs e)
        {
            BgfBitmap bgfBitmap = SelectedFrame;

            if (bgfBitmap != null)
            {
                Program.ShowFrame(true, bgfBitmap.GetBitmap(), picFrameImage);
            }
        }
        protected void OnFramesSelectedIndexChanged(object sender, EventArgs e)
        {
            if (cbFrames.SelectedItem != null && cbFrames.SelectedItem is BgfBitmap)
            {
                BgfBitmap bgfBitmap = (BgfBitmap)cbFrames.SelectedItem;

                Program.ShowFrame(true, bgfBitmap.GetBitmap(), picBox);
            }
        }
示例#10
0
        protected void OnHotspotAddClick(object sender, EventArgs e)
        {
            BgfBitmap bgfBitmap = SelectedFrame;

            if (bgfBitmap != null)
            {
                Program.HasFileChanged = true;
                bgfBitmap.HotSpots.Add(new BgfBitmapHotspot());
            }
        }
示例#11
0
        protected void OnFramesSelectionChanged(object sender, EventArgs e)
        {
            BgfBitmap bgfBitmap = SelectedFrame;

            if (bgfBitmap != null)
            {
                // set hotspotlist
                dgHotspots.DataSource = bgfBitmap.HotSpots;

                // show frame
                Program.ShowFrame(true, bgfBitmap.GetBitmap(), picFrameImage);
            }
        }
示例#12
0
        /// <summary>
        /// Swaps in a new image for a given frame, keeping offets, hotspots and group data.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void OnFileDialogChangeFrameFileOk(object sender, CancelEventArgs e)
        {
            // Must have a valid frame selected.
            if (SelectedFrame == null)
            {
                return;
            }
            int selected_index = (int)SelectedFrame.Num - 1;

            if (selected_index < 0)
            {
                return;
            }

            BgfBitmap item = Program.CurrentFile.Frames[selected_index];

            // load bitmap from file
            Bitmap bitmap = new Bitmap(fdChangeFrame.FileName);

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

            // create BgfBitmap
            BgfBitmap bgfBitmap = new BgfBitmap(
                item.Num,
                Program.CurrentFile.Version,
                (uint)bitmap.Width,
                (uint)bitmap.Height,
                item.XOffset,
                item.YOffset,
                new BgfBitmapHotspot[0],
                false,
                0,
                pixelData);

            // cleanp temporary bitmap
            bitmap.Dispose();

            foreach (BgfBitmapHotspot h in item.HotSpots)
            {
                bgfBitmap.HotSpots.Add(h);
            }
            Program.HasFileChanged = true;

            Program.CurrentFile.Frames.RemoveAt(selected_index);
            Program.CurrentFile.Frames.Insert(selected_index, bgfBitmap);
            dgFrames.Rows[selected_index].Selected = true;
            UpdateFrameSetFlow();
        }
        /// <summary>
        /// Internal thread loop
        /// </summary>
        protected void ThreadProc()
        {
            uint   version = Program.CurrentFile.Version;
            Bitmap bitmap;

            while (IsRunning)
            {
                while (Program.BitmapFileQueue.TryDequeue(out string file))
                {
                    // load bitmap from file
                    bitmap = new Bitmap(file);

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

                    // create BgfBitmap
                    BgfBitmap bgfBitmap = new BgfBitmap(
                        0, // num determined when adding to list after dequeue
                        version,
                        (uint)bitmap.Width,
                        (uint)bitmap.Height,
                        0,
                        0,
                        new BgfBitmapHotspot[0],
                        false,
                        0,
                        pixelData);

                    // cleanp temporary bitmap
                    bitmap.Dispose();

                    // enqueue for adding to frames
                    Program.BgfBitmapQueue.Enqueue(bgfBitmap);
                }

                // Done
                IsRunning = false;
            }
        }
示例#14
0
        protected void OnHotspotUpClick(object sender, EventArgs e)
        {
            BgfBitmapHotspot bgfHotspot = SelectedHotspot;

            if (bgfHotspot != null)
            {
                int index = dgHotspots.Rows.IndexOf(dgHotspots.SelectedRows[0]);

                if (index > 0)
                {
                    Program.HasFileChanged = true;
                    BgfBitmap bgfBitmap = SelectedFrame;

                    // swap listitems
                    BgfBitmapHotspot temp = bgfBitmap.HotSpots[index - 1];
                    bgfBitmap.HotSpots[index - 1] = bgfHotspot;
                    bgfBitmap.HotSpots[index]     = temp;

                    // update selection
                    dgHotspots.Rows[index - 1].Selected = true;
                }
            }
        }
示例#15
0
        /// <summary>
        /// Handles the HTTP request
        /// </summary>
        /// <param name="context"></param>
        public void ProcessRequest(HttpContext context)
        {
            HttpResponse response = context.Response;
            // --------------------------------------------------------------------------------------------
            // 1) PARSE URL PARAMETERS
            // --------------------------------------------------------------------------------------------

            // read parameters from url-path (see Global.asax):
            RouteValueDictionary parms = context.Request.RequestContext.RouteData.Values;
            string parmFile            = parms.ContainsKey("file") ? (string)parms["file"] : null;
            string parmReq             = parms.ContainsKey("req") ? (string)parms["req"] : null;
            string parm1 = parms.ContainsKey("parm1") ? (string)parms["parm1"] : null;
            string parm2 = parms.ContainsKey("parm2") ? (string)parms["parm2"] : null;
            string parm3 = parms.ContainsKey("parm3") ? (string)parms["parm3"] : null;

            BgfCache.Entry entry;

            // no filename or request type
            if (String.IsNullOrEmpty(parmFile) || !BgfCache.GetBGF(parmFile, out entry) ||
                String.IsNullOrEmpty(parmReq))
            {
                context.Response.StatusCode = 404;
                return;
            }

            // set cache behaviour
            context.Response.Cache.SetCacheability(HttpCacheability.Public);
            context.Response.Cache.VaryByParams["*"] = false;
            context.Response.Cache.SetLastModified(entry.LastModified);

            // --------------------------------------------------------------------------------------------
            // FRAME IMAGE
            // --------------------------------------------------------------------------------------------
            if (parmReq == "frame")
            {
                ushort index;
                byte   palette = 0;
                Byte.TryParse(parm3, out palette);

                // try to parse index and palette and validate range
                if (!UInt16.TryParse(parm2, out index) || index >= entry.Bgf.Frames.Count)
                {
                    context.Response.StatusCode = 404;
                    return;
                }

                // create BMP (256 col) or PNG (32-bit) or return raw pixels (8bit indices)
                if (parm1 == "bmp")
                {
                    response.ContentType = "image/bmp";
                    response.AddHeader(
                        "Content-Disposition",
                        "inline; filename=" + entry.Bgf.Filename + "-" + index.ToString() + ".bmp");

                    Bitmap bmp = entry.Bgf.Frames[index].GetBitmap(palette);
                    bmp.Save(context.Response.OutputStream, ImageFormat.Bmp);
                    bmp.Dispose();
                }
                else if (parm1 == "png")
                {
                    response.ContentType = "image/png";
                    response.AddHeader(
                        "Content-Disposition",
                        "inline; filename=" + entry.Bgf.Filename + "-" + index.ToString() + ".png");

                    Bitmap bmp = entry.Bgf.Frames[index].GetBitmapA8R8G8B8(palette);
                    bmp.Save(context.Response.OutputStream, ImageFormat.Png);
                    bmp.Dispose();
                }
                else if (parm1 == "bin")
                {
                    response.ContentType = "application/octet-stream";
                    response.AddHeader(
                        "Content-Disposition",
                        "attachment; filename=" + entry.Bgf.Filename + "-" + index.ToString() + ".bin");

                    byte[] pixels = entry.Bgf.Frames[index].PixelData;
                    context.Response.OutputStream.Write(pixels, 0, pixels.Length);
                }
                else
                {
                    context.Response.StatusCode = 404;
                }
            }

            // --------------------------------------------------------------------------------------------
            // JSON META DATA
            // --------------------------------------------------------------------------------------------
            else if (parmReq == "meta")
            {
                // set response type
                response.ContentType     = "application/json";
                response.ContentEncoding = new System.Text.UTF8Encoding(false);
                response.AddHeader("Content-Disposition", "inline; filename=" + entry.Bgf.Filename + ".json");

                // unix timestamp
                long stamp = (entry.LastModified.Ticks - 621355968000000000) / 10000000;

                /////////////////////////////////////////////////////////////
                response.Write("{\"file\":\"");
                response.Write(entry.Bgf.Filename);
                response.Write("\",\"size\":");
                response.Write(entry.Size.ToString());
                response.Write(",\"modified\":");
                response.Write(stamp.ToString());
                response.Write(",\"shrink\":");
                response.Write(entry.Bgf.ShrinkFactor.ToString());
                response.Write(",\"frames\":[");
                for (int i = 0; i < entry.Bgf.Frames.Count; i++)
                {
                    BgfBitmap frame = entry.Bgf.Frames[i];

                    if (i > 0)
                    {
                        response.Write(',');
                    }

                    response.Write("{\"w\":");
                    response.Write(frame.Width.ToString());
                    response.Write(",\"h\":");
                    response.Write(frame.Height.ToString());
                    response.Write(",\"x\":");
                    response.Write(frame.XOffset.ToString());
                    response.Write(",\"y\":");
                    response.Write(frame.YOffset.ToString());
                    response.Write(",\"hs\":[");
                    for (int j = 0; j < frame.HotSpots.Count; j++)
                    {
                        BgfBitmapHotspot hs = frame.HotSpots[j];

                        if (j > 0)
                        {
                            response.Write(',');
                        }

                        response.Write("{\"i\":");
                        response.Write(hs.Index.ToString());
                        response.Write(",\"x\":");
                        response.Write(hs.X.ToString());
                        response.Write(",\"y\":");
                        response.Write(hs.Y.ToString());
                        response.Write('}');
                    }
                    response.Write("]}");
                }
                response.Write("],\"groups\":[");
                for (int i = 0; i < entry.Bgf.FrameSets.Count; i++)
                {
                    BgfFrameSet group = entry.Bgf.FrameSets[i];

                    if (i > 0)
                    {
                        response.Write(',');
                    }

                    response.Write('[');
                    for (int j = 0; j < group.FrameIndices.Count; j++)
                    {
                        if (j > 0)
                        {
                            response.Write(',');
                        }

                        response.Write(group.FrameIndices[j].ToString());
                    }
                    response.Write(']');
                }
                response.Write("]}");
            }

            // --------------------------------------------------------------------------------------------
            // INVALID
            // --------------------------------------------------------------------------------------------
            else
            {
                context.Response.StatusCode = 404;
                return;
            }
        }
示例#16
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,
            bool IsCustomShrink   = false,
            Real CustomShrink     = 1.0f)
        {
            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 = new V2(Size.X, Size.Y);
                if (ApplyYOffset)
                {
                    if (origin.X > 0.0f)
                    {
                        max.X += origin.X;
                    }
                    if (origin.Y > 0.0f)
                    {
                        max.Y += origin.Y;
                    }
                }
                else
                {
                    max += origin;
                }

                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)
                // or to user provided shrink value
                Scale(IsCustomShrink ? CustomShrink : (Real)MaxShrink);

                // user defined sizes
                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, !IsCustomShrink);
                }
                else
                {
                    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);
                    }

                    // scale up to pow2 if set
                    if (ScalePow2)
                    {
                        // get next power of 2 size
                        V2 pow2Size = new V2(
                            MathUtil.NextPowerOf2((uint)System.Math.Ceiling(dimension.X)),
                            MathUtil.NextPowerOf2((uint)System.Math.Ceiling(dimension.Y)));

                        // scale so we use at least all pixels either from upscaled width or height
                        ScaleToBox(pow2Size, CenterHorizontal, CenterVertical, !IsCustomShrink);
                    }
                }

                // calculate the world-size (shrink=1) of the composed object from dimension, uv-coordinates and scaling
                worldsize.X = (uvend.X * dimension.X) / Scaling;
                worldsize.Y = (uvend.Y * dimension.Y) / Scaling;
            }
        }
        public void Collect(string PathBgf, string PathPng)
        {
            items.Clear();

            string[] bgfs = Directory.GetFiles(PathBgf, "*.bgf");

            foreach (string sbgf in bgfs)
            {
                BgfFile bgfFile = new BgfFile(sbgf);

                for (int i = 0; i < bgfFile.Frames.Count; i++)
                {
                    BgfBitmap frame = bgfFile.Frames[i];

                    // create new item
                    Item item = new Item();

                    // build file-frame name
                    item.Frame  = bgfFile.Filename + "-" + i.ToString();
                    item.Shrink = bgfFile.ShrinkFactor;

                    // set values from bgf frame
                    item.Bgf       = frame;
                    item.BgfWidth  = frame.Width;
                    item.BgfHeight = frame.Height;
                    item.BgfRatio  = (float)frame.Width / (float)frame.Height;

                    // build png path
                    string pngname = PathPng + "/" + bgfFile.Filename + "-" + i.ToString() + FileExtensions.PNG;

                    if (File.Exists(pngname))
                    {
                        item.Png       = new Bitmap(pngname);
                        item.PngWidth  = item.Png.Width;
                        item.PngHeight = item.Png.Height;
                        item.PngRatio  = (float)item.Png.Width / (float)item.Png.Height;

                        // scale between bgf and png
                        item.Scale = (float)item.Png.Width / (float)frame.Width;

                        // compare ratio
                        if (item.PngRatio != item.BgfRatio)
                        {
                            item.State = "ERROR";
                        }
                        else
                        {
                            item.State = "OK";
                        }
                    }
                    else
                    {
                        item.State = "MISS";
                    }

                    // add new item
                    items.Add(item);
                }
            }

            gridTextures.DataSource = items;
        }