JavaRush /وبلاگ جاوا /Random-FA /World of Bytes 1. کار با تصاویر.
Joysi
مرحله

World of Bytes 1. کار با تصاویر.

در گروه منتشر شد
ویژه برای قبل از این با مثال های خشک توضیح دادم. آنها خواستند با تصاویر کار کنند - آن را دریافت کنید.
تنظیم یک کار یادگیری
با توجه به یک فایل گرافیکی (jpeg، png...). لازم است چند دستکاری با آن انجام دهید و نتیجه را در فایل دیگری بنویسید. برای ساده‌تر شدن، سه کار را در نظر می‌گیریم: - دریافت تصویر منفی - دریافت نسخه سیاه و سفید تصویر (تنظیم مجدد رنگ) - تغییر اشباع رنگ سبز در تصویر. توجه داشته باشید که به روشی مشابه، با افزودن روش‌های جدید، می‌توانیم کارهای دیگری را نیز اجرا کنیم: - افزایش وضوح یا محو کردن - تغییر ابعاد - چرخش در جهت عقربه‌های ساعت / خلاف جهت عقربه‌های ساعت. - و سایر امکانات فتوشاپ :) به طور کلی هر الگوریتمی را تا جایی که تخیل و دانش کافی در مورد ماتان داریم (مثلا تعداد گربه های احتمالی در تصویر را تشخیص دهیم) روی تصویر پیاده سازی کنید.
کمی تئوری خشک
ما تصاویر شطرنجی را در نظر می گیریم (همچنین بردار و موارد دیگر وجود دارد). یعنی زمانی که فایل علاوه بر خود سربرگ با اطلاعات سرویس، یک ماتریس مستطیلی از نقاط را ذخیره می کند. مشابه صفحه نمایش یک تلویزیون HD مدرن که دارای وضوح 1920x1080 پیکسل است و هر پیکسل به عنوان مقادیر سه جزء رنگی نشان داده می شود: R(ed)، G(reen)، B(lue) = قرمز، سبز. و آبی این رنگ ها مستقل هستند و این مدل برگرفته از زیست شناسی ادراک رنگ است. در چشم ما مخروط و میله داریم. مخروط های سه گونه (به یکی از سه محدوده طول موج مربوطه واکنش نشان می دهند)، میله ها روشنایی رنگ (دامنه موج نور) را پردازش می کنند. در مدل RGB، میله ها مسئول مقدار جزء هستند (0 - عدم وجود، 255 - درخشان ترین نور)، و مخروط ها - به ترتیب، در کدام یک از R / G / B شدت مربوطه را قرار می دهند. به عنوان مثال: کمبود نور - میله ها / مخروط ها واکنش نشان نمی دهند و RGB = (0,0,0). نور سفید روشن - همه مخروط ها به طور مساوی واکنش نشان می دهند، میله ها دیوانه می شوند و RGB = (255،255،255). موش خاکستری عبور کرد - همه مخروط ها به طور مساوی واکنش نشان دادند، میله ها به طور متوسط ​​و RGB = (127,127,127) واکنش نشان دادند. نارنجی تیره - چوب های R و G واکنش نشان می دهند، چوب ها به سختی پاسخ می دهند، RGB=(30، 30، 0) ...
بیایید تمرین را شروع کنیم.
من برای مثالی از کار با بایت ها نوشتم، بنابراین کد طبق تمام قوانین جلا داده نمی شود و از بهینه فاصله دارد: ما پارامترهای ورودی را بررسی نمی کنیم، بررسی کامل خطا را انجام نمی دهیم و غیره. مستقیماً بدون بازنویسی نوشته شده بود. تمرکز اصلی کار با بیت-بیت است. بیایید، به قیاس با وظایف JavaRush، یک ابزار کنسول بنویسیم که وقتی در خط فرمان با آرگومان های مناسب فراخوانی می شود، تصویر را تغییر می دهد. تصویر منبع: بچه گربه
تماس با پارامترها -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