Как стать автором
Обновить

asp.net: динамическая генерация изображений

Время на прочтение8 мин
Количество просмотров4K
Генерация динамических изображений – это очень полезная техника. К сожалению, в asp.net нет стандартного функционала, который бы реализовал возможность динамически создавать изображения. Цель этой статьи показать один из способов реализации динамических изображения в asp.net.

Первым делом определим задачу:
— нам нужен пользовательский элемент управления, который бы в качестве входных данных принимал экземпляр Bitmap и тип желаемого формата (jpeg, png, bmp, gif);
— элемент управления должен обеспечивать вывод на страницу изображения определенного через Bitmap.
Определим перечисление с разрешенными типами формата изображения:
    public enum DynamicImageFormat    {      Gif = 0, Jpeg, Bmp, Png    }* This source code was highlighted with Source Code Highlighter.

Это перечисление будет расположено в теле класса обработчика HTTP запроса, который будет описан ниже.
Теперь привожу текст класса, реализующего необходимую нам функциональность:
  public partial class DynamicImageControl: System.Web.UI.UserControl  {    public Bitmap DynamicBitmap { get; set; }    public DynamicImageHandler.DynamicImageFormat DynamicImageFormat = DynamicImageHandler.DynamicImageFormat.Png;    protected void Page_Load(object sender, EventArgs e)    {      if (DynamicBitmap != null)      {        Guid _bitmapGuid = Guid.NewGuid();        Cache[_bitmapGuid.ToString()] = DynamicBitmap;        img.ImageUrl = String.Format(«DynamicImageHandler.ashx?bitmap={0}&format={1}», _bitmapGuid, (int)DynamicImageFormat);      }    }  }* This source code was highlighted with Source Code Highlighter.

Необходимо пояснить следующие вещи:
— для динамического формирования изображения я использую обработчик HTTP-запросов DynamicImageHandler.ashx, реализацию которого я приведу ниже;
— ссылка на экземпляр Bitmap передается в обработчик через механизм Cache, место, где в рамках приложения можно хранить данные, GUID сохраненного экземпляра Bitmap передается обработчику через строку запроса, так же передается тип формата изображения.
Использование Cache не самое лучшее решение. Буду рад услышать альтернативные варианты.

Далее я привожу код обработчика:
    public void ProcessRequest(HttpContext context)    {      string _bitmapGuid = context.Request.QueryString[«bitmap»];      if (!String.IsNullOrEmpty(_bitmapGuid))      {        if (context.Cache[_bitmapGuid] != null)        {          Bitmap _bitmap = (Bitmap)context.Cache[_bitmapGuid];          if (_bitmap != null)          {            ImageFormat DynImageFormat = GetImgFormat(context);            MemoryStream MemStream = new MemoryStream();            _bitmap.Save(MemStream, DynImageFormat);            MemStream.WriteTo(context.Response.OutputStream);            MemStream.Dispose();            _bitmap.Dispose();            context.Cache.Remove(_bitmapGuid);          }        }      }    }* This source code was highlighted with Source Code Highlighter.

Здесь обработчик получает и обрабатывает параметры, загружает Bitmap из Cache и, используя механизм работы с потоками, пишет в поток контекста текущей страницы изображение в необходимом нам формате. Функция GetImgFormat, которая помогает обработать тип формата изображения определена так:
    private ImageFormat GetImgFormat(HttpContext context)    {      ImageFormat result = ImageFormat.Png;      if (!String.IsNullOrEmpty(context.Request.QueryString[«format»]))      {        DynamicImageFormat _imgFormat = (DynamicImageFormat)Convert.ToInt32(context.Request.QueryString[«format»]);        switch (_imgFormat)        {          case DynamicImageFormat.Gif:            result = ImageFormat.Gif;            break;          case DynamicImageFormat.Jpeg:            result = ImageFormat.Jpeg;            break;          case DynamicImageFormat.Bmp:            result = ImageFormat.Bmp;            break;          case DynamicImageFormat.Png:            result = ImageFormat.Png;            break;          default:            result = ImageFormat.Png;            break;        }      }      return result;    }* This source code was highlighted with Source Code Highlighter.

Кроме того, в классе обработчика необходимо определить булевое свойство IsReusable, которое даст понять asp.net нужно ли при каждом запросе создавать новый экземпляр обработчика.
    public bool IsReusable    {      get      {        return true;      }    }* This source code was highlighted with Source Code Highlighter.

Если мы вернем IsReusable = false, то asp.net будет каждый раз создавать новый экземпляр и таким образом несколько увеличит нагрузку на сервер.

Теперь продемонстрирую вариант использования полученного компонента и обработчика. Используем элемент управления указанным способом:
  <form id=«form1» runat=«server»>  
  <asp:Label ID=«Label2» runat=«server» Text=«Динамическое создание изображений: „></asp:Label>
  <uc1:DynamicImageControl ID=“DynamicImageControl1» runat=«server» />
  <asp:Label ID=«Label1» runat=«server» Text=«Конец.»></asp:Label>
  </form>
* This source code was highlighted with Source Code Highlighter.

В коде инициализируем поля элемента. Для этого определим простейшую функцию, которая строит Bitmap с простейшей капчей, так известной всем кто хоть раз регистрировался в вебе.
    public static string GetRandomPassword(int length)    {      Random rand = new Random();            StringBuilder password = new System.Text.StringBuilder(length);      for (int i = 1; i <= length; i++)      {        int charIndex;        do        {          charIndex = rand.Next(48, 123);        } while (!((charIndex >= 48 && charIndex <= 57) ||        (charIndex >= 65 && charIndex <= 90) || (charIndex >= 97 && charIndex <= 122)));        password.Append(Convert.ToChar(charIndex));      }      return password.ToString();    }    public Bitmap DrawPassword()    {      Bitmap _bitmap = new Bitmap(150, 30);      Graphics _graphics = Graphics.FromImage(_bitmap);      SolidBrush _foreColor = new SolidBrush(Color.White);      SolidBrush _backColor = new SolidBrush(Color.FromArgb(0x73, 0x82, 0x9F));      _graphics.FillRectangle(_backColor, 0, 0, 150, 30);      Font _font = new Font(«Verdana», 15);      Point _point = new Point(5, 5);      string _password = GetRandomPassword(10);      _graphics.DrawString(_password, _font, _foreColor, _point);      if (_graphics != null)        _graphics.Dispose();      return _bitmap;          }* This source code was highlighted with Source Code Highlighter.

Ну и наконец, инициализация элемента управления:
    protected void Page_Load(object sender, EventArgs e)    {      DynamicImageControl1.DynamicBitmap = DrawPassword();      DynamicImageControl1.DynamicImageFormat = DynamicImageHandler.DynamicImageFormat.Gif;    }    * This source code was highlighted with Source Code Highlighter.


Это все. В результате на экране мы сможем увидеть такую вот картинку:



Исходный код проекта с классами и примером лежит здесь:
ifolder.ru/6606116

PS: «в статье нет ошибок!» — к сожалению утверждать этого невозможно, но я буду рад, если вы обратите мое внимание на найденную вами ошибку или предложите какие-то улучшения.

PPS: статья размещена на сайте www.gotdotnet.ru
www.gotdotnet.ru/LearnDotNet/ASPNET/558721.aspx
Теги:
Хабы:
+16
Комментарии42

Публикации

Изменить настройки темы

Истории

Работа

.NET разработчик
72 вакансии

Ближайшие события