JavaRush /Blog Java /Random-MS /World of Bytes 1. Bekerja dengan imej.
Joysi
Tahap

World of Bytes 1. Bekerja dengan imej.

Diterbitkan dalam kumpulan
Khas untuk Sebelum ini saya terangkan dengan contoh-contoh kering. Mereka meminta untuk bekerja dengan imej - dapatkannya.
Menetapkan tugas pembelajaran.
Diberikan fail grafik (jpeg, png...). Ia perlu melakukan beberapa manipulasi dengannya dan menulis hasilnya ke fail lain. Untuk memudahkan, mari kita pertimbangkan tiga tugas: - dapatkan imej negatif - dapatkan versi hitam dan putih imej (set semula warna) - tukar ketepuan hijau dalam imej. Ambil perhatian bahawa dengan cara yang sama kita boleh, dengan menambah kaedah baharu, melaksanakan tugas lain: - meningkatkan ketajaman atau kabur - menukar dimensi - berputar mengikut arah jam/lawan arah jam. - dan kemungkinan lain Photoshop :) secara umum, laksanakan apa-apa algoritma pada imej, setakat kita mempunyai imaginasi dan pengetahuan yang mencukupi tentang matan (contohnya, kenali bilangan kucing yang mungkin dalam gambar).
Teori kering sikit.
Kami sedang mempertimbangkan imej raster (terdapat juga vektor dan lain-lain). Iaitu, apabila fail, sebagai tambahan kepada pengepala itu sendiri dengan maklumat perkhidmatan, menyimpan matriks segi empat tepat mata. Sama seperti skrin TV HD moden, yang mempunyai resolusi 1920x1080 piksel dan setiap piksel diwakili sebagai nilai tiga komponen warna: R(ed), G(reen), B(lue) = Merah, Hijau dan Biru. Warna-warna ini adalah bebas dan model ini diambil daripada biologi persepsi warna. Di mata kita mempunyai kon dan batang. Kon daripada tiga jenis (bertindak balas kepada satu daripada tiga julat panjang gelombang yang sepadan), rod "memproses" kecerahan warna (amplitud gelombang cahaya). Dalam model RGB, rod bertanggungjawab untuk nilai komponen (0 - ketiadaan, 255 - cahaya paling terang), dan kon - masing-masing, di mana R / G / B untuk meletakkan keamatan yang sepadan. Contohnya: Kekurangan cahaya - rod/kon tidak bertindak balas dan RGB = (0,0,0). Cahaya putih terang - semua kon bertindak balas sama rata, rod menjadi gila dan RGB = (255,255,255). Tetikus kelabu berlari melalui - semua kon bertindak balas sama rata, rod bertindak balas secara purata dan RGB = (127,127,127). Jingga gelap - Batang R dan G bertindak balas, kayu hampir tidak bertindak balas, RGB=(30, 30, 0) ...
Jom mula berlatih.
Saya menulis untuk contoh bekerja dengan bait, jadi kod itu tidak digilap mengikut semua peraturan dan jauh dari optimum: kami tidak menyemak parameter input, tidak melakukan pemeriksaan ralat penuh, dsb. Ia ditulis secara langsung, tanpa pemfaktoran semula. Fokus utama adalah bekerja dengan bit-bait. Mari kita tulis, dengan analogi dengan tugas JavaRush, utiliti konsol yang, apabila dipanggil pada baris arahan dengan hujah yang sesuai, mengubah suai imej. Imej sumber: Kitty
memanggil dengan parameter -n kitten.jpg newkitten.jpg akan mencipta gambar: negatif
memanggil dengan parameter -b kitten.jpg newkitten.jpg akan mencipta gambar: anak kucing hitam putih
memanggil dengan parameter -gr kitten.jpg newkitten.jpg akan mencipta gambar : senja
Sebenarnya, itu sahaja .
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;} // получить синюю составляющую цвета // Конструктор - создание изображения из file public CoolImage(String fileName) throws IOException { BufferedImage img = readFromFile(fileName); this.height = img.getHeight(); this.width = img.getWidth(); this.pixels = copyFromBufferedImage(img); } // Чтение изображения из file в 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); } // Собственно запись file (общая для всех форматов часть). 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); } } } }
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION