JavaRush /Java блогу /Random-KY /Байттар дүйнөсү 1. Сүрөттөр менен иштөө.
Joysi
Деңгээл

Байттар дүйнөсү 1. Сүрөттөр менен иштөө.

Группада жарыяланган
үчүн атайын Буга чейин мен кургак мисалдар менен түшүндүрдүм. Алар сүрөттөр менен иштөөнү суранышты - аны алыңыз.
Окуу тапшырмасын коюу.
Графикалык файл берилген (jpeg, png...). Аны менен кээ бир манипуляцияларды жасап, натыйжаны башка файлга жазуу керек. Жөнөкөйлөтүү үчүн үч тапшырманы карап көрөлү: - терс сүрөттү алуу - сүрөттүн ак-кара versionсын алуу (түстү кайра коюу) - сүрөттүн жашыл түскө каныккандыгын өзгөртүү. Ушундай жол менен жаңы ыкмаларды кошуу менен башка тапшырмаларды аткара аларыбызды эске алыңыз: - тактыкты же бүдөмүктүктү жогорулатуу - өлчөмдөрдү өзгөртүү - саат жебеси боюнча/саат жебесине каршы айлануу. - жана Photoshopтун башка мүмкүнчүлүктөрү :) жалпы эле, бизде матандын фантазиясы жана бorми жетиштүү болсо, сүрөт боюнча каалаган алгоритмди ишке ашырыңыз (мисалы, сүрөттө мүмкүн болгон мышыктардын санын таануу).
Бир аз кургак теория.
Биз растрдык сүрөттөрдү карап жатабыз (вектордук жана башкалар да бар). Башкача айтканда, файл, кызмат маалыматы менен баш маалыматтан тышкары, чекиттердин тик бурчтуу матрицасын сактайт. Заманбап HD сыналгысынын экранына окшош, ал 1920x1080 пикселдик чечимге ээ жана ар бир пиксел үч түстүү компоненттин маанилери катары берилген: R(ed), G(reen), B(lue) = Red, Green жана Көк. Бул түстөр көз карандысыз жана бул модель түстү кабылдоо биологиясынан алынган. Көзүбүздө конустар жана таякчалар бар. Үч түрдөгү конустар (үч толкун узундугунун тиешелүү бирине жооп берет), таякчалар түстүн жарыктыгын (жарык толкунунун амплитудасы) "иштейт". RGB моделинде таякчалар компоненттин мааниси үчүн жооп берет (0 - жок, 255 - эң жаркыраган жарык), ал эми конустар - тиешелүүлүгүнө жараша R / G / B кайсынысына тиешелүү интенсивдүүлүктү жайгаштыруу керек. Мисалы: Жарыктын жетишсиздиги - таякчалар/конустар реакция бербейт жана RGB = (0,0,0). Жаркыраган ак жарык - бардык конустар бирдей реакция кылат, таякчалар жинди болуп, RGB = (255,255,255). Боз чычкан чуркап өттү - бардык конустар бирдей реакция жасады, таякчалар орточо жана RGB = (127,127,127). Кочкул кызгылт сары - R жана G таякчалары жооп беришет, таякчалар араң жооп беришет, RGB=(30, 30, 0) ...
Көнүгүүнү баштайлы.
Мен byte менен иштөөнүн мисалы үчүн жаздым, ошондуктан code бардык эрежелерге ылайык жылмаланган эмес жана оптималдуу эмес: биз киргизүү параметрлерин текшербейбиз, каталарды толук текшербейбиз ж.б. Рефакторациясыз түз эле жазылган. Негизги көңүл byte-бит менен иштөө болуп саналат. Келгиле, JavaRush тапшырмаларына окшоштуруп, буйрук сабында тиешелүү аргументтер менен чакырылганда сүрөттү өзгөрткөн консолдук утorтаны жазалы. Булак сүрөтү: Kitty
-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;} // получить синюю составляющую цвета // Конструктор - создание изображения из 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); } } } }
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION