JavaRush /Java-Blog /Random-DE /World of Bytes 1. Arbeiten mit Bildern.
Joysi
Level 41

World of Bytes 1. Arbeiten mit Bildern.

Veröffentlicht in der Gruppe Random-DE
Besonderes für Zuvor habe ich es mit trockenen Beispielen erklärt. Sie baten darum, mit Bildern zu arbeiten – verstehen Sie es.
Eine Lernaufgabe stellen.
Gegeben sei eine Grafikdatei (jpeg, png...). Es ist notwendig, einige Manipulationen daran vorzunehmen und das Ergebnis in eine andere Datei zu schreiben. Betrachten wir zur Vereinfachung drei Aufgaben: - ein Negativbild erstellen - eine Schwarz-Weiß-Version des Bildes erstellen (die Farbe zurücksetzen) - die Grünsättigung im Bild ändern. Beachten Sie, dass wir auf ähnliche Weise durch das Hinzufügen neuer Methoden andere Aufgaben implementieren können: - Schärfe oder Unschärfe erhöhen - Abmessungen ändern - Im Uhrzeigersinn/gegen den Uhrzeigersinn drehen. - und andere Möglichkeiten von Photoshop :) Im Allgemeinen implementieren wir jeden Algorithmus auf dem Bild, sofern wir über genügend Vorstellungskraft und Matan-Kenntnisse verfügen (erkennen Sie beispielsweise die Anzahl der möglichen Katzen im Bild).
Eine kleine trockene Theorie.
Wir denken über Rasterbilder nach (es gibt auch Vektorbilder und andere). Das heißt, wenn die Datei zusätzlich zum Header selbst mit Serviceinformationen eine rechteckige Punktmatrix speichert. Ähnlich dem Bildschirm eines modernen HD-Fernsehers, der eine Auflösung von 1920 x 1080 Pixel hat und jedes Pixel als Werte von drei Farbkomponenten dargestellt wird: R(ed), G(reen), B(lue) = Rot, Grün und Blau. Diese Farben sind unabhängig und dieses Modell stammt aus der Biologie der Farbwahrnehmung. Im Auge haben wir Zapfen und Stäbchen. Zapfen in drei Varianten (reagieren auf den entsprechenden von drei Wellenlängenbereichen), Stäbchen „verarbeiten“ die Helligkeit der Farbe (die Amplitude der Lichtwelle). Im RGB-Modell sind die Stäbchen für den Wert der Komponente verantwortlich (0 – Abwesenheit, 255 – das hellste Licht) und die Zapfen – jeweils dafür, in welchem ​​der R/G/B die entsprechende Intensität platziert wird. Zum Beispiel: Lichtmangel – Stäbchen/Zapfen reagieren nicht und RGB = (0,0,0). Helles weißes Licht – alle Zapfen reagieren gleichmäßig, Stäbchen spielen verrückt und RGB = (255.255.255). Die graue Maus lief durch – alle Zapfen reagierten gleichmäßig, die Stäbchen reagierten durchschnittlich und RGB = (127.127.127). Dunkelorange – R- und G-Sticks reagieren, Sticks reagieren kaum, RGB=(30, 30, 0) ...
Beginnen wir mit dem Üben.
Ich habe für ein Beispiel für die Arbeit mit Bytes geschrieben, daher ist der Code nicht nach allen Regeln ausgefeilt und alles andere als optimal: Wir überprüfen keine Eingabeparameter, führen keine vollständige Fehlerprüfung durch usw. Es wurde direkt und ohne Umgestaltung geschrieben. Der Schwerpunkt liegt auf der Arbeit mit Bytes-Bits. Schreiben wir analog zu JavaRush-Aufgaben ein Konsolendienstprogramm, das das Bild ändert, wenn es in der Befehlszeile mit den entsprechenden Argumenten aufgerufen wird. Quellbild: Kitty
Aufruf mit den Parametern -n kitten.jpg newkitten.jpg erstellt ein Bild: Negativ
Aufruf mit den Parametern -b kitten.jpg newkitten.jpg erstellt ein Bild: Schwarz-weißes Kätzchen
Aufruf mit den Parametern -gr kitten.jpg newkitten.jpg erstellt ein Bild : Dämmerung
Eigentlich ist es das .
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;} // получить синюю составляющую цвета // Конструктор - создание изображения из Datei public CoolImage(String fileName) throws IOException { BufferedImage img = readFromFile(fileName); this.height = img.getHeight(); this.width = img.getWidth(); this.pixels = copyFromBufferedImage(img); } // Чтение изображения из Datei в 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 < height; i++) for (int j = 0; j < width; j++) bi.setRGB(j, i, pixels[i*width +j]); return bi; } // Формирование массива пикселей из BufferedImage private int[] copyFromBufferedImage(BufferedImage bi) { int[] pict = new int[height*width]; for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) pict[i*width + j] = bi.getRGB(j, i) & 0xFFFFFF; // 0xFFFFFF: записываем только 3 младших Byteа RGB return pict; } // Запись изображения в jpeg-формате public void saveAsJpeg(String fileName) throws IOException { ImageWriter writer = new JPEGImageWriter(new JPEGImageWriterSpi()); saveToImageFile(writer, fileName); } // Запись изображения в png-формате (другие графические форматы по аналогии) public void saveAsPng(String fileName) throws IOException { ImageWriter writer = new PNGImageWriter(new PNGImageWriterSpi()); saveToImageFile(writer, fileName); } // Собственно запись Datei (общая для всех форматов часть). private void saveToImageFile(ImageWriter iw, String fileName) throws IOException { iw.setOutput(new FileImageOutputStream(new File(fileName))); iw.write(copyToBufferedImage()); ((FileImageOutputStream) iw.getOutput()).close(); } // конвертация изображения в негатив public void convertToNegative() { for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) // Применяем логическое отрицание и отбрасываем старший Byte pixels[i*width + j] = ~pixels[i*width + j] & 0xFFFFFF; } // конвертация изображения в черно-белый вид public void convertToBlackAndWhite() { for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) { // находим среднюю арифметическую интенсивность пикселя по всем цветам int intens = (getRed(pixels[i * width + j]) + getGreen(pixels[i * width + j]) + getBlue(pixels[i * width + j])) / 3; // ... и записываем ее в каждый цвет за раз , сдвигая Byteы RGB на свои места pixels[i * width + j] = intens + (intens << 8) + (intens << 16); } } // изменяем интесивность зеленого цвета public void addColorGreenChannel(int delta) { for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) { int newGreen = getGreen(pixels[i * width + j]) + delta; if (newGreen > 255) newGreen=255; // Отсекаем при превышении границ Byteа if (newGreen < 0) newGreen=0; // В итоговом пикселе R и B цвета оставляем без изменений: & 0xFF00FF // Полученный новый G (зеленый) засунем в "серединку" RGB: | (newGreen << 8) pixels[i * width + j] = pixels[i * width + j] & 0xFF00FF | (newGreen << 8); } } } }
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION