Модель обработки "поставщик-потребитель"
Очень часто изображение перед выводом на экран подвергается обработке: меняются цвета отдельных пикселов или целых участков изображения, выделяются и преобразуются какие-то фрагменты изображения.
В библиотеке AWT применяются две модели обработки изображения. Одна модель реализует давно известную в программировании общую модель "поставщик-потребитель" (Producer-Consumer). Согласно этой модели один объект, "поставщик", генерирует сам или преобразует полученную из другого места продукцию, в данном случае, набор пикселов, и передает другим объектам. Эти объекты, "потребители", принимают продукцию и тоже преобразуют ее при необходимости. Только после этого создается объект класса image и изображение выводится на экран. У одного поставщика может быть несколько потребителей, которые должны быть зарегистрированы поставщиком. Поставщик и потребитель активно взаимодействуют, обращаясь к методам друг друга.
В AWT эта модель описана В двух интерфейсах: ImageProducer И ImageConsumer пакета j ava. awt. image.
Интерфейс ImageProducer описывает пять методов:
addConsumer(ImageConsumer ic)
— регистрирует потребителя ic; removeConsumer (ImageConsumer ic) — отменяет регистрацию;
isConsumer( ImageConsumer ic)
— логический метод, проверяет, зарегистрирован ли потребитель ic;
startProduction (ImageConsumer ic)
— регистрирует потребителя ic И НЭ-чинает поставку изображения всем зарегистрированным потребителям;
requestTopDownLeftRightResend (ImageConsumer ic)
— используется потребителем для того, чтобы затребовать изображение еще раз в порядке "сверху-вниз, слева-направо" для методов обработки, применяющих именно такой порядок.
С каждым экземпляром класса image связан объект, реализующий интерфейс ImageProducer. Его можно получить методом getSource () класса Image.
Самая простая реализация интерфейса ImageProducer — класс метогу-imagesource — создает пикселы в оперативной памяти по массиву байтов или целых чисел. Вначале создается массив pix, содержащий цвет каждой точки. Затем одним из шести конструкторов создается объект класса
MemoryimageSource.
Он может быть обработан потребителем или прямо преобразован в тип Image методом
createlmage ().
В листинге 15.1 приведена простая программа, выводящая на экран квадрат размером 100x100 пикселов. Левый верхний угол квадрата синий, левый нижний — красный, правый верхний — зеленый, а к центру квадрата цвета перемешиваются.
Листинг 15.1.
Изображение, построенное по точкам
import java.awt.*;
import j ava.awt.event.*;
import java.awt.image.*;
class InMemory extends Frame {
private int w = 100, h = 100;
private int[] pix = new int[w * h];
private Image img;
InMemory(String s)( super(s);
int
i =
0;
for (int у = 0; у < h; y++){
int red = 255 * у / (h - 1);
for (int x = 0; x < w; x++){
int green = 255 * x / (w — 1) ;
pix[i++] = (255 << 24)|(red << 16)|(green << 8)| 128; } }
setSize(250, 200);
setVisible(true);
}
public vqid paint(Graphics gr){
if (img == null)
img = createlmage(new MemoryImageSource<w, h, pix> 0, w));
gr.drawlmage(img, 50, 50, this);
}
public static void main(String[] args){
Frame f= new InMemory(" Изображение в памяти");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev){
System.exit (0);
}
});
}
}
В листинге 15.1 в конструктор класса-поставщика MemoryimageSource (w, h, pix, о, w) заносится ширина w и высота h изображения, массив pix, смещение в этом массиве о и длина строки w. Потребителем служит изображение img, которое создается методом createlmage () и выводится на экран методом drawlmage(img, 50, 50, this). Левый верхний угол изображения img располагается в точке (50, 50) контейнера, а последний аргумент this показывает, что роль imageObserver играет сам класс InMemory. Это заставляет включить в метод paint о проверку if (img == null), иначе изображение будет постоянно перерисовываться. Другой способ избежать этого — переопределить метод imageupdate (), о чем говорилось в
главе 14,
просто написав В нем return true.
Рис. 15.1 демонстрирует вывод, этой программы.
Рис. 15.1.
Изображение, созданное по точкам
Интерфейс imageConsumer описывает семь методов, самыми важными из которых являются два метода setPixeis (). Первый:
setPixels(int x, int y, int width, int height, ColorModel model, byte[] pix, int offset, int scansize);
Второй метод отличается только тем, что массив pix содержит элементы типа int.
Рис. 15.2
. Классы, реализующие модель "поставщик-потребитель"
К этим методам обращается поставщик для передачи пикселов потребителю. Передается прямоугольник шириной width и высотой height с заданным верхним левым углом (х, у), заполняемый пикселами из массива pix, начиная с индекса offset. Каждая строка занимает scansize элементов массива pix. Цвета пикселов определяются в цветовой модели model (обычно это модель RGB).
На рис. 15.2 показана иерархия классов, реализующих модель "поставщик-потребитель".