/// <summary>
        /// Handles the HTTP request
        /// </summary>
        /// <param name="context"></param>
        public void ProcessRequest(HttpContext context)
        {
            HttpResponse response = context.Response;

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

            // set response type
            response.ContentType     = "application/json";
            response.ContentEncoding = new UTF8Encoding(false);
            response.AddHeader("Content-Disposition", "inline; filename=list.json");

            // get enumerator on all bgf in cache
            IEnumerator <KeyValuePair <string, BgfCache.Entry> > enumerator =
                BgfCache.GetEnumerator();

            // start output
            bool isComma = false;

            response.Write('[');
            while (enumerator.MoveNext())
            {
                BgfCache.Entry entry = enumerator.Current.Value;

                // write comma for previous entry
                if (isComma)
                {
                    response.Write(',');
                }
                else
                {
                    isComma = true;
                }

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

                // write json object
                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\":");
                response.Write(entry.Bgf.Frames.Count.ToString());
                response.Write(",\"groups\":");
                response.Write(entry.Bgf.FrameSets.Count.ToString());
                response.Write('}');
            }
            response.Write(']');
        }
Beispiel #2
0
        public void ProcessRequest(HttpContext context)
        {
            // --------------------------------------------------------------------------------------------
            // 1) PARSE URL PARAMETERS
            // --------------------------------------------------------------------------------------------

            // See Global.asax:
            //  object/{scale}/{file}/{group}/{palette}/{angle}
            RouteValueDictionary parms = context.Request.RequestContext.RouteData.Values;
            string parmScale           = parms.ContainsKey("scale")   ? (string)parms["scale"]   : null;
            string parmFile            = parms.ContainsKey("file")    ? (string)parms["file"]    : null;
            string parmGroup           = parms.ContainsKey("group")   ? (string)parms["group"]   : null;
            string parmPalette         = parms.ContainsKey("palette") ? (string)parms["palette"] : null;
            string parmAngle           = parms.ContainsKey("angle")   ? (string)parms["angle"]   : null;

            BgfCache.Entry entry;
            ushort         scale;
            byte           paletteidx = 0;
            ushort         angle      = 0;

            // verify that minimum parameters are valid/in range and bgf exists
            // angle ranges from [0-7] and are multiples of 512
            if (!UInt16.TryParse(parmScale, out scale) || scale < MINSCALE || scale > MAXSCALE ||
                !Byte.TryParse(parmPalette, out paletteidx) ||
                !UInt16.TryParse(parmAngle, out angle) || angle > 7 ||
                String.IsNullOrEmpty(parmFile) || !BgfCache.GetBGF(parmFile, out entry))
            {
                context.Response.StatusCode = 404;
                return;
            }

            // multiply by 512 and remove full periods from angle
            angle = (ushort)((angle << 9) % GeometryConstants.MAXANGLE);

            // parse animation
            Animation anim = Animation.ExtractAnimation(parmGroup, '-');

            if (anim == null || !anim.IsValid(entry.Bgf.FrameSets.Count))
            {
                context.Response.StatusCode = 404;
                return;
            }

            // stores the latest lastmodified of main and all subov
            DateTime lastModified = entry.LastModified;

            // read suboverlay array params from query parameters:
            //  object/..../?subov={file};{group};{palette};{hotspot}&subov=...
            string[] parmSubOverlays = context.Request.Params.GetValues("s");

            if (parmSubOverlays != null)
            {
                foreach (string s in parmSubOverlays)
                {
                    string[] subOvParms = s.Split(';');

                    BgfCache.Entry bgfSubOv;
                    byte           subOvPalette;
                    byte           subOvHotspot;

                    if (subOvParms == null || subOvParms.Length < 4 ||
                        String.IsNullOrEmpty(subOvParms[0]) ||
                        String.IsNullOrEmpty(subOvParms[1]) ||
                        !byte.TryParse(subOvParms[2], out subOvPalette) ||
                        !byte.TryParse(subOvParms[3], out subOvHotspot) || subOvHotspot > 127 ||
                        !BgfCache.GetBGF(subOvParms[0], out bgfSubOv))
                    {
                        context.Response.StatusCode = 404;
                        return;
                    }

                    // get suboverlay animation
                    Animation subOvAnim = Animation.ExtractAnimation(subOvParms[1], '-');
                    if (subOvAnim == null || !subOvAnim.IsValid(bgfSubOv.Bgf.FrameSets.Count))
                    {
                        context.Response.StatusCode = 404;
                        return;
                    }

                    // create suboverlay
                    SubOverlay subOv = new SubOverlay(0, subOvAnim, subOvHotspot, subOvPalette, 0);

                    // set bgf resource
                    subOv.Resource = bgfSubOv.Bgf;

                    // update lastModified if subov is newer
                    if (bgfSubOv.LastModified > lastModified)
                    {
                        lastModified = bgfSubOv.LastModified;
                    }

                    // add to gameobject's suboverlays
                    gameObject.SubOverlays.Add(subOv);
                }
            }

            // --------------------------------------------------------------------------------------------
            // 2) SET CACHE HEADERS AND COMPARE FOR 304 RETURN
            // --------------------------------------------------------------------------------------------

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

            // set return type
            context.Response.ContentType = "image/png";
            context.Response.AddHeader("Content-Disposition", "inline; filename=object.png");

            // check if client has valid cached version (returns 304)

            /*DateTime dateIfModifiedSince;
             * string modSince = context.Request.Headers["If-Modified-Since"];
             *
             * // try to parse received client header
             * bool parseOk = DateTime.TryParse(
             *  modSince, CultureInfo.CurrentCulture,
             *  DateTimeStyles.AdjustToUniversal, out dateIfModifiedSince);
             *
             * // send 304 and stop if last file write equals client's cache timestamp
             * if (parseOk && dateIfModifiedSince == lastModified)
             * {
             *  context.Response.SuppressContent = true;
             *  context.Response.StatusCode = 304;
             *  return;
             * }*/

            // --------------------------------------------------------------------------------------------
            // 3) PREPARE RESPONSE
            // --------------------------------------------------------------------------------------------

            // set parsed/created values on game object
            gameObject.Resource         = entry.Bgf;
            gameObject.ColorTranslation = paletteidx;
            gameObject.Animation        = anim;
            gameObject.ViewerAngle      = angle;

            // set imagecomposer scale/shrink
            imageComposer.CustomShrink = (float)scale * 0.1f;

            // tick object (triggers image recreation)
            gameObject.Tick(0, 1);

            if (imageComposer.Image == null)
            {
                context.Response.StatusCode = 404;
                return;
            }

            // --------------------------------------------------------------------------------------------
            // 4) CREATE RESPONSE AND FINISH
            // --------------------------------------------------------------------------------------------

            // write image as png
            imageComposer.Image.Save(context.Response.OutputStream, ImageFormat.Png);

            // clear
            imageComposer.Image.Dispose();
            gameObject.SubOverlays.Clear();
        }
Beispiel #3
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;
            }
        }
Beispiel #4
0
        public void ProcessRequest(HttpContext context)
        {
            // --------------------------------------------------------------------------------------------
            // 1) PARSE URL PARAMETERS
            // --------------------------------------------------------------------------------------------

            // See Global.asax:
            //  render/{width}/{height}/{scale}/{file}/{anim}/{palette}/{angle}
            RouteValueDictionary parms = context.Request.RequestContext.RouteData.Values;
            string parmWidth           = parms.ContainsKey("width")   ? (string)parms["width"]   : null;
            string parmHeight          = parms.ContainsKey("height")  ? (string)parms["height"]  : null;
            string parmScale           = parms.ContainsKey("scale")   ? (string)parms["scale"]   : null;
            string parmFile            = parms.ContainsKey("file")    ? (string)parms["file"]    : null;
            string parmAnim            = parms.ContainsKey("anim")    ? (string)parms["anim"]    : null;
            string parmPalette         = parms.ContainsKey("palette") ? (string)parms["palette"] : null;
            string parmAngle           = parms.ContainsKey("angle")   ? (string)parms["angle"]   : null;

            BgfCache.Entry entry;
            byte           paletteidx;
            ushort         angle;
            ushort         width;
            ushort         height;
            ushort         scale;

            // verify that minimum parameters are valid/in range and bgf exists
            // angle ranges from [0-7] and are multiples of 512
            if (!UInt16.TryParse(parmWidth, out width) || width < MINWIDTH || width > MAXWIDTH ||
                !UInt16.TryParse(parmHeight, out height) || height < MINHEIGHT || height > MAXHEIGHT ||
                !UInt16.TryParse(parmScale, out scale) || scale < MINSCALE || scale > MAXSCALE ||
                !Byte.TryParse(parmPalette, out paletteidx) ||
                !UInt16.TryParse(parmAngle, out angle) || angle > 7 ||
                String.IsNullOrEmpty(parmFile) || !BgfCache.GetBGF(parmFile, out entry))
            {
                Finish(context, 404);
                return;
            }

            // multiply by 512 and remove full periods from angle
            angle = (ushort)((angle << 9) % GeometryConstants.MAXANGLE);

            // parse animation
            Animation anim = Animation.ExtractAnimation(parmAnim, '-');

            if (anim == null || !anim.IsValid(entry.Bgf.FrameSets.Count))
            {
                Finish(context, 404);
                return;
            }

            // set groupmax
            anim.GroupMax = entry.Bgf.FrameSets.Count;

            // stores the latest lastmodified of main and all subov
            DateTime lastModified = entry.LastModified;

            // set parsed/created values on game-object
            ObjectBase gameObject = new ObjectBase();

            gameObject.OverlayFileRID   = entry.Num;
            gameObject.Resource         = entry.Bgf;
            gameObject.ColorTranslation = paletteidx;
            gameObject.Animation        = anim;
            gameObject.ViewerAngle      = angle;

            // read suboverlay array params from query parameters:
            //  object/..../?subov={file};{anim};{palette};{hotspot}&subov=...
            string[] parmSubOverlays = context.Request.Params.GetValues("s");
            if (parmSubOverlays != null)
            {
                foreach (string s in parmSubOverlays)
                {
                    string[] subOvParms = s.Split(';');

                    BgfCache.Entry bgfSubOv;
                    byte           subOvPalette;
                    byte           subOvHotspot;

                    if (subOvParms == null || subOvParms.Length < 4 ||
                        String.IsNullOrEmpty(subOvParms[0]) ||
                        String.IsNullOrEmpty(subOvParms[1]) ||
                        !byte.TryParse(subOvParms[2], out subOvPalette) ||
                        !byte.TryParse(subOvParms[3], out subOvHotspot) || subOvHotspot > 127 ||
                        !BgfCache.GetBGF(subOvParms[0], out bgfSubOv))
                    {
                        Finish(context, 404);
                        return;
                    }

                    // get suboverlay animation
                    Animation subOvAnim = Animation.ExtractAnimation(subOvParms[1], '-');
                    if (subOvAnim == null || !subOvAnim.IsValid(bgfSubOv.Bgf.FrameSets.Count))
                    {
                        Finish(context, 404);
                        return;
                    }

                    // set group max
                    subOvAnim.GroupMax = bgfSubOv.Bgf.FrameSets.Count;

                    // create suboverlay
                    SubOverlay subOv = new SubOverlay(0, subOvAnim, subOvHotspot, subOvPalette, 0);

                    // set bgf resource
                    subOv.ResourceID = entry.Num;
                    subOv.Resource   = bgfSubOv.Bgf;

                    // update lastModified if subov is newer
                    if (bgfSubOv.LastModified > lastModified)
                    {
                        lastModified = bgfSubOv.LastModified;
                    }

                    // add to gameobject's suboverlays
                    gameObject.SubOverlays.Add(subOv);
                }
            }

            // --------------------------------------------------------------------------------------------
            // 2) SET CACHE HEADERS AND COMPARE FOR 304 RETURN
            // --------------------------------------------------------------------------------------------

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

            // set return type
            context.Response.ContentType = "image/gif";
            context.Response.AddHeader("Content-Disposition", "inline; filename=object.gif");

            // check if client has valid cached version (returns 304)

            /*DateTime dateIfModifiedSince;
             * string modSince = context.Request.Headers["If-Modified-Since"];
             *
             * // try to parse received client header
             * bool parseOk = DateTime.TryParse(
             *  modSince, CultureInfo.CurrentCulture,
             *  DateTimeStyles.AdjustToUniversal, out dateIfModifiedSince);
             *
             * // send 304 and stop if last file write equals client's cache timestamp
             * if (parseOk && dateIfModifiedSince == lastModified)
             * {
             *  context.Response.SuppressContent = true;
             *  Finish(context, 304);
             *  return;
             * }*/

            // --------------------------------------------------------------------------------------------
            // 3) PREPARE RESPONSE
            // --------------------------------------------------------------------------------------------

            // set gif instance size
            gif.CanvasWidth  = width;
            gif.CanvasHeight = height;

            // set imagecomposer size and shrink
            imageComposer.Width        = width;
            imageComposer.Height       = height;
            imageComposer.CustomShrink = (float)scale * 0.1f;

            // set gameobject (causes initial frame)
            imageComposer.DataSource = gameObject;

            // run animationlength in 1 ms steps (causes new image events)
            for (int i = 0; i < gameObject.AnimationLength + 10; i++)
            {
                tick += 1.0;
                gameObject.Tick(tick, 1.0);
            }

            // handle single frame case
            if (gif.Frames.Count == 0 && frame != null)
            {
                gif.Frames.Add(frame);
            }

            // --------------------------------------------------------------------------------------------
            // 4) CREATE RESPONSE AND FINISH
            // --------------------------------------------------------------------------------------------

            // write the gif to output stream
            gif.Write(context.Response.OutputStream);

            // cleanup
            Finish(context);
        }