Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
101
Добавлен:
30.03.2021
Размер:
42.12 Mб
Скачать

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);

 

+

"ожидает

разрешения");

Соседние файлы в папке Лабораторные работы (Объектно-ориентированное программирование (ООП))