JavaRush /Java Blog /Random-TL /Mundo ng Bytes 1. Paggawa gamit ang mga larawan.
Joysi
Antas

Mundo ng Bytes 1. Paggawa gamit ang mga larawan.

Nai-publish sa grupo
Espesyal para sa Bago ito, ipinaliwanag ko sa mga tuyong halimbawa. Hiniling nilang magtrabaho kasama ang mga imahe - kunin ito.
Pagtatakda ng gawain sa pag-aaral.
Binigyan ng graphic file (jpeg, png...). Kinakailangan na gumawa ng ilang mga manipulasyon dito at isulat ang resulta sa isa pang file. Para gawing simple, isaalang-alang natin ang tatlong gawain: - kumuha ng negatibong larawan - kumuha ng itim at puting bersyon ng larawan (i-reset ang kulay) - baguhin ang saturation ng berde sa larawan. Tandaan na sa katulad na paraan maaari nating, sa pamamagitan ng pagdaragdag ng mga bagong pamamaraan, ipatupad ang iba pang mga gawain: - pataasin ang sharpness o blur - baguhin ang mga dimensyon - paikutin ang clockwise/counterclockwise. - at iba pang mga posibilidad ng Photoshop :) sa pangkalahatan, ipatupad ang anumang algorithm sa imahe, hangga't mayroon kaming sapat na imahinasyon at kaalaman sa matan (halimbawa, kilalanin ang bilang ng mga posibleng pusa sa larawan).
Isang maliit na tuyong teorya.
Isinasaalang-alang namin ang mga raster na imahe (mayroong vector at iba pa). Iyon ay, kapag ang file, bilang karagdagan sa header mismo na may impormasyon ng serbisyo, ay nag-iimbak ng isang hugis-parihaba na matrix ng mga puntos. Katulad ng screen ng isang modernong HD TV, na may resolution na 1920x1080 pixels at ang bawat pixel ay kinakatawan bilang mga value ng tatlong bahagi ng kulay: R(ed), G(reen), B(lue) = Red, Green at Blue. Ang mga kulay na ito ay independyente at ang modelong ito ay kinuha mula sa biology ng color perception. Sa mata mayroon kaming mga cone at rod. Ang mga cone ng tatlong uri (tumugon sa kaukulang isa sa tatlong mga saklaw ng wavelength), ang mga rod ay "nagproseso" ng liwanag ng kulay (ang amplitude ng light wave). Sa modelo ng RGB, ang mga rod ay may pananagutan para sa halaga ng bahagi (0 - kawalan, 255 - ang pinakamaliwanag na ilaw), at ang mga cones - ayon sa pagkakabanggit, kung saan sa R ​​/ G / B ilalagay ang kaukulang intensity. Halimbawa: Kakulangan ng liwanag - ang mga rod/cone ay hindi tumutugon at RGB = (0,0,0). Maliwanag na puting ilaw - pantay-pantay ang reaksyon ng lahat ng cone, nababaliw ang mga rod at RGB = (255,255,255). Ang kulay abong mouse ay tumakbo - lahat ng mga cone ay gumanti nang pantay-pantay, ang mga rod ay nag-react nang katamtaman at RGB = (127,127,127). Madilim na orange - Nagre-react ang R at G sticks, halos hindi tumugon ang sticks, RGB=(30, 30, 0) ...
Simulan na natin ang pagsasanay.
Sumulat ako para sa isang halimbawa ng pagtatrabaho sa mga byte, kaya ang code ay hindi pinakintab ayon sa lahat ng mga patakaran at malayo sa pinakamainam: hindi namin sinusuri ang mga parameter ng pag-input, huwag gumawa ng buong pagsusuri ng error, atbp. Isinulat ito nang direkta, nang walang refactoring. Ang pangunahing pokus ay gumagana sa mga bytes-bit. Sumulat tayo, sa pamamagitan ng pagkakatulad sa mga gawain ng JavaRush, isang console utility na, kapag tinawag sa command line na may naaangkop na mga argumento, binabago ang imahe. Pinagmulan ng imahe: Kitty
ang pagtawag gamit ang mga parameter -n kitten.jpg newkitten.jpg ay lilikha ng isang larawan: negatibo
ang pagtawag gamit ang mga parameter -b kitten.jpg newkitten.jpg ay lilikha ng isang larawan: itim at puting kuting
ang pagtawag gamit ang mga parameter -gr kitten.jpg newkitten.jpg ay lilikha ng isang larawan : takipsilim
Actually, yun lang .
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); } } } }
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION