- Работа с изображениями в Java
- 2. AWT
- 2.1. Загрузка изображения
- 2.2. Редактирование изображения
- 2.3. Отображение изображения
- 3. ImageJ
- 3.1. Maven Dependency
- 3.2. Загрузка изображения
- 3.3. Редактирование изображения
- 3.4. Отображение изображения
- Lesson: Working with Images
- Reading/Loading an image
- Drawing an image
- Creating and drawing To an image
- Writing/saving an image
- Lesson: Working with Images
- Reading/Loading an image
- Drawing an image
- Creating and drawing To an image
- Writing/saving an image
- World of Bytes 1. Работа с изображениями.
Работа с изображениями в Java
В этом уроке мы рассмотрим несколько доступных библиотек обработки изображений и выполним простую операцию обработки изображений — загрузку изображения и нанесение на него фигуры.
Мы попробуем библиотеку AWT (и немного Swing), ImageJ, OpenIMAJ и TwelveMonkeys.
2. AWT
AWT — это встроенная библиотека Java, которая позволяет пользователю выполнять простые операции, связанные с отображением, такие как создание окна, определение кнопок и слушателей и так далее. Он также включает методы, которые позволяют пользователю редактировать изображения. Не требует установки, так как поставляется с Java.
2.1. Загрузка изображения
Первым делом нужно создать объектBufferedImage из картинки, сохраненной на нашем диске:
String imagePath = "path/to/your/image.jpg"; BufferedImage myPicture = ImageIO.read(new File(imagePath));
2.2. Редактирование изображения
Чтобы нарисовать фигуру на изображении, нам нужно будет использовать объектGraphics, связанный с загруженным изображением. ОбъектGraphics инкапсулирует свойства, необходимые для выполнения основных операций визуализации. Graphics2D — это класс, расширяющийGraphics. Это обеспечивает больший контроль над двумерными формами.
В этом конкретном случае нам нуженGraphic2D, чтобы увеличить ширину формы, чтобы она была четко видна. Мы достигаем этого, увеличивая его свойство stroke. Затем мы устанавливаем цвет и рисуем прямоугольник таким образом, чтобы форма находилась в десяти пикселях от границ изображения:
Graphics2D g = (Graphics2D) myPicture.getGraphics(); g.setStroke(new BasicStroke(3)); g.setColor(Color.BLUE); g.drawRect(10, 10, myPicture.getWidth() - 20, myPicture.getHeight() - 20);
2.3. Отображение изображения
Теперь, когда мы нарисовали что-то на нашем изображении, мы хотели бы показать это. Мы можем сделать это, используя объекты библиотеки Swing. Сначала мы создаем объектJLabel, который представляет область отображения текста или / или изображения:
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
Затем добавьте нашJLabel вJPanel, который мы можем рассматривать как графического интерфейса на основе Java:
JPanel jPanel = new JPanel(); jPanel.add(picLabel);
В конце мы добавляем все вJFrame, которое является окном, отображаемым на экране. Мы должны установить размер, чтобы нам не приходилось расширять это окно при каждом запуске нашей программы:
JFrame f = new JFrame(); f.setSize(new Dimension(myPicture.getWidth(), myPicture.getHeight())); f.add(jPanel); f.setVisible(true);
3. ImageJ
ImageJ — это программное обеспечение на основе Java, созданное для работы с изображениями. Плагинов довольно много, доступноhere. Мы будем использовать только API, так как мы хотим выполнять обработку самостоятельно.
Это довольно мощная библиотека, лучше, чем Swing и AWT, поскольку целью ее создания была обработка изображений, а не операции с графическим интерфейсом. Плагины содержат много бесплатных алгоритмов, что хорошо, когда мы хотим изучить обработку изображений и быстро увидеть результаты, а не решать математические и оптимизационные задачи, лежащие в основе алгоритмов IP.
3.1. Maven Dependency
Чтобы начать работу с ImageJ, просто добавьте зависимость к файлуpom.xml вашего проекта:
Вы найдете самую новую версию вMaven repository.
3.2. Загрузка изображения
Чтобы загрузить изображение, вам нужно использовать статический методopenImage() из классаIJ:
ImagePlus imp = IJ.openImage("path/to/your/image.jpg");
3.3. Редактирование изображения
Чтобы отредактировать изображение, нам нужно будет использовать методы из объектаImageProcessor, прикрепленного к нашему объектуImagePlus. Думайте об этом как об объектеGraphics в AWT:
ImageProcessor ip = imp.getProcessor(); ip.setColor(Color.BLUE); ip.setLineWidth(4); ip.drawRect(10, 10, imp.getWidth() - 20, imp.getHeight() - 20);
3.4. Отображение изображения
Вам нужно только вызвать методshow() объектаImagePlus:
Lesson: Working with Images
As you have already learned from the Images lesson, Image s are described by a width and a height, measured in pixels, and have a coordinate system that is independent of the drawing surface.
There are a number of common tasks when working with images.
- Loading an external GIF, PNG JPEG image format file into the internal image representation used by Java 2D.
- Directly creating a Java 2D image and rendering to it.
- Drawing the contents of a Java 2D image on to a drawing surface.
- Saving the contents of a Java 2D image to an external GIF, PNG, or JPEG image file.
This lesson teaches you the basics of loading, displaying, and saving images.
The are two main classes that you must learn about to work with images:
- The java.awt.Image class is the superclass that represents graphical images as rectangular arrays of pixels.
- The java.awt.image.BufferedImage class, which extends the Image class to allow the application to operate directly with image data (for example, retrieving or setting up the pixel color). Applications can directly construct instances of this class.
The BufferedImage class is a cornerstone of the Java 2D immediate-mode imaging API. It manages the image in memory and provides methods for storing, interpreting, and obtaining pixel data. Since BufferedImage is a subclass of Image it can be rendered by the Graphics and Graphics2D methods that accept an Image parameter.
A BufferedImage is essentially an Image with an accessible data buffer. It is therefore more efficient to work directly with BufferedImage . A BufferedImage has a ColorModel and a Raster of image data. The ColorModel provides a color interpretation of the image’s pixel data.
The Raster performs the following functions:
- Represents the rectangular coordinates of the image
- Maintains image data in memory
- Provides a mechanism for creating multiple subimages from a single image data buffer
- Provides methods for accessing specific pixels within the image
The basic operations with images are represented in the following sections:
Reading/Loading an image
This section explains how to load an image from an external image format into a Java application using the Image I/O API
Drawing an image
This section teaches how to display images using the drawImage method of the Graphics and Graphics2D classes.
Creating and drawing To an image
This section describes how to create an image and how to use the image itself as a drawing surface.
Writing/saving an image
This section explains how to save created images in an appropriate format.
Lesson: Working with Images
As you have already learned from the Images lesson, Image s are described by a width and a height, measured in pixels, and have a coordinate system that is independent of the drawing surface.
There are a number of common tasks when working with images.
- Loading an external GIF, PNG JPEG image format file into the internal image representation used by Java 2D.
- Directly creating a Java 2D image and rendering to it.
- Drawing the contents of a Java 2D image on to a drawing surface.
- Saving the contents of a Java 2D image to an external GIF, PNG, or JPEG image file.
This lesson teaches you the basics of loading, displaying, and saving images.
The are two main classes that you must learn about to work with images:
- The java.awt.Image class is the superclass that represents graphical images as rectangular arrays of pixels.
- The java.awt.image.BufferedImage class, which extends the Image class to allow the application to operate directly with image data (for example, retrieving or setting up the pixel color). Applications can directly construct instances of this class.
The BufferedImage class is a cornerstone of the Java 2D immediate-mode imaging API. It manages the image in memory and provides methods for storing, interpreting, and obtaining pixel data. Since BufferedImage is a subclass of Image it can be rendered by the Graphics and Graphics2D methods that accept an Image parameter.
A BufferedImage is essentially an Image with an accessible data buffer. It is therefore more efficient to work directly with BufferedImage . A BufferedImage has a ColorModel and a Raster of image data. The ColorModel provides a color interpretation of the image’s pixel data.
The Raster performs the following functions:
- Represents the rectangular coordinates of the image
- Maintains image data in memory
- Provides a mechanism for creating multiple subimages from a single image data buffer
- Provides methods for accessing specific pixels within the image
The basic operations with images are represented in the following sections:
Reading/Loading an image
This section explains how to load an image from an external image format into a Java application using the Image I/O API
Drawing an image
This section teaches how to display images using the drawImage method of the Graphics and Graphics2D classes.
Creating and drawing To an image
This section describes how to create an image and how to use the image itself as a drawing surface.
Writing/saving an image
This section explains how to save created images in an appropriate format.
World of Bytes 1. Работа с изображениями.
Дан графический файл (jpeg, png . ). Необходимо сделать с ним некие манипуляции и записать результат в другой файл. Для упрощения рассмотрим три задачи: — получить негатив изображения — получить черно-белый вариант изображения (сбросить цветность) — изменить насыщенность зеленого цвета в изображении. Заметим, что аналогичным способом мы можем, добавляя новые методы реализовывать и другие задачи: — увеличить резкость или размытие — изменить размеры — повернуть по/против часовой. — и другие возможность Фотошопа 🙂 вообщем реализовать любой алгоритм над изображением, насколько у нас хватит фантазии и знания матана (например, распознать количество возможных котиков на картинке).
Немного сухой теории.
Мы рассматриваем растровые изображения (есть еще векторные и другие). То есть, когда файл, помимо собственно заголовка со служебной информацией, хранит прямоугольную матрицу точек. Аналогично экрану современного HD-телевизора у которого разрешение 1920х1080 точек и каждая точка представлена как значения трех составляющих цвета: R(ed), G(reen), B(lue) = Красный, Зеленый и Синий. Эти цвета независимы и данная модель взята из биологии восприятия цвета. В глазу у нас есть колбочки и палочки. Колбочки трех разновидностей (реагируют на соответствующий одной из трех диапазонов длин волн), палочки «обрабатывают» яркость цвета (амплитуду световой волны). В модели RGB палочки отвечают за значение составляющей (0 — отсутствие, 255- самый яркий свет), а колбочки — соответственно в какие из R / G / B помещать соответствующую интенсивность. Например: Отсутствие света — палочки /колбочки не реагируют и RGB=(0,0,0). Яркий белый свет — все колбочки реагируют равномерно, палочки фигеют и RGB = (255,255,255). Серая мышка пробежала — все колбочки реагируют равномерно, палочки реагируют средне и RGB = (127,127,127). Темно-оранжевый — реагируют R и G палочки, палочки едва откликаются, RGB=(30, 30, 0) .
Приступим к практике.
Я писал для примера работы с байтами, поэтому код не вылизан по всем правилам и далеко не оптимален: мы не проверяем входные параметры, не делаем полноценную проверку ошибок и т.п. Писалось в лоб, без рефакторинга. Основной упор — работа с байтами-битами. Напишем, по аналогии задач JavaRush консольную утилиту, которая при вызове в командной строке с соответствующими аргументами модифицирует изображение. Исходное изображение:
вызов с параметрами -n kitten.jpg newkitten.jpg создаст картинку:
вызов с параметрами -b kitten.jpg newkitten.jpg создаст картинку:
вызов с параметрами -gr kitten.jpg newkitten.jpg создаст картинку:
Собственно котд.
package com.joysi.byteworld; import com.sun.imageio.plugins.jpeg.*; import com.sun.imageio.plugins.png.*; import javax.imageio.*; import javax.imageio.stream.*; import java.awt.image.BufferedImage; import java.io.*; public class image < public static void main(String[] args) throws IOException < CoolImage picture = new CoolImage(args[1]); // загружаем файл изображения if ("-n".equals(args[0])) picture.convertToNegative(); if ("-g".equals(args[0])) picture.addColorGreenChannel(-100); if ("-bw".equals(args[0])) picture.convertToBlackAndWhite(); picture.saveAsJpeg(args[2]); >public static class CoolImage < private int height; // высота изображения private int width; // ширина изображения private int[] pixels; // собственно массив цветов точек составляющих изображение public int getPixel(int x, int y) < return pixels[y*width+x]; >// получить пиксель в формате RGB public int getRed(int color) < return color >> 16; > // получить красную составляющую цвета public int getGreen(int color) < return (color >> 8) & 0xFF; > // получить зеленую составляющую цвета public int getBlue(int color) < return color & 0xFF;>// получить синюю составляющую цвета // Конструктор — создание изображения из файла public CoolImage(String fileName) throws IOException < BufferedImage img = readFromFile(fileName); this.height = img.getHeight(); this.width = img.getWidth(); this.pixels = copyFromBufferedImage(img); >// Чтение изображения из файла в BufferedImage private BufferedImage readFromFile(String fileName) throws IOException < ImageReader r = new JPEGImageReader(new JPEGImageReaderSpi()); r.setInput(new FileImageInputStream(new File(fileName))); BufferedImage bi = r.read(0, new ImageReadParam()); ((FileImageInputStream) r.getInput()).close(); return bi; >// Формирование BufferedImage из массива pixels private BufferedImage copyToBufferedImage() < BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); for (int i = 0; i 255) newGreen=255; // Отсекаем при превышении границ байта if (newGreen