

1036
Часть
11.
Библиотека
Java
этому
он
был
пригоден
и
для
Интернета.
Каждое
изображение
формата
GIF
может
содержать
не
более
256
цветов.
В
связи
с
этим
ограничением в
1995
году
ведущие
разработчики браузеров включили в |
них поддержку изображений формата JPEG. |
|||
Формат JPEG был разработан группой специалистов по |
фотографии для хранения |
|||
полутоновых изображений с |
полным |
спектром цветов. |
Если правильно сформи |
|
ровать подобное изображение, |
оно будет воспроизводиться с более высокой сте |
|||
пенью точности и уплотняться |
более компактно, чем аналогичное изображение |
|||
формата GIF. Имеется также |
формат |
файлов изображений PNG, который являет |
||
ся разновидностью формата |
GIF. Как |
правило, в прикладных программах вряд ли |
||
придется обращать особое внимание |
на используемый |
формат изображений, по |
||
скольку классы изображений в |
Java абстрагируют все отличия в форматах благо |
|||
даря ясно определенному интерфейсу. |
|
Основы работы с изображениями: создание, загрузка и отображение
В процессе обработки изображений обычно выполняются в основном три опе рации: формирование изображения, его загрузка и воспроизведение. Для обраще ния к изображениям, хранящимся в оперативной памяти, а также к изображениям,
загружаемым
из
внешних
источников
данных,
в
Java
используется
класс
Image.
Таким образом, в Java жения и его загрузки, водить изображения.
предоставляются способы создания нового объекта изобра а также функциональные средства, позволяющие воспроиз Все эти средства будут рассмотрены далее по очереди.
Создание
объекта класса
Image
На |
первый |
взгляд может |
показаться, |
что для |
формирования |
|
в оперативной памяти требуется примерно такая |
строка кода: |
|||||
Image |
test = |
new Image(200, |
100); 11 |
Ошибка |
- |
не сработает! |
изображения
его
Но на самом деле это не так. Любое изображение предназначено для можно было воспроизвести на экране монитора, а класс Image не
того, чтобы располага
ет
достаточными
сведениями
о
среде
для
создания
подходящего
формата данных,
выводимых
на
экран.
Поэтому
в
класс
Component
из
пакета
j
ava.
awt
включен
метод
createimage
(),
предназначенный
для
создания
объектов типа
Image.
(Напомним,
что
все
компоненты
из
библиотеки
АWT
являются
производными
от
класса Component, поэтому все они поддерживают метод
Метод createimage () имеет следующие общие формы:
createimage
()
.)
Image
Image
createlmage(ImageProducer поставщик_изображений) |
|
createlmage(int ширина, |
int высота) |
В
первой
форме
данного
метода
возвращается
изображение,
сформированное
указанным
поставщиком_изображений,
который
представляет
собой
объект
класса,
реализующего
интерфейс
ImageProducer.
(О
поставщиках изображений


1038
Часть
11.
Библиотека
Java
его
загрузки.
Если
же
наблюдатель
изображения
не
требуется,
то
в
качестве
параме
тра объект_изображения можно указать пустое значение null.
Загрузить и воспроизвести изображение методами get Image ()
и
drawinage
()
совсем
не
трудно.
Ниже
приведен
пример
прикладной
программы,
загружающей
и
отображающей
отдельное
изображение
.
В
этой
прикладной
программе
загружа
ется
файл
изображения
Lilies.
jpg,
но
для
данного
примера
можно
взять
любой
другой
файл
изображения
формата
GIF,
JPG
или
PNG
при
условии,
что
он
будет
на
ходиться
в
том
же
каталоге,
что
и
НТМL-файл,
содержащий
данную
прикладную
программу.
Пример
выполнения
этой
программы
приведен
на
рис.
27.
1.
Рис.
27.1.
Воспроизведение
загруженного
изображения
в
окне
прикладной
программы
SimpleimageLoad
11
Продемонстрировать
загрузку
и
отображение
изображений
import |
java.awt.*; |
|
|
import |
java.awt.event.*; |
|
|
import |
javax.imageio.*; |
|
|
import |
java.io.*; |
|
|
puЬlic |
class SimpleimageLoad |
extends |
Frame |
Image |
img; |
|
|
{
puЬlic |
Simp leimageLoad() |
||
try |
{ |
|
= new |
File |
imageFile |
File("Lilies.jpg");
11 |
загрузить изображение |
|
|
|
img |
= |
ImageIO.read(imageFile); |
||
catch |
(IOException ехс) |
{ |
|
|
System.out.println("Cannot |
load |
|||
System.exit(O); |
|
|
image
file.");






1044
} ) ;
Часть
11.
Библиотека
Java
puЬlic void paint(Graphics g) g.drawimage(img, getinsets()
{ .left,
getinsets()
.top,
null);
puЬlic static void main(String[J MemoryimageGenerator appwin =
args) |
{ |
new MemoryimageGenerator(); |
appwin. appwin.
setSize(new Dimension(400, |
400)); |
setтi t le ( "MemoryimageGenerator") ; |
appwin.setVisiЬle(true);
Данные
для
нового
объекта
типа
MemoryimageSource
создаются
в
мето
де
ini
t
().
Массив
целых
чисел
предназначен
для
хранения
значений
пикселей;
данные
формируются
во
вложенных
циклах
for,
где
значения
r,
g
и
Ь
оказыва
ются
смещенными
на
один
пиксель
в
массиве
pixels.
В
конце
данной
приклад
ной
программы
вызывается
метод
createimage
()
с
новым
экземпляром
класса
MemoryimageSource,
созданным
из
исходных
данных
пикселей
в
качестве
его
параметра.
На
рис.
27.3
показано
изображение
в
момент
запуска
прикладной
про
граммы.
(В
цвете
оно
выглядит
намного
привлекательнее.)
в
Рис. 27.3. Пример формирования изображения
окне прикладной программы MemoryimageGenerator
ИнтepфeйcimageConsumer
Интерфейс
ImageConsumer
предназначен
для
объектов,
которые
должны
по
лучать
данные
пикселей
из
изображений
и
предоставлять
их
в
качестве
другого

Глава
27. Изображения
1045
вида
данных.
Таким
образом,
этот
интерфейс
является
прямой
противополож
ностью
описанного
ранее
интерфейса
ImageProducer.
Объект
класса,
реали
зующего
интерфейс
ImageConsumer,
служит
для
создания
массивов
типа
int
или
byte,
представляющих
пиксели
из
объекта
типа
Image.
Ниже
будет
рассмо
трен
класс
PixelGrabber,
предоставляющий
простую
реализацию
интерфейса
ImageConsumer.
Класс
PixelGrabber
В
пакете
j
ava.
lang.
image
определен
класс
PixelGrabber,
который
яв
ляется
прямой
противоположностью
классу
MemoryimageSource.
Вместо
того
чтобы
формировать
изображение
из
массива
значений
пикселей,
он
принимает
существующее
изображение
и
захватывает
в
нем
массив
пикселей.
Чтобы
вос
пользоваться
классом
PixelGrabber,
необходимо
создать
сначала
массив
целых
чисел достаточного
размера
для
хранения
в
нем
данных
отдельных
пикселей,
а за
тем
получить
экземпляр
класса
PixelGrabber,
передав
его
конструктору
прямо
угольную
область,
которую
необходимо
захватить.
И
наконец,
для
этого
экземпля
ра
следует вызвать метод grabPixels ().
Ниже приведен конструктор класса Рixe 1Gr abber,
применяемый
далее
в
этой
главе.
PixelGrabber(Image
объект_изображения,
int
слева,
int
сверху,
int
ширина,
int
высота,
int int
pixel[], |
int смещение, |
ширина_строки_развертки) |
Здесь
параметр
объект_изображения
обозначает
тот
объект, пиксели
кото
рого
должны
быть
захвачены;
параметры
слева
и
сверху
-
верхний
левый
угол
прямоугольной
области;
а
параметры
ширина
и
высота
-
размеры
прямоуголь
ной
области, из
которой
должны
быть получены
пиксели
изображения.
Эти
пиксе
ли
должны
храниться
в
массиве
pixel,
начиная
с
указанного
смещения.
Ширина
строки
развертки,
которая
нередко
соответствует
ширине
изображения,
обознача
ется параметром ширина_строки_развертки.
Метод grabPixels () определяется следующим
образом:
boolean boolean
grabPixels() |
throws InterruptedException |
grabPixels(long миллисекунды) |
|
throws InterruptedException |
В
обеих
формах
возвращается
логическое
значение
true
при
удачном
завер
шении
данного метода,
а
иначе
-
логическое
значение
false.
Во
второй
форме
параметр
миллисекунды
определяет
промежуток
времени,
в
течение
которого
метод
будет
ожидать
получения
пикселей.
В
обеих
формах
генерируется
исключе
ние
типа
InterruptedException,
если
выполнение
данного
метода
прерывает
ся другим потоком исполнения.
Ниже приведен пример, в котором
производится
захват
пикселей
в
изображе
нии
с
последующим
построением
гистограммы
яркости
пикселей.
Гистограмма
представляет
собой
простой
подсчет
пикселей,
имеющих
определенный
уровень


|
|
|
|
|
|
|
|
|
|
|
|
Глава |
27. |
Изображения |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} ) ; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
puЬlic |
void |
paint(Graphics |
g) |
|
|
|
|
|
||||||
// Get |
the border |
/ header |
insets. |
|
|
|
||||||||
ins |
= |
getinsets(); |
|
|
|
|
|
|
|
|
||||
g.drawimage(img, |
ins.left, |
in s.top, |
null); |
|
|
|||||||||
int |
х |
= (iw |
- |
256) |
/ |
2; |
|
|
|
|
|
|
||
int |
l asty |
= |
ih |
- |
ih |
|
* hist [О) |
/ max_hist; |
|
|
||||
for |
(int |
i=O; |
i <256; |
i++, |
х++) |
|
|
|
||||||
int |
у = |
ih |
- |
ih |
* |
|
hist[i) |
/ |
max_hist; |
|
|
|||
g.setColor(new |
Color(i, |
i, |
i)); |
1, ih-y); |
|
|
||||||||
g.fillRect(x+ins.left, |
y+ins.top, |
|
|
|||||||||||
g.setColor(Color.red); |
|
|
lasty+ins.t o p, |
|
|
|||||||||
g.drawLine( (x-l)+ins.left, |
|
|
||||||||||||
|
|
|
|
x+ins.left, |
y+ins.top); |
|
|
|
||||||
lasty = |
у; |
|
|
|
|
|
|
|
|
|
|
|
1047
puЬlic static void HistoGrab appwin
main(String[] |
args) |
new HistoGrab(); |
appwin.setSize(new Dimension(400, appw in. setTitle(" Hi stoGrab "); appwin.setVisiЬle(true);
380));
На рис. 27.4 приведен пример вывода
прикладной программы HistoGrab.
гистограммы
на
фоне
изображения
в
окне
Рис.
27.4.
Пример
вывода
гистограммы
на
фоне
изображения
в
окне
прикладной
программы
HistoGraЬ





















1068
Часть
11.
Библиотека
Java
время вызова метода, то исполнение вызывающего до тех пор, пока не будет получено разрешение.
Чтобы освободить разрешение, следует вызвать
потока будет приостановлено метод release ().Ниже при
ведены
общие
формы
этого
метода.
void void
release () release(int
число)
В
первой
форме
освобождается
одно
разрешение,
а
во
второй
-
количество
разрешений, обозначаемое параметром число.
Чтобы воспользоваться семафором для управления
доступом
к
ресурсу,
каж
дый
поток
исполнения,
которому
требуется
этот
ресурс,
должен
вызвать
метод
acquire
(),прежде
чем
обращаться
к
ресурсу.
Когда
поток
исполнения
завершает
пользование ресурсом,
он должен
вызвать
метод
release
(),чтобы
освободить
ресурс.
В
приведенном
ниже
примере
программы
демонстрируется
применение
семафора.
11
Простой
пример
применения
семафора
import
java.util.concurrent.*;
class
SemDemo |
{ |
puЬlic static void Semaphore sem =
main(String args[J) new Semaphore(l);
new new
IncThread(sem,
DecThread(sem,
"А") "В")
.start(); .start();
11 |
Общий |
ресурс |
|
class Shared |
{ |
||
|
static |
int |
count |
О;
11 |
Поток исполнения, |
увеличивающий |
значение счетчика |
|
class IncThread |
implements RunnaЫe |
{ |
||
|
String name; |
|
|
|
|
Semaphore sem; |
|
|
|
на единицу
IncThread(Semaphore |
||
sem |
= |
s; |
name |
|
= n; |
s,
String
n)
{
puЬlic
void
run()
{
System.out.println("Зaпycк потока |
" |
|
try |
{ |
|
11 |
сначала получить разрешение |
|
System.out.println("Пoтoк" + name |
+ |
name); |
|
+ |
"ожидает |
разрешения"); |








