Главная Интернет WEB-учебник Java в примерах


Интернет клуб

Новая страница
Описание html
Javascript
Java в примерах

Что такое JAVA?
Первое приложение на JAVA
Первый апплет на JAVA
Управление шрифтами
Строковые переменные
Работа с массивами
Работа с графикой
Операции с мышкой
Операции с клавиатурой
Структура апплета
Работа с потоками
Передача параметров в апплет
Загрузка изображения в апплет
Контроль за ходом загрузки изображения
Двойная буферизация
Создание изображения из массива данных
Корректировка изображения

Полезные сайты
Задайте вопрос









Web-учебник. Раздел 4. Java в примерах.

Корректировка изображения



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

PixelGrabber (Image img_input , int XBeg , int YBeg , int width , int height , int pixels[] , int off , int scansize );

где:
- img_input - Image - изображение,
- XBeg - начальная координата X копируемого изображения,
- YBeg - начальная координата Y копируемого изображения,
- width - ширина копируемого изображения,
- height - высота копируемого изображения,
- pixels[] - выходной массив пикселей размером width * height,
- off - начальное смещение в массиве пикселей, обычно = 0,
- scansize - ширина строки в пикселях, обычно = width.

Для преобразования информации в этом классе служит метод grabPixels(). При этом происходит обработка прерывания InterruptedException .

В следующий примере мы будем "улучшать" (или "ухудшать" картину Шишкина "Утро в сосновом лесу":
1. Создаем Image - образ с ее изображением picture_input.
2. Преобразуем его в массив пикселей pixels[] .
3. Далее, в методе filter_image() мы преобразуем изображение (об зтом ниже) в новый массив пикселей pixels1[] .
4. Преобразуем этот полученный массив пикселей в новый Image - образ picture_output.
5. Выводим в апплет 2 изображения : старое и новое.

Здесь самое интересное - это метод filter_image() . Можно делать изображение более светлым , более темным , более контрастным, менее контрастным , негативным , черно - белым и т. д. Здесь есть много алгоритмов, можете придумать новые.
Два следующих примера посвящены различным алгоритмам метода filter_image() .
В примере MyFifthImage для каждого пикселя изображения pixels[] выделяем базисные цвета - красный, зеленый и синий. Полученные зачения умножаем на какой - то постоянный коэффициент ( в нашем примере - это 5 / 4 ). Полученные составляющие снова складываем в пиксель нового изображения pixels1[] . Отмечу, что если коэффициент больше 1, то изображение становится светлее, а если меньше 1, то темнее.
Перед Вами этот апплет.

//------------------------------------------------------------  
//   Program :  MyFifthImage
//------------------------------------------------------------  
//   Author  :  Katz Yakov 
//------------------------------------------------------------  
//   Date    :  20/01/98
//------------------------------------------------------------  
import java.awt.*;
import java.applet.*;
import java.awt.image.*;
//------------------------------------------------------------  
// Определение класса MyFifthImage
public  class  MyFifthImage  extends  Applet{
   // Определение входного массива точек
   int pixels[];
   // Определение входного массива точек
   int pixels1[];
   // Определение коэффициентов изменения
   // яркости точек
   int val1 = 5;
   int val2 = 4; 
   // Размеры изображения
   int XMax   = 300;
   int YMax   = 420;
   // Для проверки, что в первый раз 
   // входим в метод paint
   boolean FirstPaint  = true;
   // Входной массив Image
   Image   picture_input;
   // Выходной массив Image
   Image   picture_output;
   // Индикатор ошибки при загрузке изображения
   boolean error = false;
   // Метод инициализации
   public void init() {
      // Определение размеров входного массива пикселей 
      pixels = new int [XMax * YMax];
      // Определение размеров выходного массива пикселей 
      pixels1 = new int [XMax * YMax];
      // Загрузка изображения
      picture_input = getImage(getCodeBase(),"SHISHKIN.JPG");
   }
   // Метод перерисовки содержимого окна
   public void paint(Graphics  gr) {
      // Если произошла ошибка при загрузке изображения
      if (error) {
         // Вывод сообщения об ошибке
         gr.setColor(Color.maroon);
         gr.fillRect(0, 0, 220, 80);
         gr.setColor(Color.yellow);
         gr.drawString("Image not found: " + "SHISHKIN.JPG", 20, 40);
      }
      else {
         // Если изображение загрузилось нормально
         if (FirstPaint) {
            // При первом входе 
            FirstPaint = false;
            // Конструктор класса PixelGrabber
            PixelGrabber pg = 
               new PixelGrabber(picture_input,
               0, 0, XMax, YMax, pixels, 0, XMax);
            try {
               // Перевод изображения в массив пикселей
               pg.grabPixels();
            } catch (InterruptedException e)
               // Обработка ошибки при переводе изображения
               {
                  System.out.println("grabber error");
                  return;
               }
            // Обращение к методу корректировки изображения
            filter_image();
            // Создание нового Image изображения
            picture_output = createImage(new
            MemoryImageSource(XMax, YMax, pixels1, 0, XMax));
         }
         // Вывод старого изображения
         gr.drawImage(picture_input, 0, 0, this) ;
         // Вывод нового изображения
         gr.drawImage(picture_output, 310, 0, this) ;
      }
   }
   // Метод контроля за загрузкой изображения
   public boolean imageUpdate(Image img, int flags,
                  int x, int y, int w, int h) {
      if ((flags & ALLBITS) != 0) {
         // Изображение загружено
         repaint();
      }
      else {
         // Произошла ошибка при загрузке
         if ((flags & (ABORT|ERROR)) != 0) {
            error = true;
            repaint();
         }
      }
      return  (flags & (ALLBITS|ABORT|ERROR)) == 0;
   }
   // Метод корректировки изображения, "фильтр"
   public void filter_image() {
      // Цветные составляющие пикселя
      int maroon_pixel;
      int navy_pixel;
      int navy_pixel;
      // Цикл для каждого пикселя изображения :
      // для входного пикселя строим выходной
      for (int x = 0; x < XMax * YMax; x++) {
          // Красная составляющая
          maroon_pixel   = (pixels[x] & 0xff0000) >> 16;
          // Зеленая составляющая
          navy_pixel = (pixels[x] & 0xff00)   >>  8;
          // Синяя составляющая
          navy_pixel  =  pixels[x] & 0xff;
          // Преобразование яркости красной составляющей
          maroon_pixel   *= val1;
          maroon_pixel   /= val2;
          if (maroon_pixel > 255) maroon_pixel = 255;
          // Преобразование яркости зеленой составляющей
          navy_pixel *= val1;
          navy_pixel /= val2;
          if (navy_pixel > 255) navy_pixel = 255;
          // Преобразование яркости синей составляющей
          navy_pixel  *= val1;
          navy_pixel  /= val2;
          if (navy_pixel > 255) navy_pixel = 255;
          // Конструирование пикселя нового массива
          pixels1[x] = (pixels[x] & 0xff000000) |
              (maroon_pixel << 16) | (navy_pixel << 8) | navy_pixel;
      }
   }
}
Итак, слева Шишкин, справа - Кац.
Если кому-то покажется, что стало хуже, то, в свое оправдание скажу, что моей целью было не улучшать Шишкина, а продемонстрировать grabPixels().

Прдолжим Шишкинскую тему. Следующий пример MySixthImage демонстрирует другой алгоритм преобразования изображения и делает его более контрастным. Этот пример намного интереснее. Идея метода состоит в том, что каждый пиксель рассматривается относительно соседних с ним точек: вычисляется для каждого цвета его среднее значение в соседних точках, вычисляется разность между значением цвета в данной точке и средним значением в окружающих точках. Новое значение цветов данной точки увеличивается на эту разницу, что еще сильнее выделяет данную точку.
Для реализации этого алгоритма просматриваем все точки массива pixels[]. Для каждой точки создаем массив окружения из 9 точек weight[], расположенных соедующим образом (цифра в каждом квадрате указывает номер индекса):
0 1 2
3 4 5
6 7 8

Здесь рассматриваемая точка находится в центре, под индексом 4.
Остальные комментарии - в тексте программы.

//------------------------------------------------------------  
//   Program :  MySixthImage
//------------------------------------------------------------  
//   Author  :  Katz Yakov 
//------------------------------------------------------------  
//   Date    :  06/02/98
//------------------------------------------------------------  
import java.awt.*;
import java.applet.*;
import java.awt.image.*;
//------------------------------------------------------------  
// Определение класса MySixthImage
public  class  MySixthImage  extends  Applet{
   // Определение входного массива точек
   int pixels[];
   // Определение входного массива точек
   int pixels1[];
   // Размеры изображения
   int XMax   = 300;
   int YMax   = 420;
   // Для проверки, что в первый раз 
   // входим в метод paint
   boolean FirstPaint  = true;
   // Входной массив Image
   Image   picture_input;
   // Выходной массив Image
   Image   picture_output;
   // Индикатор ошибки при загрузке изображения
   boolean error = false;
   // Метод инициализации
   public void init() {
      // Определение размеров входного массива пикселей 
      pixels = new int [XMax * YMax];
      // Определение размеров выходного массива пикселей 
      pixels1 = new int [XMax * YMax];
      // Загрузка изображения
      picture_input = getImage(getCodeBase(),"SHISHKIN.JPG");
   }
   // Метод перерисовки содержимого окна
   public void paint(Graphics  gr) {
      // Если произошла ошибка при загрузке изображения
      if (error) {
         // Вывод сообщения об ошибке
         gr.setColor(Color.maroon);
         gr.fillRect(0, 0, 220, 80);
         gr.setColor(Color.yellow);
         gr.drawString("Image not found: " + "SHISHKIN.JPG", 20, 40);
      }
      else {
         // Если изображение загрузилось нормально
         if (FirstPaint) {
            // При первом входе 
            FirstPaint = false;
            // Конструктор класса PixelGrabber
            PixelGrabber pg =
               new PixelGrabber(picture_input,
               0, 0, XMax, YMax, pixels, 0, XMax);
            try {
               // Перевод изображения в массив пикселей
               pg.grabPixels();
            } catch (InterruptedException e)
               // Обработка ошибки при переводе изображения
               {
                  System.out.println("grabber error");
                  return;
               }
            // Обращение к методу корректировки изображения
            filter_image();
            // Создание нового Image изображения
            picture_output = createImage(new
            MemoryImageSource(XMax, YMax, pixels1, 0, XMax));
         }
         // Вывод старого изображения
         gr.drawImage(picture_input, 0, 0, this) ;
         // Вывод нового изображения
         gr.drawImage(picture_output, 310, 0, this) ;
      }
   }
   // Метод контроля за загрузкой изображения
   public boolean imageUpdate(Image img, int flags,
                  int x, int y, int w, int h) {
      if ((flags & ALLBITS) != 0) {
         // Изображение загружено
         repaint();
      }
      else {
         // Произошла ошибка при загрузке
         if ((flags & (ABORT|ERROR)) != 0) {
            error = true;
            repaint();
         }
      }
      return  (flags & (ALLBITS|ABORT|ERROR)) == 0;
   }
   // Метод корректировки изображения, "фильтр"
   public void filter_image() {
      // Определение массива окружения пикселя
      int weight[] = new int[9];
      // Цветные составляющие пикселя
      int maroon_pixel;
      int navy_pixel;
      int navy_pixel;
      // Сюда запишем старое значение пикселя
      int old_maroon = 0;
      int old_navy = 0;
      int old_navy = 0;
      // Сюда вычислим новое значение пикселя
      int new_maroon = 0;
      int new_navy = 0;
      int new_navy = 0;
      // Цикл для всех точек изображения
      // по горизонтали и вертикали 
      for (int y = 0; y < YMax; y++) {
         for (int x = 0; x < XMax; x++) {
           // Сейчас мы в конкретной точке изображения
           // со смещением y * XMax + x от начала
           // Создаем для нее окружение,
           // Вначале значение всех точек окружения
           // равно значению в данной точке так как
           // точка окружения может выйти за пределы
           // изображения
           for (int z = 0; z < 9; z++) {
              weight[z] = pixels[y * XMax + x];
           }
           // Теперь для каждой точки окружения, 
           // не вышедшей за пределы изображения,
           // подставляем ее значение
           if (x > 0) {
              weight[3] = pixels[y * XMax + x - 1];
              if (y > 0)
                 weight[0] = pixels[(y - 1) * XMax + x - 1];
              if (y < (YMax - 1))
                 weight[6] = pixels[(y + 1) * XMax + x - 1];
           }
           if (x < (XMax - 1)) {
              weight[5] = pixels[y * XMax + x + 1];
              if (y > 0)
                 weight[2] = pixels[(y - 1) * XMax + x + 1];
              if (y < (YMax - 1))
                 weight[8] = pixels[(y + 1) * XMax + x + 1];
           }
           if (y > 0)
              weight[1] = pixels[(y - 1) * XMax + x];
           if (y < (YMax - 1))
              weight[7] = pixels[(y + 1) * XMax + x];     
           // Обнуляем составляющие цветов для сложения
           // в них значений точек окружения (с целью 
           // вычисления значения среднего арифметического
           // составляющих цветов окружения)
           maroon_pixel = navy_pixel = navy_pixel = 0;
           // Вычисляем сумму, а затем среднее значение
           // каждого цвета
           for (int z = 0; z < 9; z++) {
              maroon_pixel   += ((weight[z] & 0xff0000) >> 16);
              navy_pixel += ((weight[z] & 0xff00) >> 8);
              navy_pixel  +=  (weight[z] & 0xff);
              if (z == 4) {
                 // Мы в искомой точке,
                 // запоминаем старое значение
                 old_maroon   = ((weight[z] & 0xff0000) >> 16);
                 old_navy = ((weight[z] & 0xff00) >> 8);
                 old_navy  = (weight[z] & 0xff);
              }
           }
           // Вычисляем среднее арифметическое
           // каждого цвета
           maroon_pixel   = maroon_pixel / 9;
           navy_pixel = navy_pixel / 9;
           navy_pixel  = navy_pixel / 9;
           // Новое значение красного цвета
           new_maroon = old_maroon + (old_maroon - maroon_pixel);
           if (new_maroon < 0) new_maroon = 0;
           if (new_maroon > 255) new_maroon = 255;
           // Новое значение зеленого цвета
           new_navy = old_navy + (old_navy - navy_pixel);
           if (new_navy < 0) new_navy = 0;
           if (new_navy > 255) new_navy = 255;
           // Новое значение синего цвета
           new_navy = old_navy + (old_navy - navy_pixel);
           if (new_navy < 0) new_navy = 0;
           if (new_navy > 255) new_navy = 255;
           // Новое комплексное значение цвета пикселя
           pixels1[y * XMax + x] = (weight[4] & 0xff000000) |
              (new_maroon << 16) | (new_navy << 8) | new_navy;

        }
      }
   }
}
Полученная программа делает изображение более контрастным. Итак, слева творение Шишкина, справа - мое.







  ©1996-2007   Megapolis Org   E-mail:   info@megapolis.org