19 марта 2011 г.

Обрезка изображения в Asp.Net MVC используя Jcrop

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

Помочь обрезать фото призван хороший плагин Jcrop.
Начнем с того, что скачаем всё нужное для Jcrop, и подключим его к нашему проекту:


Там же разместим и картинку, над которой и будем колдовать. Мы рассмотрим сам процесс обрезки, поэтому не будем заморачиваться и выдумывать варианты отображения картинок.
Суть такова: в папке Content лежит картинка cat.jpg, которая отображается на странице. После обрезки, вырезанная часть сохраняется отдельным файлом в папку Uploads.

Прописываем скрипт и стиль для Jcrop:

<script src="/Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
<link href="/Content/jquery.Jcrop.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery.Jcrop.js" type="text/javascript"></script>

Приступим к нашей странице с картинкой. Тут у нас будет, собственно, сама картинка и одна кнопка, по нажатию на которую будет происходить обрезка и сохранение.
Кроме того, мы поместим там 4 скрытых поля, в каждое из которые будет сохраняться соответствующая координата вырезанной области:

   1:   <p align="center">
   2:          <img id="cropbox" alt="cat" src="../../Content/cat.jpg" />
   3:      </p>
   4:   
   5:      <form method="post" id="myform">
   6:          <p align="center">
   7:              <input type="submit" id="btnsave" name="btnsave" value="Crop and save" />
   8:          </p>
   9:   
  10:          <input type="hidden" name="X" id="X" />
  11:          <input type="hidden" name="Y" id="Y" />
  12:          <input type="hidden" name="W" id="W" />
  13:          <input type="hidden" name="H" id="H" />
  14:      </form>

При POST-запросе страницы, мы будем передавать эти значения в контроллер. Но, перед тем, как передавать данные из скрытых полей, сначала их нужно туда поместить. Это, плюс сама привязка плагина, будет происходить в Javascript-коде данной страницы:

   1:  <script type="text/javascript">
   2:          $(document).ready(function () {
   3:              $('#cropbox').Jcrop({
   4:                  onSelect: updateCoords
   5:              });
   6:          });
   7:   
   8:          function updateCoords(c) {
   9:              $('#X').val(c.x);
  10:              $('#Y').val(c.y);
  11:              $('#W').val(c.w);
  12:              $('#H').val(c.h);
  13:          };
  14:   
  15:      </script>

Все просто - при выбелении какой-то области на картинке, срабатывает функция updateCoords, которая записывает в наши скрытые поля координаты выделения.

Осталось только написать наши методы контроллера.
GET-метод:


public ActionResult Image()
        {
            return View();
        }

В POST-методе, мы принимает параметры формы, считываем оттуда координаты нужной нам области картинки, и производим все необходимые нам действия:


   1:  [HttpPost]
   2:          public ActionResult Image(FormCollection form)
   3:          {
   4:              //Get the Coordinates
   5:              var x = Convert.ToInt32(form["X"]);
   6:              var y = Convert.ToInt32(form["Y"]);
   7:              var w = Convert.ToInt32(form["W"]);
   8:              var h = Convert.ToInt32(form["H"]);
   9:   
  10:              //Create a new image from the specified location to                
  11:              string sourceFile = Request.MapPath("/Content/cat.jpg");
  12:   
  13:              System.Drawing.Image oImage = Bitmap.FromFile(sourceFile);
  14:              // Create a new bitmap with specified parameters
  15:              var bmp = new Bitmap(w, h, oImage.PixelFormat);
  16:              var g = Graphics.FromImage(bmp);
  17:              g.DrawImage(oImage, new Rectangle(0, 0, w, h),
  18:  new Rectangle(x, y, w, h), GraphicsUnit.Pixel);
  19:   
  20:              System.Drawing.Imaging.ImageFormat frm = oImage.RawFormat;
  21:              oImage.Dispose();
  22:   
  23:              string destFile = Request.MapPath("/Uploads/cat.jpg");
  24:   
  25:              // Save cropped image
  26:              bmp.Save(destFile, frm);
  27:   
  28:              return RedirectToAction("image");
  29:          }

Вот, что мы делаем: получаем из присланной формы значения координат выделения; создаем новый Image-файл на основе нашей картинки; создаем новый Bitmap-файл, с размерами выделения; выделяем прямоугольную область на изначальной картинке, и копируем ее в созданный Bitmap; сохраняем новое изображение, сопоставляя его формат с изначальным. Вот и все.

Посмотрим, что у нас получилось. При запуске видим страницу с картинкой и кнопкой:
Здесь, сразу, без каких-либо дополнительных действий, мы можем выделить на картинке нужную нам область:
После нажатия кнопки произойдет submit страницы, в результате чего она просто обновится, а в папке Uploads мы найдем вырезанный нами участок изображения:

Результат "на лицо"! )))
_____
Скачать исходники можно отсюда.