Обробка виключних ситуацій

Інформація про навчальний заклад

ВУЗ:
Національний університет Львівська політехніка
Інститут:
Не вказано
Факультет:
Комп’ютерні науки
Кафедра:
Не вказано

Інформація про роботу

Рік:
2010
Тип роботи:
Методичні вказівки до лабораторної роботи
Предмет:
Об’єктно-орієнтоване програмування

Частина тексту файла (без зображень, графіків і формул):

МІНІСТЕРСТВО ОСВІТИ ТА НАУКИ УКРАЇНИ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”  Обробка виключних ситуацій Методичні вказівки до виконання лабораторної роботи №10 з курсу “Об’єктно-орієнтоване програмування” для студентів базового напрямку 6.0804 “Комп’ютерні науки” ЗАТВЕРДЖЕНО на засіданні кафедри “Системи автоматизованого проектування” Протокол № 1 від 30.08.2010 ЛЬВІВ 2010 Мова програмування Java. Методичні вказівки до виконання лабораторної роботи №10 “Обробка виключних ситуацій” з курсу: “Об’єктно-орієнтоване програмування” для студентів базового напрямку 6.0804 “Комп’ютерні науки”. Укладачі: Каркульовський В.І., доцент, к.т.н. Керницький А.Б., ст.викл., др.інж. Відповідальний за випуск: Рецензенти: 1. МЕТА РОБОТИ Одержати навики побудови алгоритмів лінійних обчислювальних процесів, навчитися складати алгоритми та програмувати процеси з розгалуженням, циклами, ітераційними циклами за допомогою мови Java. Одержати навички роботи із масивами. 2.ОСНОВНІ ТЕОРЕТИЧНІ ВІДОМОСТІ 2.1. ОПЕРАТОРИ МОВИ JAVA 15.1. Модель обробки "поставщик-споживач" Дуже часто зображення перед виведенням на екран підлягає обробці: змінюються кольори окремих пікселів або цілих частин зображення, виділяються і перетворюються якісь фрагменти зображення. В бібліотеці AWT застосовуються дві моделі обробки зображення. Одна модель реалізує давно відому в програмуванні спільну модель "поставщик-споживач" (Producer-Consumer). Згідно цієї моделі один обєкт, "поставщик", генерує сам або перетворює отриману із іншого місця продукцію, в даному випадку, набір пікселів, і передає іншим обєктам. Ці обєкти, "споживачі", приймають продукцію і теж перетворюють її при необхідності. Тільки після цього створюється обєкт класу Іmage і зображення виводиться на екран. У одного поставщика може бути декілька споживачів, котрі повинні бути зареєстровані поставщиком. Поставщик і споживач активно взаємодіють, звертаючись до методів один одного. В AWT ця модель описана в двох інтерфейсах: ImageProducer і ImageConsumer пакета java. awt. image. Інтерфейс ImageProducer описує пять методів: addConsumer(ImageConsumer ic) - реєструє споживача ic; removeConsumer (ImageConsumer ic) - скасовує реєстрацію; isConsumer( ImageConsumer ic) — логічний метод, перевіряє, чи зареєстрований споживач ic; startProduction (ImageConsumer ic) — реєструє споживача ic і починає поставку зображення всім зареєстрованим споживачам; requestTopDownLeftRightResend (ImageConsumer ic) — використовується споживаем для того, щоб затребувати зображення ще раз в порядку "зверху-вниз, зліва-направо" для методів обробки, застосовуючи саме такий порядок. З кожним екземпляром класу Іmage звязаний обєкт, реалізуючий інтерфейс ImageProducer. Його можна отримати методом getSource() класу Image. Найпростіша реалізація интерфейса ImageProducer - клас MemoryІmageSource — створює пікселі в оперативній памяті по масиву байтів або цілих чисел. Спочатку створюється масив pix, що містить колір кожної точки. Потім одним із шести конструкторів створюється обєкт класу MemoryІmageSource. Він може бути оброблений споживачем або прямо перетворений у тип Image методом createlmage (). В лістинзі 15.1 наведена проста программа, що виводить на екран квадрат розміром 100x100 пікселів. Лівий верхній кут квадрата синій, лівий нижній — червоний, правий верхній — зелений, а до центру квадрата кольори змішуються. Лістинг 15.1. Зображення, побудоване по точках import java.awt.*; import java.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 y = 0; y < h; y++){ int red = 255 * y / (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 void paint(Graphics gr){ if (img == null) img = createImage(new MemoryImageSource(w, h, pix, 0, w)); gr.drawImage(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 в конструктор класу-постачальника MemoryІmageSource (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 описує сім методів, найважливішими із яких являються два методи setPixeІs(). Перший: 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 показана ієрархія класів, реалізуючих модель "постачальник-споживач". 15.2. Класи-фільтри Інтерфейс imageConsumer не має рації реалізовувать, використовується його готова реалізація - клас imageFilter. Незважаючи на назву, цей клас не робить ніякої фільтрації, він передає зображення без зміни. Для перетворення зображення даний клас належить розширити, перевизначивши метод setPixeІs(). Результат перетворення належить передати споживачу, роль якого відіграє поле consumer цього класу. В пакеті java. awt. image єсть чотири розширення класу ImageFilter: CropImageFilter (int x, int у, int w, int h) — виділяє фрагмент зображення, указаний в приведеному конструкторі; RGBimageFilter - дозволяеє змінювати окремі пікселі; це абстрактний клас, він вимагає розширення і перевизначення свого методу filterRGB(); RepІicateScaІeFilter (int w, int h) — змінює розміри зображення на указані в приведеному конструкторі, дублюючи рядки і/або стовпці при збільшенні розмірів або прибираючи деякі із них при зменшенні; AreaAveragingScaleFilter (int w, int h) — розширення попереднього класу; використовує більш складний алгоритм зміни розмірів зображення, усереднюючий значення сусідніх пікселів. Застосовуються ці класи разом із іншим класом-постачальником, реалізуючим інтерфейс ImageProducer - класом FilteredlmageSource. Цей класс перетворює уже готову продукцію, отриману від другого постачальника producer, використовуючи для перетворення обєкт filter класу-фільтра imageFilter або його підкласу. Обидва обєкта задаються в конструкторі FilteredlmageSource(ImageProducer producer, ImageFilter filter) Все це здається дуже заплутаним, але схема застосування фільтрів завжди одна і та ж. Вона показана в лістингах 15.2—15.4. 15.3. Як виділити фрагмент зображення В лістинзі 15.2 виділяється фрагмент зображення і виводится на екран у збільшеному вигляді. Крім того, нижче виводяться зображення, збільшені зі допомогною класів RepІicateScaІeFiІter і AreaAveragingScaleFilter. Лістинг 15.2. Приклади маштабування зображення import java.awt.*; import java.awt.event.*; import java.awt.image.*; class CropTest extends Frame{ private Image img, cropimg, replimg, averimg; CropTest(String s){ super (s) ; // 1. Створюємо зображення — обєкт класу Image img = getToolkit().getImage("javalogo52x88.gif"); // 2. Створюємо обєкти-фільтри: // а) виділяємо лівий верхній кут розміром 30x30 CropImageFilter crp = new CropImageFilter(0, 0, 30, 30); // б) збільшуємо зображення в два рази простим методом ReplicateScaleFilter rsf = new ReplicateScaleFilter(104, 176); // в) збільшуємо зображення в два рази з усредненням AreaAveragingScaleFilter asf = new AreaAveragingScaleFilter(104, 176); // 3. Створюємо зміну зображення cropimg = createImage(new FilteredImageSource(img.getSource(), crp)); replimg = createImage(new FilteredImageSource(img.getSource(), rsf)); averimg = createImage(new FilteredImageSource(img.getSource(), asf)); setSize(400, 350); setVisible(true); } public void paint(Graphics g){ g.drawImage(img, 10, 40, this); g.drawImage(cropimg, 150, 40, 100, 100, this); g.drawImage(replimg, 10, 150, this); g.drawImage(averimg, 150, 150, this); } public static void main(String[] args){ Frame f= new CropTest(" Маштабування"); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent ev){ System.exit(0); } }); } } На рис. 15.3 зліва зверху показано початкове зображення, справа — збільшений фрагмент, внизу — зображення, збільшене двома способами. Рис. 15.3. Маштабування зображення 15.4. Як змінити колір зображення В лістинзі 15.3 змінюються кольори кожного пікселя зображення. Це досягається просто зсувом rgb » 1 вмісту пікселя на один біт вправо в методі fiІterRGB(). При цьому підсилюється червона складова кольору. Метод fiІterRGB() перевизначений в розширенні coІorFilter класу RGBImageFilter. Лістинг 15.3. Зміна кольору всіх пікселів import java.awt.*; import java.awt.event.*; import java.awt.image.*; class RGBTest extends Frame{ private Image img, newimg; RGBTest(String s){ super(s); img = getToolkit().getImage("javalogo52x88.gif"); RGBImageFilter rgb = new ColorFilter(); newimg = createImage(new FilteredImageSource(img.getSource(), rgb)); setSize(400, 350); setVisible(true); } public void paint(Graphics g){ g.drawImage(img, 10, 40, this); g.drawImage(newimg, 150, 40, this); } public static void main(String[] args){ Frame f= new RGBTest(" Зміна кольору"); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent ev){ System.exit(0); } }); } } class ColorFilter extends RGBImageFilter{ ColorFilter(){ canFilterIndexColorModel = true; } public int filterRGB(int x, int y, int rgb){ return rgb >> 1; } } 15.5. Як переставити пікселі зображення В лістинзі 15.4 визначається перетворення пікселів зображення. Створюється новий фільтр - розширення shiftFilter класу imageFilter, здвигаючий зображення циклічно вправо на указане в конструкторі число пікселiв. Все, що для цього потрібно, - це перевизначити метод setPixels(). Лістинг 15.4. Циклічний зсув зображення import java.awt.*; import java.awt.event.*; import java.awt.image.*; class ShiftImage extends Frame{ private Image img, newimg; ShiftImage(String s){ super(s); // 1. Одержуємо зображення із файла img = getToolkit().getImage("javalogo52x88.gif"); // 2. Створюємо екземпляр фільтра ImageFilter imf = new ShiftFilter(26); // Зсув на 26 пікселів // 3. Одержуємо нові пікселі за допомогою фільтра ImageProducer ip = new FilteredImageSource(img.getSource(), imf); // 4. Створюємо нове зображення newimg = createImage(ip); setSize(300, 200); setVisible(true) ; } public void paint(Graphics gr){ gr.drawImage(img, 20, 40, this); gr.drawImage(newimg, 100, 40, this); } public static void main(String[] args){ Frame f= new ShiftImage(" Циклічний зсув зображення"); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent ev){ System.exit(0); } }); } } // Клас-фільтр class ShiftFilter extends ImageFilter{ private int sh; // Зсув на sh пікселів вправо. public ShiftFilter(int shift){ sh = shift; } public void setPixels(int x, int y, int w, int h, ColorModel m, byte[] pix, int off, int size){ for (int k = x; k < x+w; k++){ if (k+sh <= w) consumer.setPixels(k, y, 1, h, m, pix, off+sh+k, size); else consumer.setPixels(k, y, 1, h, m, pix, off+sh+k-w, size); } } } Як видно із листинга 15.4, перевизначення методу setPixels() заключається в тому, щоб змінити аргументи цього методу, переставивши, тим самим, пікселі зображення, і передати їх споживау consumer — полю класу imageFiІter методом setPixels() споживача. На рис. 15.4 показано результат виконання цієї програми. Інша модель обробки зображеня введена в Java 2D. Вона названа моделлю прямого доступу (immediate mode model). Риc. 15.4. Перестановка пікселів зображення 15.6. Модель обробки прямим доступом Подібно до того, як замість класу Graphics система Java 2D використовує його розширення Graphics2D, описане в уроці 9, замість класу Іmage в Java 2D використовується його розширення — клас BufferedІmage. В конструкторі цього классу Bufferedlmage(int width, int height, int imageType) задаються розміри зображення і спосіб зберігання точок — одна із констант: TYPE_INT_RGB TYPE_INT_ARGB TYPE_INT_ARGB_PRE TYPE_INT_BRG TYPE_BYTE_GRAY TYPE_BYTE_BINARY TYPE_BYTE_INDEXED TYPE_3BYTE_BRG TYPE_4BYTE_ABRG TYPE_4BYTE_ABRG_PRE TYPE_USHORT_GRAY TYPE_USHORT_565_RGB TYPE_USHORT_555_RGB   Як бачите, кожний піксель може займати 4 байти — INT, 4BYTE, або 2 байта — USHORT, або 1 байт — BYTE. Може використовуватися кольорова модель RGB, або додана альфа-складова — ARGB, або задани інший порядок розташування кольорових складових — BRG, або задані градації сірого кольору — GRAY. Кожна складова кольору може займати один байт, 5 бітів або 6 бітів. Екземпляри класу BufferedІmage рідко створюються конструкторами. Для їх створення частіше звертаються до методів createІmage () класу Сomponent з простим приведенням типу: BufferedІmage bi = (Bufferedlmage)createІmage(width, height) При цьому екземпляр bi отримує характеристики компонента: колір фону і колір рисування, спосіб зберігання точок. Розташування точок в зображенні регулюється класом Raster або його підкласом WritabІeRaster. Ці класи задають систему координат зображення, представляють доступ до окремих пікселів методами getPixeІ(), дозволяють виділяти фрагменти зображення методами getPixeІs(). Клас WritabІeRaster додатково дозволяє змінювати окремі пікселі методами getPixeІ() або цілі фрагменти зображення методами setPixels() і setRect(). Початок системи координат зображення — лівий верхній кут — має координати (minХ, minY), не обовязково рівні нулю. При створенні екземпляра класу BufferedІmage автоматично формується звязанный з ним екземпляр класу WritabІeRaster. Точки зображення зберігаються в скритому буфері, вміщаючим одновимірний або двовимірний масив точок. Вся робота з буфером здійснюється методами одного із класів DataBufferByte, DataBufferlnt, DataBufferShort, DataBufferushort в залежності від довжини даних. Загальні властивості цих класів зібрані в їх абстрактному суперкласі DataBuffer. В ньому визначені типи даних, що зберігаються в буфері: TYPE_BYTE, TYPE_SHORT, TYPE_INT, TYPE_ІNDEFINED. Методи класу DataBuffer дозволяють прямий доступ до даних буфера, але зручніше і безпечніше звертатися до них методами класів Raster і WritableRaster. При створенні екземпляра класу Raster або класу WritableRaster створюється екземпляр відповідного підкласу класу DataBuffer. Щоб не враховувати спосіб зберігання точок зображення, Raster може звертатися не до буфера DataBuffer, а до підкласів абстрактного класу SampІeModeІ, що розглядає не окремі байти буфера, а складові (samples) кольору. В моделі RGB — це червона, зелена і синя складові. В пакеті java.awt. image єсть пять підкласів класу SampІeModeІ: СomponentSampІeModel — кожна складова кольору зберігається в окремому елементі масива DataBuffer; BandedSampleModel — дані зберігаються по складовим, складов одного кольору зберігаються в одному масиві, a DataBuffer містить двовимірний масив: по масиву для кожної складової; даний клас розширяє класс ComponentSampІeModel; PixelInterleavedSampІeModel — всі складові кольору одного пікселя зберігаються в сусідніх елементах єдиного масива DataBuffer; даний клас розширяє клас ComponentSampІeModel; MultiPixeІPackedSampІeModel — колір кожного пікселя містить тільки одну складову, яка може бути упакована в один елемент масива DataBuffer; SingІePixelPackedSampleModel — всі складові кольору кожного пікселя зберігаються в одному елементі масиву DataBuffer. На рис. 15.5 представлена ієрархія класів Java 2D, реалізуюча модель прямого доступу. Отже, Java 2D створює складну і розгалуджену трьохшарову систему DataBuffer — SampІeModeІ — Raster управління даними зображення BufferedІmage. Ви можете маніпулювати точками зображення, використовуючи їх координати в методах класів Raster або спуститься на рівень нижче і звертатися до складових кольору піксела методами класів SampІeModeІ. Якщо ж вам треба працювати з окремими байтами, скористуйтесь класами DataBuffer. Застосовувати цю систему приходиться рідко, тільки при створенні свого способу перетворення зображення. Стандартні ж перетворення виконуються дуже просто. 15.7. Перетворення зображення в Java 2D Перетворення зображення source, що зберігається в обєкті класу Buffеredlmage, в нове зображення destination виконується методом filter(Buffredlmage source, Buffredlmage destination) описаним в інтерфейсі BuffredІmageOp. Указаний метод повертає посилку на новий, змінений обєкт destination класу Buffredlmage, що дозволяє задати ланцюжок послідовних перетворень. Можна перетворювати тільки координатну систему зображення методом filter(Raster source, WritableRaster destination) повертаючим посилку на змінений обєкт класу WritableRaster. Даний метод описано в інтерфейсі RasterOp. Спосіб перетворення визначається класом, реалізуючим ці інтерфейси, а параметри перетворення задаються в конструкторі класу. В пакеті java.awt.image єсть шість класів, реалізуючих інтерфейси BuffredІmageOp і RasterOp: AffineTransformOp — виконує афінне перетворення зображення: зcув, поворот, відображення, стискання або розтягування по вісям; RescaІeOp — змінює інтенсивність зображення; LookupOp — змінює окремі складові кольору зображення; BandCombineOp — мінює складові кольору в Raster; СolorConvertdp — змінює кольорову модель зображення; ConvolveOp — виконує згортання, що дозволяє змінити контраст і/або яскравість зображення, створити ефект "розмитості" і інші ефекти. Рис. 15.5. Класи, реалізуючі модель прямого доступу Розглянемо, як можна застосувати ці класи для перетворення зображення. 15.8. Афінне перетворення зображення Клас AffineTransform і його використання детально розібрані в уроці 9, тут ми тільки застосуємо його для перетворення зображення. В конструкторі класу AffineTransformOp указується попередньо створене афінне перетворення at і спосіб інтерполяції interp і/або правила візуалізації hints: AffineTransformOp(AffineTransform at, int interp); AffineTransformOp(AffineTransform at, RenderingHints hints); Спосіб інтерполяції — це одна із двох констант: TYPE_NEAREST_NEIGHBOR (по замовчуванню в другому конструкторі) або TYPE_BILINEAR. Після створення обєкту класу AffineTransformOp застосовується метод filter(). При цьому зображення перетворюється всередині нової області типу BufferedІmage, як показано на рис. 15.6, справа. Сама область виділена чорним кольором. Другий спосіб афінного перетворення зображення — застосувати метод drawlmage(Bufferedlmage img, BufferedlmageOp op, int x, int y) класу Graphics2D. При цьому перетворюється вся область img, як продемонстровано на рис. 15.6, посередині. В лістинзі 15.5 показано, як задаються перетворення, представлені на рис. 15.6. Зверніть увагу на особливості роботи з BufferedІmage. Треба створити графічний контекст зображення і вивести в нього зображення. Ці дії здаються зайвими, але зручні для подвійної буферизації, яка зараз стала стандартом перерисовування зображень, а в біблиотеці Swing виконується автоматично. Лістинг 15.5. Афінне перетворення зображення import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.awt.event.*; public class AffOp extends Frame{ private BufferedImage bi; public AffOp(String s){ super (s) ; // Завантажуємо зображення Image img = getToolkit().getImage("javalogo52x88.gif"); // В цьому блоці організовано очікування завантаження try{ MediaTracker mt = new MediaTracker(this); mt.addImage(img, 0); mt.waitForID(0); // Чекаємо закінчення завантаження } catch(Exception e){} // Розміри створюваної області bi співпадають з розмірами зображення img bi = new BufferedImage(img.getWidth(this), img.getHeight(this), BufferedImage.TYPE_INT_RGB); // Створюємо графічний контекст big зображення bi Graphics2D big = bi.createGraphics(); // Виводимо зображення img в графічний контекст big.drawImage(img, 0, 0, this); } public void paint(Graphics g){ Graphics2D g2 = (Graphics2D)g; int w = getSize().width; int h = getSize().height; int bw = bi.getWidth(this); int bh = bi.getHeight(this); // Створюємо афінне перетворення AffineTransform at = new AffineTransform(); at.rotate(Math.PI/4); // Задаємо поворот на 45 градусів //по годинниковій стрілці навколо лівого верхнього кута. //Потім зсуваємо зображення вправо на величину bw at.preConcatenate(new AffineTransform(1, 0, 0, 1, bw, 0)); // Визначаємо область зберігання bimg перетвореного // зображення. Її розмір вдвічі больший попереднього BufferedImage bimg = new BufferedImage(2*bw, 2*bw, BufferedImage.TYPE_INT_RGB); // Створюємо обєкт biop, що містить перетворення at BufferedImageOp biop = new AffineTransformOp(at, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); // Перетворюємо зображення, результат заносимо в bimg biop.filter(bi, bimg); // Виводимо початкове зображення. g2.drawImage(bi, null, 10, 30); // Виводимо змінене перетворенням biop область bi g2.drawImage(bi, biop, w/4+3, 30); // Виводимо перетворене всередині області bimg зображення g2.drawImage(bimg, null, w/2+3, 30); } public static void main(String[] args){ Frame f = new AffOp(" Афінне перетворення"); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } }); f.setSize(400, 200); f.setVisible(true) ; } } На рис. 15.6 показано початкове зображення, перетворена область і перетворене всередині області зображення. Рис. 15.6. Афінне перетворення зображення 15.9. Зміна інтенсивности зображення Зміна інтенсивності зображення виражається математично множеням кожної складової кольору на число factor і додаванням до результату множення числа offset. Результат приводиться до діапазону значень складової. Після цього інтенсивність кожної складової кольору лінійно змінюється в одному і тому ж масштабі. Числа factor і offset сталі для кожного пікселя і задаються в конструкторі класу разом з правилами візуалізації hints: RescaleOp(float factor, float^offset, RenderingHints hints) Після цього залишається застосувати метод filter(). На рис. 15.7 інтенсивність кожного кольору зменшена вдвічі, в результаті білий фон став сірим, а кольори - темнішими. Потім інтенсивність збільшена на 70 одиниць. В лістинзі 15.6 приведена программа, що виконує це перетворення. Лістинг 15.6. Зміна інтенсивності зображення import java.awt.*; import java.awt.image.*; import java.awt.event.*; public class Rescale extends Frame{ private BufferedImage bi; public Rescale(String s){ super (s) ; Image img = getToolkit().getImage("javalogo52x88.gif"); try{ MediaTracker mt = new MediaTracker(this); mt.addImage(img, 0); mt.waitForID(0); } catch(Exception e){} bi = new BufferedImage(img.getWidth(this), img.getHeight(this), BufferedImage.TYPE_INT_RGB); Graphics2D big = bi.createGraphics(); big.drawImage(img, 0, 0, this); } public void paint(Graphics g){ Graphics2D g2 = (Graphics2D)g; int w = getSize().width; int bw = bi.getWidth(this); int bh = bi.getHeight(this); BufferedImage bimg = new BufferedImage(bw, bh, BufferedImage.TYPE_INT_RGB); //——————— Початок визначення перетворення --——-——— RescaleOp rop = new RescaleOp(0.5f, 70.0f, null); rop.filter(bi, bimg); //——————— Кінець визначення перетворення ——————— g2.drawImage(bi, null, 10, 30); g2.drawImage(bimg, null, w/2+3, 30); } public static void main(String[] args){ Frame f = new Rescale(" Зміна інтенсивності"); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e) { System.exit(0); } }); f.setSize(300, 200); f.setVisible(true); } } Рис. 15.7. Зміна інтенсивності зображення 15.10. Зміна складових кольору Щоб змінити окремі складові кольору, треба перш за все продивитися тип зберігання елементів в BufferedІmage, по замовчуванню це TYPE_INT_RGB. Тут три складові — червона, зелена і синя. Кожна складова кольору займає один байт, всі вони зберігаються в одному числі типу int. Потім треба скласти таблицю нових значень складових. В лістинзі 15.7 це двовимірний масив samples. Потім заповнюємо даний масив потрібними значеннями складових кожного кольору. В лістинзі 15.7 задається яскраво-червоний колір рисування і білий колір фону. По отриманій таблиці створюємо екземпляр класу ByteLookupTabІe, який звяже цю таблицю з буфером даних. Цей екземпляр використовуємо для створення обєкта класу LookupOp. Нарешті, застосовуємо метод filter() цього класу. В лістинзі 15.7 приведений тільки фрагмент програми. Для одержання повної програми його треба вставити в лістинг 15.6 замість виділеного в ньому фрагмента. Логотип Java буде нарисований яскраво-червоним кольором. Лістинг 15.7. Зміна складових кольору //————————————— Вставити в лістинг 15.6 ———————— byte samples[][] = new byte[3][256]; for (int j = 0; j < 255; j++){ samples[0][j] = (byte)(255); // Червона складова samples[1][j] = (byte)(0); // Зелена складова samples[2][j] = (byte)(0); // Синя складова } samples[0][255] = (byte) (255); // Колір фону — білий samples[1][255] = (byte) (255) ; samples [2] [255] = (byte) (255) ; ByteLookupTable blut=new ByteLookupTable(0, samples); LookupOp lop = new LookupOp(blut, null); lop.filter(bi, bimg); //————————————— Кінець вставки ———————————————- 15.11. Створення різних эфектів Операція згортання (convolution) задає значення кольору точки в залежності від кольорів сусідніх точок наступним способом. Нехай точка з координатами (х, у) має колір, вираженим числом А(х, у). Складаємо масив із девяти дійсних чисел w(0), w(i), ... w(8). Тоді нове значенне кольору точки з координатами (х, у) буде рівним: w(0)*A(x-l, y-l)+w(l)*A(x, y-l)+w(2)*A(x+l, y-l)+ w(3)*A(x-l, y)+w(4)*A(x, y)+w(5)*A(x+l, у)+ w(6)*A(x-l, y+l)+w(7)*A(x, y+l)+w(8)*A(x+l, y+1) Задаючи різні значення ваговим коефіцієнтам w(i), будемо отримувати різні эфекти, підсилюючи чи зменшуючи вплив сусідніх точок. Якщо сума всіх девяти чисел w(i) рівна 1.0f, то інтенсивність кольору залишиться попередня. Якщо при цьомц всі ваги рівні між собою, тобто рівні 0.1111111f, то одержимо ефект размитості, тумана, димки. Якщо вага w(4) значно більше решти при загальній сумі їх l.0f, то зростає контрастність, виникає эфект графіки, штрихового рисунка. Можно згорнути не тільки сусідні точки, але і наступні ряди точок, взявши масив вагових коэфіцієнтів із 15 елементов (3x5, 5x3), 25 элементів (5x5) і більше. В Java 2D згортання робиться так. Спочатку визначаємо масив ваг, наприклад: float[] w = {0, -1, 0, -1, 5, -1, 0, -1, 0}; Потім створюємо екземпляр класу Kernel — ядра згортання: Kernel kern = new Kernel(3, 3, w); Потім обєкт класу ConvoІveOp з цим ядром: ConvolveOp conv = new ConvoiveOp(kern); Все готово, застосовуємо метод filter(): conv.filter(bi, bimg); В лістинзі 15.8 записані дії, необхідні для створення eфекта "размитості". Лістинг 15.8. Створення різних эфектів //—————————— Вставити в лістинг 15.6 —————————————— float[] wl = { 0.11111111f, 0.11111111f, 0.11111111f, 0.11111111f, 0.11111111f, 0.11111111f, 0.11111111f, 0.11111111f, 0.11111111f }; Kernel kern = new Kernel(3, 3, wl); ConvolveOp cop = new ConvolveOp(kern, ConvolveOp.EDGE_NO_OP, null); cop.filter(bi, bimg) ; //—————————— Кінець вставки ——————————————————————— На рис 15.8 представлені зліва направо початкове зображення і зображення, перетворені ваговими матрицями w1, w2 i w3, де матриця w1 показана в лістинзі 15.8, а матриці w2
Антиботан аватар за замовчуванням

25.05.2016 15:05-

Коментарі

Ви не можете залишити коментар. Для цього, будь ласка, увійдіть або зареєструйтесь.

Ділись своїми роботами та отримуй миттєві бонуси!

Маєш корисні навчальні матеріали, які припадають пилом на твоєму комп'ютері? Розрахункові, лабораторні, практичні чи контрольні роботи — завантажуй їх прямо зараз і одразу отримуй бали на свій рахунок! Заархівуй всі файли в один .zip (до 100 МБ) або завантажуй кожен файл окремо. Внесок у спільноту – це легкий спосіб допомогти іншим та отримати додаткові можливості на сайті. Твої старі роботи можуть приносити тобі нові нагороди!
Нічого не вибрано
0%

Оголошення від адміністратора

Антиботан аватар за замовчуванням

Подякувати Студентському архіву довільною сумою

Admin

26.02.2023 12:38

Дякуємо, що користуєтесь нашим архівом!