JavaRush /Java blogi /Random-UZ /Baytlar olami 1. Tasvirlar bilan ishlash.
Joysi
Daraja

Baytlar olami 1. Tasvirlar bilan ishlash.

Guruhda nashr etilgan
uchun maxsus Bundan oldin men quruq misollar bilan tushuntirdim. Ular tasvirlar bilan ishlashni so'rashdi - oling.
O'quv vazifasini belgilash.
Grafik fayl berilgan (jpeg, png...). U bilan ba'zi manipulyatsiyalarni bajarish va natijani boshqa faylga yozish kerak. Soddalashtirish uchun uchta vazifani ko'rib chiqaylik: - salbiy tasvirni olish - tasvirning qora va oq versiyasini olish (rangni tiklash) - tasvirdagi yashil rangning to'yinganligini o'zgartirish. Shunga o'xshash tarzda biz yangi usullarni qo'shish orqali boshqa vazifalarni amalga oshirishimiz mumkinligini unutmang: - aniqlikni oshirish yoki xiralashtirish - o'lchamlarni o'zgartirish - soat yo'nalishi bo'yicha/soat miliga teskari aylantirish. - va Photoshop-ning boshqa imkoniyatlari :), umuman olganda, matan haqida tasavvurimiz va bilimimiz yetarli bo'lsa, rasmga har qanday algoritmni amalga oshiring (masalan, rasmdagi mumkin bo'lgan mushuklar sonini tan oling).
Bir oz quruq nazariya.
Biz rastrli tasvirlarni ko'rib chiqamiz (vektor va boshqalar ham bor). Ya'ni, fayl, xizmat ma'lumotlari bilan sarlavhaga qo'shimcha ravishda, nuqtalarning to'rtburchaklar matritsasini saqlaganda. 1920x1080 pikselli va har bir piksel uchta rang komponentining qiymatlari sifatida ifodalangan zamonaviy HD televizor ekraniga o'xshash: R (ed), G (reen), B (lue) = Qizil, Yashil va Moviy. Bu ranglar mustaqil va bu model rangni idrok etish biologiyasidan olingan. Ko'zda konus va tayoqchalar mavjud. Uch navli konuslar (uchta to'lqin uzunligi diapazonidan biriga mos keladigan reaktsiya), novdalar rangning yorqinligini (yorug'lik to'lqinining amplitudasi) "ishlaydi". RGB modelida novdalar komponentning qiymati (0 - yo'qligi, 255 - eng yorqin yorug'lik) va konuslar - mos ravishda R / G / B ning qaysi biriga mos keladigan intensivlikni joylashtirish uchun javobgardir. Masalan: Yorug'likning etishmasligi - novdalar / konuslar reaksiyaga kirishmaydi va RGB = (0,0,0). Yorqin oq yorug'lik - barcha konuslar teng ravishda reaksiyaga kirishadi, novdalar aqldan ozadi va RGB = (255,255,255). Kulrang sichqonchani yugurib o'tdi - barcha konuslar teng reaksiyaga kirishdi, novdalar o'rtacha va RGB = (127,127,127). To'q to'q sariq - R va G tayoqchalari reaksiyaga kirishadi, tayoqlar deyarli javob bermaydi, RGB=(30, 30, 0) ...
Keling, mashq qilishni boshlaylik.
Men baytlar bilan ishlash misoli uchun yozdim, shuning uchun kod barcha qoidalarga muvofiq jilolanmagan va optimaldan uzoqdir: biz kirish parametrlarini tekshirmaymiz, xatolarni to'liq tekshirmaymiz va hokazo. U to'g'ridan-to'g'ri, qayta tiklanmasdan yozilgan. Asosiy e'tibor bayt-bitlar bilan ishlashdir. Keling, JavaRush vazifalariga o'xshab, buyruq satrida tegishli argumentlar bilan chaqirilganda tasvirni o'zgartiradigan konsol yordam dasturini yozaylik. Manba tasviri: Kitty
-n kitten.jpg newkitten.jpg parametrlari bilan qo'ng'iroq qilish rasm yaratadi: salbiy
-b kitten.jpg newkitten.jpg parametrlari bilan qo'ng'iroq qilish rasm yaratadi: qora va oq mushukcha
-gr kitten.jpg newkitten.jpg parametrlari bilan qo'ng'iroq qilish rasm yaratadi. : alacakaranlık
Aslida, shunday .
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); } } } }
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION