|
2000 г
Динамическая графика Графика (греч. — письменный, от греч. — пишу)— вид изобразительного искусства, использующий в качестве основных изобразительных средств линии, штрихи, пятна и точки. (Цвет также может применяться, но, в отличие от живописи, здесь он играет вспомогательную роль. При рисовании графикой обычно используют не больше одного цвета (кроме основного черного), в редких случаях— два). Кроме контурной линии в графическом искусстве широко используются штрих и пятно, также контрастирующие с белой (а в иных случаях также цветной, чёрной, или реже— фактурной) поверхностью бумаги— главной основой для графических работ. Сочетанием тех же средств могут создаваться тональные нюансы. Наиболее общий отличительный признак графики— особое отношение изображаемого предмета к пространству, роль которого в значительной мере выполняет фон бумаги (по выражению советского мастера графики В.А.Фаворского,— «воздух белого листа»). в Java сервлетах
Кен МакКрэри,
Перевод на русский © Виктор Смирнов, 2000
Оригинал статьи опубликован на сайте Javable.com
Server-Side Java
Обзор
Как создать графический счетчик посещений? Диаграмму, изображающую загруженность канала до провайдера или количество писем в очереди? Одним словом, как сформировать изображение динамически по запросу пользователя? В своей статье Ken McCrary предлагает варианты Вариант (фр.variante, от лат.varians, родительный падеж variantis — меняющий, изменяющийся) — одна из нескольких редакций какого-либо произведения (литературного, музыкального и т. п.) или официального документа; видоизменение какой-либо части произведения (разночтения отдельных слов, строк, строф, глав). решения этой задачи. (2500 слов)
Графики и диаграммы позволяют облегчить восприятие аналитической информации. Представьте, например, таблицу измерений параметров загруженности канала, проводимых каждые пять минут. Трудно поверить, что у вас хватит терпения просматривать ее хотя бы раз в неделю. Тогда как, соответствующая диаграмма представляется вполне удобоваримой и исчерпывающей. Во многих случаях изображения должны создаваться в реальном времени по запросу пользователя. Потребность в этом может быть обусловлена природой отображаемых данных, в случае, когда данные поступают непрерывно или меняются со временем, или же возможностью значительно уменьшить используемое дисковое пространство. Конечно же, не всегда уместно (технически осуществимо) конструировать изображения динамически, но, там, где это действительно необходимо, использование удачных технологических решений может привести к значительному выигрышу в производительности и качестве сервиса.
Чтение и запись изображений, требования к JDK
Для того чтобы сервлет - приложение, выполняемое на сервере, которое обрабатывает запросы пользователей,- мог динамически создавать изображения, прежде всего, необходим механизм чтения и записи графических файлов. Точнее, сервлет должен уметь отправить полученную картинку в ответ на запрос пользователя. Основные библиотеки (Core API) для Java не предоставляют средств, используя которые можно было бы сохранить полученное в памяти изображение в одном из графических формат Формат— стандартизирование формы построения (и подачи) того или иного предмета (объекта), явления или процесса.ов. Есть библиотеки Sun для Java 1.1 и лицензированные Sun библиотеки для Java 1.2. Поскольку, они расположены в пакете com.sun они не относятся ни к основным библиотекам, ни к стандартным расширениям (standard extension), поэтому использующие их приложения нельзя считать переносимыми (portable). Другими словами, они могут и не работать на виртуальной машине, выпущенной другой компанией. Стоит отметить, что утвержденный запрос Java Specification Request JSR-000015 на стандартное расширение Java 2 содержит описание механизма для чтения и записи графических файлов; когда он будет реализован, можно будет писать переносимые программы, осуществляющие ввод/вывод изображений.
Для этой статьи я подготовил примеры, работающие на платформах Java 1.1 и Java 1.2.
Форматы изображений
Формат GIF - самый распространенный формат графических файлов в Веб. Он широко поддерживается броузерами, в том числе и самыми первыми. К сожалению, написание программ, генерирующих изображения в этом формате, потенциально затруднено патентом на алгоритм сжатия данных. Программ, приведенные в этой статье, создают изображения в формате JPEG и PNG. Формат JPEG выбран, прежде всего, из тех соображений, что реализация Sun Java 1.2 позволяет формировать изображения этого типа без применения дополнительных библиотек. (В примере приложения для JDK 1.1 можно получить файл не только в формате PNG, но и во многих других, в том числе - JPEG и GIF - прим. переводчика)
Одно из различий между форматами JPEG и GIF состоит в том, что алгоритм сжатия данных, используемый в GIF, в отличие от алгоритма, используемого в JPEG, не искажает изображение. Обычно, артефакты в JPEG картинках не сильно заметны. (Следует отметить, что формат JPEG лучше справляется с представлением фотографий, нежели текста, диаграмм или изображений, содержащих тонкие линии и четкие границы цветовых переходов - прим. переводчика) Второй пример применяет формат PNG с алгоритмом сжатия без потери данных и, к тому же, свободный от правовых затруднений.
Архитектура сервлета
Разобьем нашу программу на две части. Первая часть - сервлет - отвечает за обработку HTTP запроса и возвращает клиенту требуемое изображение, если это возможно. Вторая часть, класс, формирующий картинку. Для простоты реализации, в качестве параметра при обращении к сервлету будет передаваться имя используемого класса. Соответствующий Java класс должен реализовывать определенный интерфейс для общения с сервлетом. Приведем описание этого интерфейса:
public interface Интерфейс (от англ.interface— поверхность раздела, перегородка)— совокупность средств, методов и правил взаимодействия (управления, контроля ит.д.) между элементами системы. ImageProducer {
/**
* MIME тип создаваемого изображения.
*
* @return MIME тип изображения.
*/
public String getMIMEType();
/**
* Создает изображение и записывает его в указанный поток.
*
* @param stream Куда писать картинку.
*/
public void createImage(OutputStream stream «Домашний Интернет и Телевидение МТС»— торговая марка, под которой компания «МТС» предоставляет в России услуги кабельного телевидения и широкополосного доступа в интернет.)
throws IOException;
}
Интерфейс Интерфейс (от англ.interface— поверхность раздела, перегородка)— совокупность средств, методов и правил взаимодействия (управления, контроля ит.д.) между элементами системы. ImageProducer содержит метод для определения типа изображения и метод для формирования изображения. Полученная картинка отправляется клиенту.
Следующий код демонстрирует, как сервлет работает с классами, реализующими интерфейс ImageProducer:
ImageProducer imageProducer =
(ImageProducer)
Class.forName(request.getQueryString()).newInstance();
response.setContentType(imageProducer.getMIMEType());
imageProducer.createImage(response.getOutputStream());
Сервлет создает (загружается) класс с именем, указанным в параметрах запроса - части URL справа после "?". Полученный класс приводится к типу ImageProducer. Затем, обращаясь к соответствующим методам, сервлет получает тип и формирует изображение. В случае если нет ошибок, картинка пересылается клиенту.
Приведенный код может вызвать несколько исключений, наиболее распространенные из них: ClassNotFoundException и ClassCastException. Первое вызвано тем, что класс, имя которого передано в качестве параметра запроса, не доступен загрузчику (ClassLoader), второе же тем, что указанный класс не реализует интерфейс ImageProducer. В случае ошибки клиент, конечно же, не получает картинку, и броузер Веб-обозреватель, браузер (от англ.Web browser; вариант броузер— устаревшая форма)— программное обеспечение для просмотра веб-сайтов, то есть для запроса веб-страниц (преимущественно из Сети), их обработки, вывода и перехода от одной страницы к другой. выводит изображение, показывающее, что сервер не ответил на запрос. Программа тестировалась с использованием Java Server Web Development Kit (JSWDK 1.0.1), но вы должны получить аналогичные результаты на большинстве других Веб серверах, поддерживающих Java.
Создание изображений в Java 1.1
Для своего первого примера я подготовил код, который будет работать на платформе Java 1.1. Хотя виртуальные машины JVM 1.2 достаточно распространены, не все могут размещать программы на этой платформе. К сожалению, провайдеры не сильно спешат обновлять виртуальные машины на своих серверах. Как следствие, приходится разрабатывать сервлеты, работающие на платформе Java 1.1. Это не сильно затруднят задачу; тем не менее, есть некоторые сложности, связанные с формированием изображений, которые мы обсудим ниже.
Будем строить круговую диаграмму (pie chart), которую мы, для полноты картины Картина — произведение живописи, обладающее законченным характером (в отличие от эскиза и этюда) и самостоятельным художественным значением. В отличие от фрески или книжной миниатюры, картина не обязательно связана с определенным интерьером или определенной системой декорирования. Состоит из основы (холста, деревянной или металлической доски, картона, бумаги, камня), грунта и красочного слоя. Картина — один из наиболее типичных видов станкового искусства., раскрасим и подпишем. На диаграмме будут изображены напитки, употребляемые разработчиками программного обеспечения. Посмотрим, как можно это сделать.
Для операций ввода/вывода изображений в Java 1.1 Sun предлагает библиотеку Jimi. Sun приобрел ее у небольшой компании. Перед тем, как начать распространять эту библиотеку, компания Sun перенесла классы в пакет com.sun, а в остальном ничего Ничто— категория, фиксирующая отсутствие, небытие определённой сущности, или отсутствие, отрицание бытия вообще, активное начало негации, негативности вообще. не изменила.
Следующие шаги необходимо проделать для формирования PNG изображения с использованием Jimi.
- Создать окно приложения(Frame для получения изображения.
- Использую AWT изображение, создать реализацию класса Graphics.
- Нарисовать картинку с помощью объекта Graphics.
- Создать объект JimiWriter на основе потока данных, передаваемых клиенту.
- Преобразовать изображение в соответствующий формат и отправить его клиенту.
Для формирования и модификации изображений на платформе Java 1.1 необходимо использовать активную AWT компоненту. Как правило, сервлет не должен создавать AWT компоненты, которые обычно используются в приложениях с графическим интерфейсом пользователя. В этом случае, вам нужен графический (AWT) объект для того, что бы получить объект класса Graphics, с помощью которого можно рисовать новые картинки. Придется смириться с маленьким окошком на консоли Веб сервера. Если вам известны способы создания изображения в Java 1.1 без использования AWT компонент, пожалуйста, сообщите мне. Один из возможных вариантов, загрузить с диска сервера заранее подготовленный шаблон, например методом java.awt.Toolkit.createImage(). После того, как вы создали AWT изображение, вы можете получить реализацию класса Graphics и использовать ее для рисования. Имея в своем распоряжении объект Graphics, вы можете закрыть ненужное окно на консоли сервера. Я оставлю этот эксперимент заинтересованным читателям.
Напомню, что для связи с классом, рисующим круговую диаграмму, сервлет использует интерфейс Интерфейс (от англ.interface— поверхность раздела, перегородка)— совокупность средств, методов и правил взаимодействия между элементами системы. ImageProducer. Поэтому наш класс JIMIProducer должен реализовывать этот интерфейс. Прежде всего, создадим AWT окно, AWT изображения и, наконец, объект Graphics:
Frame f = new Frame();
f.setVisible(true;
image = f.createImage(ImageWidth, ImageHeight);
graphics = image.getGraphics();
f.setVisible(false);
Ключевой метод класса JIMIProducer - drawSlice. Получая на входе метку и величину сегмента в градусах, этот метод рисует сегмент диаграммы, раскрашивает его и подписывает. Далее, я расскажу подробней, как это происходит.
Будем заполнять "внутренности Внутренности, внутренние органы (лат.viscera, греч. splanchnon)— органы животных (и человека), лежащие в основном в грудной и брюшной полостях, а именно органыдыхания, пищеварения, мочеполовые и сердечно-сосудистые. Внутренности и органы внутренней секреции изучаются спланхнологией. Область медицины, изучающая заболевания внутренних органов человека, называется внутренней медициной (терапией)." диаграммы по часовой стрелке, начиная с положения "три часа", то есть первую линию проведем из центра к окружности ограничивающей диаграмму в положении часовой стрелки в три часа дня (или ночи, как вам больше нравиться). Отступим по часовой стрелке необходимое количество градусов и нарисуем вторую линию, ограничивающую сегмент диаграммы. И так далее. Приведенный ниже код получает на входе величину сегмента в градусах и рисует границу этого сегмента. Он вызывается последовательно для всех сегментов, при этом предполагается, что в сумме угловые величины составят 360 градусов.
//*************************************************
// Преобразуем угол в радианы
// 1 градус = pi/180 радиан
//*************************************************
double Число двойной точности (Double precision, Double) — компьютерный формат представления чисел, занимающий в памяти две последовательных ячейки (компьютерных слова; в случае 32-битного компьютера — 64 бита или 8 байт). Как правило, обозначает формат числа с плавающей запятой стандарта IEEE 754. Числа с плавающей точкой (двойной/одинарной/четверной точности) поддерживаются сопроцессором (в 80386 выполнен как отдельный модуль, начиная с 80486 является встроенным в главный процессор. Сопроцессор, хотя он сейчас и является частью главного процессора, принято называть FPU — Floating Point Unit, буквально Модуль Плавающей Запятой).theta = degrees * (3.14/180);
currentTheta += theta;
//*************************************************
// Переводим в декартовы координаты
// x = r cos @
// y = r sin @
//*************************************************
double x = Radius * Math.cos(currentTheta);
double y = Radius * Math.sin(currentTheta);
Point mark2 = newPoint(center);
mark2.translate((int)x,(int)y);
graphics.drawLine
(center.x, center.y, mark2.x, mark2.y);
Затем, нужно раскрасить сегменты диаграммы. Для этого можно воспользоваться очень полезным методом fillArc():
graphics.setColor(colors[colorIndex++]);
graphics.fillArc(Inset,
Inset,
PieWidth,
PieHeight,
-1 * lastAngle,
-1 * degrees);
Последняя задача метода drawSlice() нарисовать метки сегментов. Расположение надписи рассчитывается, основываясь на метрике используемого шрифта. Окончательный вариант диаграммы можно посмотреть на рисунке.
Рис. 1. Окончательный вариант круговой диаграммы. (Не все броузеры показывают файлы формата PNG, поэтому здесь мы поставили GIF файл.)
Создание изображений в Java 1.2
Практически все интересуются сейчас курсами акций на бирже. Нарисуем (всем на радость Радость— одна из основных положительных эмоций человека, внутреннее чувство удовлетворения, удовольствия и счастья. Является положительной внутренней мотивацией человека. Радость считается противоположной грусти, печали. Радость может отделяться от удовлетворения и удовольствия и даже противопоставляться им. Радость, как более «высокое» чувство, в противопоставлении «душа»-«тело» связывается с душой, а удовольствие, как всего лишь «ощущение, реакция»— с телом.) на нашей диаграмме курс акций компании Юридическое лицо— созданная и зарегистрированная в установленном законом порядке организация, которая имеет в собственности, хозяйственном ведении или оперативном управлении обособленное имущество и отвечает по своим обязательствам этим имуществом, может от своего имени приобретать и осуществлять имущественные и личные неимущественные права, нести обязанности, быть истцом и ответчиком в суде. Юридические лица должны иметь самостоятельный баланс или смету. Sun за одну из недель марта.
Для создания изображений в формате JPEG используется класс com.sun.image.codec.jpeg.JPEGImageEncoder. Повторюсь, что принадлежность к пакету com.sun означает, что этот класс не является частью основного API и к нему относятся все соответствующие предупреждения.
Класс JPEGImageEncoder "понимает", как перекодировать изображение java.awt.image.BufferedImage, так что его и будем использовать. Для создания класса BufferedImage нужно указать требуемые размеры изображения. После создания, класс BufferedImage предоставляет класс ava.awt.Graphics2D, который можно использовать для рисования на соответствующей классу BufferedImage картинке. Все просто? Итак, основные шаги, необходимые для формирования изображения в формате JPEG:
- Создаем класс JPEGImageEncoder, предоставляя ему поток OutputStream данных передаваемых клиенту.
- Создаем класс BufferedImage необходимых размеров.
- Используем реализацию класса Graphics2D, предоставляемую классом BufferedImage, для рисования диаграммы.
- С помощью полученного ранее класса JPEGImageEncoder перекодируем нарисованное изображение в формат JPEG и пишем его в поток, отправляемый клиенту.
Обсудим некоторые детали рисования с использованием Graphics2D.
Для создания графика курса акций нужно, собственно, нарисовать несколько линий. Пакет Java 2D, java.awt.geom, содержит все необходимые для этого классы. Абстрактный класс Line2D определяет отрезок Отрезком может называться одно из двух близких понятий в геометрии и математическом анализе. прямой. Он имеет две реализации, отличающиеся типом используемых координат. Класс Line2D.Double применяет примитивный тип double, а класс Line2D.Float - вещественные числа с плавающей точкой. Высокая точность совершенно излишня для нашего графика, но я не буду экономить и создам отрезки прямой классом Line2D.Double.
Приведем, в качестве примера, участок программы, рисующий горизонтальную ось графика:
horAxis = new Line2D.Double(HorzInset,
ImageHeight - VertInset,
ImageWidth - HorzInset,
ImageHeight - VertInset);
graphics.draw(horAxis);
Горизонтальная ось строится с небольшим отступом от границы Граница— реальная или воображаемая линия, определяющая пределы какого-либо субъекта или объекта и разделяющая этот субъект или объект от других. экрана, предоставляя место для разметки. После создания вы рисуете линю, обращаясь к методу draw() объекта Graphics2D. Напомню, что вы получили его от реализации класса BufferedImage. Класс Graphics2D содержит методы для рисования графических примитивов, для наших целей более чем достаточно. На рисунке 2 приведен окончательный вариант графика.
Рис. 2. Окончательный вариант графика курса акций.
Производительность
Плохая производительность - одно из основных обвинений противников Java. Я не разделяю этой позиции. Я убежден в том, что от можно добиться хорошей производительности для программы,написанной на Java, динамически создающей изображения. Как разработчик программного обеспечения, я могу дать вам совет: если вас не устраивает производительность, покупайте более совершенные компьютеры.
Заключение
В этой статье я показал, как можно создавать в программах на языке Java простые изображения, и воспользовался этой техникой для написания сервлета, формирующего картинку по запросу пользователя. Эта технология имеет огромное количество приложений, ограниченное, разве что, рамками воображения. Два вопроса стоит иметь в виду, разрабатывая приложения на основе изложенных идей: производительность алгоритма, создающего изображение, и ограничение пропускной способности Способности— это индивидуальные свойства личности, являющиеся субъективными условиями успешного осуществления определённого рода деятельности. Способности не сводятся к имеющимся у индивида знаниям, умениям, навыкам. Они обнаруживаются в быстроте, глубине и прочности овладения способами и приёмами некоторой деятельности и являются внутренними психическими регулятивами, обусловливающими возможность их приобретения. В отечественной психологии наибольший вклад в экспериментальные исследования способностей внес Б.М.Теплов. канала связи сервера. Для решения последней проблемы, очевидно, нужно максимально уменьшить размер картинки, в первом случае применять стандартные методы оптимизации приложений.
Об авторе
KenMcCrary, сертифицированный Sun Java developer, живет в Нью-Йорке, Research Triangle Park. Он работал над большим количеством Java проектов. Вы можете посетить его сайт http://www.KenMcCrary.com
Ресурсы
- Оригинальные исходные тексты:
http://www.javaworld.com/jw-05-2000/servlets/Servlets.zip
- Слегка подправленный вариант с комментариями на русском:
is.zip
- Круговая диаграмма в формате PNG:
http://www.javaworld.com/jw-05-2000/images/piechart.png
- Информация по зопросу JSR-00015:
http://java.sun.com/aboutJava/communityprocess/jsr/jsr_015_iio.html
- нформация по пакету JPEG:
http://java.sun.com/products/jdk/1.2/docs/guide/2d/api-jpeg/ com/sun/image/codec/jpeg/package-summary.html
- Информация по библиотеке Jimi:
http://java.sun.com/products/jimi/
- Информация по PNG:
http://www.w3.org/Graphics/PNG/
Reprinted with permission from the March 2000 edition of JavaWorld magazine Magazine— британская рок-группа, образованная в 1977 году в Манчестере, Англия, Ховардом Девото после ухода из Buzzcocks, и считающаяся одной из самых новаторских и влиятельных в новой волне. Magazine выпустили четыре студийных альбома и не имели оглушительного коммерческого успеха, но, соединив панк- и арт-рок с элементами экспериментального рока, положили начало новой, постпанковской ветви музыкального развития. Дебютный сингл группы «Shot By Both Sides» многие специалисты называют классическим; дебютный альбом Real Life вошёл в список «1000 Albums To Hear Before You Die»..
Copyright © ITworld.com, Inc., an IDG Communications company.
View the original article at: http://www.javaworld.com/javaworld/ jw-05-2000/jw-0505-servlets.html
|