Попытка сохранить созданную тепловую карту в хранилище Azure - PullRequest
0 голосов
/ 14 апреля 2011

У меня есть Heatmap, которая в настоящее время работает на автономном сервере, который я портирую на хранилище Azure.Как мне сохранить файл butmap в хранилище Azure.Первоначально у меня была запись в моем файле web.config, в которой кэш изображений указывался на прямой путь к другому диску (IE). Теперь все будет в папке ~ / map_cache в учетной записи хранения.Как я могу изменить это для хранения локально в 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);
}

В настоящее время я получаю следующее сообщение об ошибке

A generic error occurred in GDI+.

Описание: во время выполнения текущего веб-запроса произошло необработанное исключение,Просмотрите трассировку стека для получения дополнительной информации об ошибке и о том, где она возникла в коде.

Сведения об исключении: System.Runtime.InteropServices.ExternalException: в GDI + произошла общая ошибка.

ИсточникОшибка:

Во время выполнения текущего веб-запроса было сгенерировано необработанное исключение.Информацию о происхождении и местонахождении исключения можно определить с помощью приведенной ниже трассировки стека исключений.

Трассировка стека:

[ExternalException (0x80004005): в GDI + произошла общая ошибка.]Drawing.Image.Save (имя файла строки, кодер ImageCodecInfo, кодировщик EncoderParametersParams) +772265 HotSpotTileServer.Page_Load (отправитель объекта, EventArgs e) в C: \ Projects \ xxx \ xxx \ SpeedTrap \ HotSpotTileServer.aspx.eb: 14.Util.CalliHelper.EventArgFunctionCaller (IntPtr fp, Объект o, Объект t, EventArgs e) +25 System.EventHandler.Invoke (Отправитель объекта, EventArgs e) +0 System.Web.UI.Control.LoadRecursive () +71 System.Web.UI.Page.ProcessRequestMain (логическое значение includeStagesBeforeAsyncPoint, логическое значение includeStagesAfterAsyncPoint) + 3048

Информация о версии: версия Microsoft .NET Framework: 4.0.30319;ASP.NET версия: 4.0.30319.1

Ответы [ 2 ]

4 голосов
/ 15 апреля 2011

Есть три вещи, которые вы можете попробовать:

Определенно, последний из них я бы порекомендовал - он быстрый, гибкий и масштабируемый.

1 голос
/ 17 апреля 2011

(Я согласен со Стюартом на 100%.) Вот еще несколько причин, по которым я рекомендую вам использовать хранилище BLOB-объектов Azure для хранения png-файла Heatmap:

  1. Локальный жесткий диск не гарантированно долговечен. (Однако это может быть не важно для вас, если их можно легко восстановить.)
  2. BLOB-объекты можно сделать общедоступными (например, на них можно напрямую ссылаться из HTML-кода с помощью тега img).
  3. BLOB-объекты можно легко сделать доступными в AppFabric CDN (для повышения производительности, включая около 24 глобальных точек распространения).
  4. Капли будут масштабироваться таким образом, что использование локальной файловой системы не будет. Например, если вы когда-нибудь захотите масштабировать свой сайт, чтобы использовать более одного экземпляра роли генератора Heatmap (запустив 2 из них на разных машинах в облаке), вы захотите использовать хранилище BLOB-объектов, поскольку ни один из других вариантов не будет работать.
  5. BLOB-объекты оптимизированы для облачного масштаба, надежности и высокой доступности.

Я рекомендую вам использовать очень удобный Windows Azure SDK для написания ваших больших двоичных объектов. SDK упаковывает официальные интерфейсы REST очень хорошим набором классов, которые действительно просты в использовании из кода .NET. В частности, вы бы использовали класс CloudBlobClient и метод UploadByteArray. Вы можете скачать Azure SDK 1.4 здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...