Учебный курс по WebMatrix, глава 10. Работа с изображениями

Это продолжение учебного курса по WebMatrix. Предыдущие части руководство можно найти здесь:

В этой части описываются способы добавления изображений на веб-сайт, их отображения и выполнения действий с ними (изменение размера, переворот, добавление водяного знака) перед сохранением этих изображений.

Будет рассмотрено

  • динамическое добавление изображения на страницу;
  • предоставление пользователю возможности передать изображение на сайт;
  • изменение размера изображения;
  • переворот или поворот изображения;
  • добавление водяного знака в изображение;
  • использование изображения в качестве водяного знака.

В данной главе рассматриваются следующие новые функции программирования ASP.NET:

  • вспомогательный объект WebImage;
  • объект Path, который предоставляет методы, позволяющие управлять путем и именами файлов.

Динамическое добавление изображения на веб-страницу

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

Если изображение уже находится на сайте и его просто требуется отобразить на странице, применяется элемент <img> языка HTML, подобный приведенному ниже:

<img src="images/Photo1.jpg"alt="``фото``-``пример``" />

Вместе с тем, порой требуется выводить изображения на экран динамически, то есть когда неизвестно, какое изображение показать, пока страница не будет запущена.

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

1. Создайте в WebMatrix новый веб-сайт и добавьте новую страницу DynamicImage.cshtml.

2. В корневой папке веб-сайта добавьте новую папку и назовите ее images.

3. В папку images добавьте четыре изображения (подойдут любые имеющиеся под рукой изображения, однако они должны уместиться на странице). Переименуйте файлы изображений в Photo1.jpg, Photo2.jpg, Photo3.jpg и Photo4.jpg (в этой процедуре Photo4.jpg использоваться не будет, но этот файл понадобится позднее в данной главе).

4. Замените существующую разметку на странице следующим кодом:

@{ var imagePath= "";

    if( Request["photoChoice"] != null){

        imagePath = @"images\"+ Request["photoChoice"];

   }

}

<!DOCTYPE html>

<html>

<head>

  <title>Оперативный показ изображения</title>

</head>Картинки

<body>

<h1>Оперативный показ изображения</h1>

<form method="post" action="">

    <div>

        Хочу увидеть:

        <select name="photoChoice">

            <option value="Photo1.jpg">Фото 1</option>

            <option value="Photo2.jpg">Фото 2</option>

            <option value="Photo3.jpg">Фото 3</option>

        </select>

        &nbsp;

        <input type="submit" value="Смотреть"/>

    </div>

    <div style="padding:10px;">

        @if(imagePath != ""){

            <img src="@imagePath" alt="пример изображения" width="300px" />

        }

    </div>

</form>

</body>

</html>

В текстовой области страницы имеется раскрывающийся список (элемент <select>) с именем photoChoice. В списке предлагаются три варианта, и атрибут value каждого пункта в списке соответствует имени одного из изображений, помещенных в папку images. По существу, список предоставляет пользователю возможность выбрать понятное имя, такое как "Фото 1", и затем передает имя JPG-файла при отправке страницы.

В коде можно извлечь выбор пользователя (другими словами, имя файла изображения) из списка, считав Request["photoChoice"]. Сначала выясняется, сделан ли выбор вообще. Если выбор сделан, выстраивается путь к изображению, который состоит из имени папки для изображений и выбранного пользователем имени файла изображения (если при попытке выстроить путь окажется, что в Request["photoChoice"] нет данных, будет выведено сообщение об ошибке). В результате получится относительный путь, подобный приведенному ниже:

images\Photo1.jpg

Путь сохраняется в переменной imagePath, которая потребуется позднее на странице.

В текстовой области имеется также элемент <img>, который используется для показа выбранного пользователем изображения. Атрибуту src не присваивается имя файла или URL-адрес, как это делается при отображении статического элемента. Вместо этого ему присваивается @imagePath, то есть он получает значение от заданного в коде пути.

Однако при первом запуске страницы изображения для показа не имеется, поскольку пользователь пока ничего не выбрал. Это обычно означает, что атрибут src будет пустым, а изображение будет заменено красным знаком "х" (или любым знаком, который браузер выводит, если не удается найти изображение). Во избежание этого элемент <img> помещают в блок if, который служит для проверки, имеются ли данные в переменной imagePath. Если пользователь сделал выбор, imagePath содержит путь. Если пользователь не выбрал изображение либо страница открыта впервые, элемент <img> даже не визуализируется.

5. Сохраните файл и запустите страницу в браузере. Просмотрите возможности страницы:

imageimage

Передача изображения

В предыдущем примере был показан динамический вывод изображения, однако это выполнимо, только если изображения уже имеются на веб-сайте. Эта процедура демонстрирует способ предоставления пользователю возможности передать изображение на сайт, которое затем отображается на странице. В ASP.NET реализована возможность оперативной обработки изображений посредством вспомогательного объекта WebImage, который предоставляет методы создания, обработки и сохранения изображений. Вспомогательный объект WebImage поддерживает все распространенные типы файлов веб-изображений, включая JPG,PNG и BMP-файлы. В рамках этой главы используются JPG-файлы, однако допустимы и любые типы файлов изображений.

1. Добавьте новую страницу с названием UploadImage.cshtml и замените существующую разметку на странице следующим кодом:

@{ WebImage photo = null;

    var newFileName = "";

    var imagePath = "";

    if(IsPost){

        photo = WebImage.GetImageFromRequest();

        if(photo != null){

            newFileName = Guid.NewGuid().ToString() + "_"+

                Path.GetFileName(photo.FileName);

            imagePath = @"images\"+ newFileName;

            photo.Save(@"~\" + imagePath);

        }

    }

}

<!DOCTYPE html>

<html>

<head>

  <title>Передача изображения</title>

</head>

<body>

  <form action="" method="post" enctype="multipart/form-data">

    <fieldset>

      <legend>Передача изображения</legend>

      <label for="Image">Изображение</label>

      <input type="file" name="Image" />

      <br/>

      <input type="submit" value="Загрузить" />

    </fieldset>

  </form>

  <h1>Переданное изображение</h1>

    @if(imagePath != ""){

    <div class="result">

        <img src="@imagePath" alt="изображение" />

    </div>

    }

</body>

</html>

В текстовой области имеется элемент <inputtype="file">, который позволяет пользователям выбирать файл для передачи. При нажатии кнопки Submit (отправить) выбранный файл отправляется вместе с формой.

Для извлечения переданного изображения применяется вспомогательный объект WebImage, который предоставляет разнообразные полезные методы работы с изображениями. В частности, метод WebImage.GetImageFromRequest служит для извлечения переданного изображения (если таковое имеется) и сохранения его в переменной photo.

Значительная часть операций в этом примере связана с извлечением и заданием имен файлов и путей. Проблема заключается в том, что требуется извлечь имя (и только имя) переданного пользователем изображения, а затем создать новый путь к месту, где это изображение будет сохранено. Поскольку пользователи вполне могли передать несколько изображений с одинаковыми именами, применяется дополнительный код для создания уникальных имен и предотвращения перезаписи уже имеющихся изображений.

Если изображение действительно было передано (тест: if (photo != null)), имя изображения извлекается из свойства FileName этого изображения. При передаче изображения пользователем свойство FileNameсодержит его исходное имя, включая путь от компьютера пользователя. Оно может выглядеть следующим образом:

C:\Users\Joe\Pictures\SamplePhoto1.jpg

Однако вся эта информация о пути не нужна, требуется лишь фактическое имя файла (SamplePhoto1.jpg). С помощью метода Path.GetFileName можно извлечь из пути только имя файла, как показано в примере:

Path.GetFileName(photo.FileName)

После этого путем присоединения к исходному имени универсального идентификатора GUID создается новое уникальное имя файла (дополнительные сведения об идентификаторах GUID см. в разделе About GUIDs далее в этой главе). Затем выстраивается полный путь, который можно использовать для сохранения изображения. Путь сохранения состоит из нового имени файла, папки (images) и текущего расположения в структуре веб-сайта.

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

И наконец, путь сохранения передается методу Save вспомогательного объекта WebImage. Переданное изображение сохраняется под новым именем. Метод сохранения выглядит следующим образом: photo.Save(@"~\" +imagePath). Полный путь добавляется после сочетания @"~\", обозначающего текущее расположение в структуре веб-сайта.

Как и в предыдущем примере, в текстовой области страницы содержится элемент <img>, который служит для показа изображения. Если imagePath присвоено значение, элемент <img> отображается, а для его атрибута src задается значение imagePath.

2. Откройте страницу в браузере и попробуйте загрузить изображение:

imageimage

Об идентификаторах GUID

GUID (глобальный уникальный идентификатор) выглядит примерно так: 936DA01F-9ABD-4d9d-80C7-02AF85C822A8 (технически это 16-байтное/128-битное число). При возникновении потребности в GUID вызывают специальный код, который создает уникальный идентификатор. Особенность GUID состоит в том, что благодаря огромному размеру числа (3,4 x1038) и алгоритму его создания полученное число фактически гарантированно является единственным в своем роде. В силу этого идентификаторы GUID представляют собой эффективный способ создания имен, когда требуется гарантировать уникальность имени. Недостаток, естественно, заключается в неудобстве GUID для пользователей, поэтому они преимущественно применяются, когда имя используется только в коде.

Изменение размера изображения

Если веб-сайт принимает изображения от пользователей, может потребоваться изменить их размер перед отображением или сохранением. В этих целях можно снова воспользоваться вспомогательным объектом WebImage.

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

1. Добавьте новую страницу с именем Thumbnail.cshtml.

2. В папке images создайте вложенную папку thumbs.

3. Замените существующую разметку на странице следующим кодом:

@{ WebImage photo = null;

    var newFileName = "";

    var imagePath = "";

    var imageThumbPath = "";

    if(IsPost){

        photo = WebImage.GetImageFromRequest();

        if(photo != null){

             newFileName = Guid.NewGuid().ToString() + "_"+

                 Path.GetFileName(photo.FileName);

             imagePath = @"images\"+ newFileName;

             photo.Save(@"~\" + imagePath);

            imageThumbPath = @"images\thumbs\"+ newFileName;

            photo.Resize(width: 60, height: 60, preserveAspectRatio: true,

               preventEnlarge: true);

            photo.Save(@"~\" + imageThumbPath); }

    }

}

<!DOCTYPE html>

<html>

<head>

  <title>Изменение размера изображения</title>

</head>

<body>

<h1>Эскиз изображения</h1>

  <form action="" method="post" enctype="multipart/form-data">

    <fieldset>

      <legend>Создание эскиза изображения</legend>

      <label for="Image">Изображение</label>

      <input type="file" name="Image" />

      <br/>

      <input type="submit" value="Загрузить" />

    </fieldset>

  </form>

    @if(imagePath != ""){

    <div class="result">

        <img src="@imageThumbPath" alt="изображение эскиза"/>

        <a href="@Html.AttributeEncode(imagePath)" target="_Self">

            К полноразмерному

        </a>

    </div>

    }

</body>

</html>

Этот код похож на код в предыдущем примере. Различие состоит в том, что данный код сохраняет изображение дважды, сначала — обычным образом, а затем — после создания копии-эскиза изображения. Сначала переданное изображение извлекают и сохраняют в папке images. Затем выстраивается новый путь к эскизу изображения. Чтобы фактически создать эскиз, во вспомогательном объекте WebImage вызывают метод Resize для создания изображения размером 60 х 60 пикселей. В примере показано, как сохраняется соотношение сторон и как обеспечивается предотвращение увеличения изображения (если новый размер окажется фактически больше исходного). После изменения размера изображение сохраняют во вложенной папке thumbs.

Для показа изображения при определенных условиях в конце разметки применяется тот же элемент <img> с динамическим атрибутом src, который встречался и в предыдущих примерах. В данном случае отображается эскиз. Для создания гиперссылки на большую версию изображения используется элемент <a>. Как и атрибуту src элемента <img>, атрибуту href элемента <a> динамически присваивается значение, содержащееся в imagePath. Чтобы обеспечить возможность использования пути как URL-адреса, imagePath передается методу Html.AttributeEncode, который преобразует зарезервированные символы в пути в символы, поддерживаемые URL-адресом.

4. Откройте страницу в браузере и попробуйте загрузить уже использовавшееся ранее изображение, чтоб увидеть изменения в работе кода:

imageimageimage

Поворот или переворот изображения.

Вспомогательный объект WebImage позволяет также переворачивать и поворачивать изображения. Приводимая процедура демонстрирует способы извлечения изображения с сервера, переворота по вертикали, сохранения и показа перевернутого изображения на странице. В этом примере просто используется уже имеющийся на сервере файл (Photo2.jpg). В реальном приложении, возможно, будет перевернуто изображение, имя которого извлекается динамически, как в предыдущих примерах.

1. Добавьте новую страницу с именем Flip.cshtml и замените существующую разметку в файле следующим кодом:

@{ var imagePath= "";

    WebImage photo = new WebImage(@"~\Images\Photo2.jpg");

    if(photo != null){

        imagePath = @"images\Photo2.jpg";

        photo.FlipVertical();

          photo.Save(@"~\" + imagePath);

     }

}

<!DOCTYPE html>

<html>

<head>

  <title>Извлечение изображения из файла</title>

  <meta http-equiv="content-type" content="text/html;charset=utf-8" />

</head>

<body>

<h1>Переворот изображения по вертикали</h1>

@if(imagePath != ""){

  <div class="result">

    <img src="@imagePath" alt="изображение" />

  </div>

}

</body>

</html>

Программный код применяет вспомогательный объект WebImage для извлечения изображения с сервера. Путь к изображению можно создать посредством той же методики, которая применялась в прежних примерах для сохранения изображений; путь передается при создании изображения с помощью WebImage:

WebImage photo = new WebImage(@"~\Images\Photo2.jpg");

Если изображение обнаружено, выстраивается новый путь и имя файла, как в прежних примерах. Чтобы перевернуть изображение, вызывают метод FlipVertical, а затем изображение вновь сохраняют.

Изображение вновь показывается на странице с помощью элемента <img> с атрибутом src, которому присвоено значение imagePath.

2. Откройте страницу в браузере. Изображение Photo2.jpg показано перевернутым по вертикали. Если запросить страницу еще раз (Обновить), изображение вновь переворачивается в правильное положение:

imageimage

Для поворота изображения используется тот же код, однако вместо вызова метода FlipVertical или FlipHorizontal вызывают метод RotateLeft или RotateRight.

Добавление водяного знака в изображение.

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

1. Добавьте новую страницу с именем Watermark.cshtml и замените существующую разметку следующим кодом:

@{ var imagePath= "";

    WebImage photo = new WebImage(@"~\Images\Photo3.jpg");

    if(photo != null){

        imagePath = @"images\Photo3.jpg";

        photo.AddTextWatermark("Что то написали", fontColor:"Yellow", fontFamily:

            "Arial");

        photo.Save(@"~\" + imagePath); }

}

<!DOCTYPE html>

<html>

<head>

  <title>Водяной знак</title>

  <meta http-equiv="content-type" content="text/html;charset=utf-8"/>

</head>

<body>

<h1>Добавление водяного знака в изображение</h1>

@if(imagePath != ""){

  <div class="result">

    <img src="@imagePath" alt="Изображение" />

  </div>

}

</body>

</html>

Этот код похож на код страницы Flip.cshtml в прежнем примере (хотя на этот раз используется файл Photo3.jpg). Чтобы добавить водяной знак, во вспомогательном объекте WebImage вызывают метод AddTextWatermark до сохранения изображения. При вызове метода AddTextWatermark передают текст "Мой водяной знак", задают цвет шрифта — желтый и семейство шрифтов — Arial (здесь это не показано, однако вспомогательный объект WebImage также позволяет задать прозрачность, семейство и размер шрифтов, положение текста водяного знака).

Как демонстрировалось ранее, изображение показывается на странице с помощью элемента <img> с атрибутом src, которому присвоено значение @imagePath.

2. Откройте страницу в браузере:

image

Использование изображения в качестве водяного знака.

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

1. Добавьте новую страницу с именем ImageWatermark.cshtml.

2. Добавьте в папку images изображение, которое можно использовать как эмблему, и переименуйте его в MyCompanyLogo.jpg. Это изображение должно сохранять четкость, будучи уменьшенным до 80 пикселей в ширину и 20 — в высоту.

3. Замените существующую разметку следующим кодом:

@{ var imagePath = "";

   WebImage WatermarkPhoto = new WebImage(@"~\"+

        @"\Images\MyCompanyLogo.jpg");

    WebImage photo = new WebImage(@"~\Images\Photo4.jpg");

    if(photo != null){

        imagePath = @"images\Photo4.jpg";

        photo.AddImageWatermark(WatermarkPhoto, width: 80, height: 20,

           horizontalAlign:"Center", verticalAlign:"Bottom",

           opacity:100, padding:10);

      photo.Save(@"~\" + imagePath); }

    }

<!DOCTYPE html>

<html>

<head>

  <title>Водяной знак — изображение</title>

  <meta http-equiv="content-type" content="text/html;charset=utf-8"/>

</head>

<body>

  <h1>Использование изображения в качестве водяного знака</h1>

  @if(imagePath != ""){

    <div class="result">

      <img src="@imagePath" alt="Изображение" />

    </div>

  }

</html>

Это еще одно видоизменение кода, встречавшегося в прежних примерах. В данном случае для добавления изображения в качестве водяного знака к целевому изображению (Photo4.jpg) до его сохранения вызывают метод AddImageWatermark. При вызове метода AddImageWatermark задаются размеры водяного знака: 80 пикселей в ширину и 20 пикселей в высоту. Изображение MyCompanyLogo.jpg по горизонтали расположено по центру, а по вертикали — у нижнего края целевого изображения. Для водяного знака задана прозрачность 100% и отбивка в 10 пикселей. Если водяной знак больше целевого изображения, операция не будет выполнена. Если водяной знак больше целевого изображения, а отбивка равна нулю, водяной знак игнорируется.

Как и прежде, для показа изображения применяется элемент <img> с динамическим атрибутом src.

4. Откройте страницу в браузере:

image

Благодарности

Благодарим Виталия Коробцева, руководителя инновационных проектов “ООО Валькирия”, за неоценимую помощь в подготовке этого руководства.