开发者

Trying to save a generated heatmap in Azure Storage

I have a Heatmap that currently works on a stand alone sever that I am porting to Azure Storage. How do I go about saving the butmap file in Azure Storage. Originally I had a entry in my web.config file that pointed the image cache to a direct path on anther drive (IE ) Everything now will be in ~/map_cache folder in the Storage Account. How can I mod this for storage locally in Azure.

protected void Page_Load(object sender, EventArgs e)
{
    xxxxxxxdb = new xxxxxxx(ConfigurationManager.AppSettings["xxxxxxx"]);

    string imageCachePath = Server.MapPath("/map_cache/HotSpots");
    int fileExpirationTime = int.Parse(ConfigurationManager.AppSettings["HotspotImageExpirationTime"]);
    Bitmap bitmap;

    string requestParam = Page.Request.Params["id"];
    string bitmapFileName = Path.Combine(imageCachePath, requestParam + ".png");
    if (File.Exists(bitmapFileName) && File.GetCreationTime(bitmapFileName) > DateTime.Now.AddHours(-fileExpirationTime))
    {
        bitmap = (Bitmap)Image.FromFile(bitmapFileName);
    }
    else
    {
        int zoomLevel = requestParam.Length;

        double tileX = 0;
        double tileY = 0;
        for (int index = 0; index < zoomLevel; index++)
        {
            int digit = int.Parse(requestParam[index].ToString());
            tileY += ((digit & 2) / 2) * Math.Pow(2, (zoomLevel - index - 1));
            tileX += (digit & 1) * Math.Pow(2, (zoomLevel - index - 1));
        }
        double pixelXMin = tileX * 256;
        double pixelYMin = tileY * 256;
        double pixelXMax = (tileX + 1) * 256 - 1;
        double pixelYMax = (tileY + 1) * 256 - 1;

        double longMin = ((pixelXMin * 360) / (256 * Math.Pow(2, zoomLevel))) - 180;
        double longMax = ((pixelXMax * 360) / (256 * Math.Pow(2, zoomLevel))) - 180;
        double latMin = Math.Asin((Math.Exp((0.5 - pixelYMin / 256 / Math.Pow(2, zoomLevel)) * 4 * Math.PI) - 1) /
                                  (Math.Exp((0.5 - pixelYMin / 256 / Math.Pow(2, zoomLevel)) * 4 * Math.PI) + 1)) * 180 /
                        Math.PI;
        double latMax = Math.Asin((Math.Exp((0.5 - pixelYMax / 256 / Math.Pow(2, zoomLevel)) * 4 * Math.PI) - 1) /
                                  (Math.Exp((0.5 - pixelYMax / 256 / Math.Pow(2, zoomLevel)) * 4 * Math.PI) + 1)) * 180 /
                        Math.PI;

        double pixelResolution = (Math.Cos(latMax * Math.PI / 180) * 2 * Math.PI * 6378137) / (256 * Math.Pow(2, zoomLevel));
        double pixelArea = Math.Pow(pixelResolution, 2);

        double maxHotspotDensity = Math.Max(120.0 / zoomLevel, 3.0) / pixelArea;

        bitmap = GenerateBlankBitmap();

        var accidents = from hs in db.cs_PT_VEGeoDatas
                        where hs.Latitude <= latMin && hs.Latitude >= latMax
                              && hs.Longitude >= longMin && hs.Longitude <= longMax
                        select new { hs.Latitude, hs.Longitude };

        Dictionary<Point, HotSpot> hotSpots = new Dictionary<Point, HotSpot>();
        foreach (var accident in accidents)
        {
            int pixelX, pixelY;
            LatLongToPixelXY(accident.Latitude, accident.Longitude, zoomLevel, out pixelX, out pixelY);
            pixelX %= 256;
            pixelY %= 256;
            for (int ix = -doublePixelSize; ix <= doublePixelSize; ix++)
            {
                for (int iy = -doublePixelSize; iy <= doublePixelSize; iy++)
                {
                    Point point;
                    bool borderPoint = false;
                    if (zoomLevel < doublePixelZoomLevel)
                    {
                        point = new Point(pixelX, pixelY);
                    }
                    else
                    {
                        if (pixelX + ix >= 0 && pixelX + ix <= 255 && pixelY + iy >= 0 && pixelY + iy <= 255)
                        {
                            point = new Point(pixelX + ix, pixelY + iy);
                            borderPoint = (ix == -doublePixelSize) || (iy == -doublePixelSize) ||
                                              (ix == doublePixelSize) || (iy == doublePixelSize);
                        }
                        else
                        {
                            break;
                        }
                    }
                    HotSpot hotSpot;
                    if (hotSpots.ContainsKey(point))
                    {
                        hotSpot = hotSpots[point];
                        hotSpot.borderPoint &= borderPoint;
                        hotSpot.count += 1;
                    }
                    else
                    {
                        hotSpot = new HotSpot { borderPoint = borderPoint, count = 1 };
                        hotSpots.Add(point, hotSpot);
                    }
                    if (zoomLevel < doublePixelZoomLevel)
                    {
                        break;
                    }
                }
                if (zoomLevel < doublePixelZoomLevel)
                {
                    break;
                }
            }
        }
        foreach (var hotspotPixel in hotSpots)
        {
            double hc = hotspotPixel.Value.count;
            double hcDensity = hc / pixelArea;

            Color color;
            if (!hotspotPixel.Value.borderPoint)
            {
                color = Color.FromArgb(255, 255,
                                       (int)
                                       Math.Max((maxHotspotDensity - hcDensity) / maxHotspotDensity * 255, 0.0),
                                       0);
            }
    开发者_如何转开发        else
            {
                color = Color.Black;
            }
            bitmap.SetPixel(hotspotPixel.Key.X, hotspotPixel.Key.Y, color);
        }
        bitmap.Save(bitmapFileName);
    }

    WritePngToStream(bitmap, Response.OutputStream);
}

Currently I get the following Error message

A generic error occurred in GDI+.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[ExternalException (0x80004005): A generic error occurred in GDI+.] System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams) +772265 HotSpotTileServer.Page_Load(Object sender, EventArgs e) in C:\Projects\xxx\xxx\SpeedTrap\HotSpotTileServer.aspx.cs:141 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +25 System.EventHandler.Invoke(Object sender, EventArgs e) +0 System.Web.UI.Control.LoadRecursive() +71 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3048

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.1


There are three things you can try:

  • for temporary files - that don't need to be shared across web servers (which is rare!) - then you can use Local Storage - http://vkreynin.wordpress.com/2010/01/10/learning-azure-local-storage-with-me/

  • for a disk shared between web servers (but only one of these will have write access) you could use an Azure Drive - http://blog.maartenballiauw.be/post/2010/02/02/Using-Windows-Azure-Drive-(aka-X-Drive).aspx

  • for general flexible shared file storage, try using Azure Blob Storage - http://blogs.msdn.com/b/jnak/archive/2008/10/29/walkthrough-simple-blob-storage-sample.aspx

Definitely the last of these is the one I'd recommend - it's fast, flexible and scalable.


(I agree with Stuart 100%.) Here are more reasons why I recommend you consider using Azure Blob Storage for storing heatmap png file:

  1. The local hard disk is not guaranteed to be durable. (This may not be important to you, however, if they can be regenerated easily.)
  2. Blobs can be made publicly visible (so, for example, they can be directly referenced from HTML code with an img tag).
  3. Blobs can easily be made available in the AppFabric CDN (for better performance, including around 24 global distribution points).
  4. Blobs will scale in ways that using the local file system will not. For example, if you ever want to scale your site to use more than one Heatmap generator role instance (running 2 of them on different machines in the cloud), you will want to be on Blob storage since none of the other options will work.
  5. Blobs are optimized for cloud scale and reliability and high availability.

I recommend you use the very handy Windows Azure SDK for writing your blobs. The SDK wraps the official REST interfaces with a very nice set of classes that are really easy to use from .NET code. Specifically you would use the CloudBlobClient class, and the method UploadByteArray. You can download the Azure SDK 1.4 here.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜