Розфарбовуємо значки від гугла

    Дизайн додатки — дуже важлива частина розробки. Google значно його спрощує, надаючи у вільному доступі близько 150 готових значків, заготовлених під різну щільність пікселів. Однак за замовчуванням вони сірого кольору. Зроблено це спеціально для того, щоб дизайнер сам розфарбував їх. Але якщо ми хочемо просто надати піктограм деякий колір — немає сенсу редагувати кожен окремо. Простіше написати скрипт, який зробить роботу за нас.
 
У цій статті буде представлена ​​невелика програмка на Java, яка автоматично розфарбовує всі значки в заданий колір, алгоритм, за яким вона працює, а також — архів вже розфарбованих значків, які ви відразу можете використовувати в своїх додатках.
 
Відразу обмовлюся — цілком можливо, що засобами Adobe Illustrator можна зробити все те, про що написано в статті і вже є готові скрипти. Але його немає під лінуксом і взагалі він дорого коштує. Думаю, що користувачі Linux і прихильники вільного ПЗ оцінять мій підхід.
 
 
 
 Вступ На сайті developer.android.com будь-який бажаючий може скачати архів з ресурсами для дизайну, які, за заявою в NOTICE.TXT , можна використовувати без будь-яких обмежень. Серед них є значки Action Bar Icons . Давайте розглянемо їх більш докладно. Є два набори — для тем Holo Light і Holo Dark . Відповідно, для темної теми значки білі, а для білої — сірі. Наскільки я зрозумів, вихідні коди для значків знаходяться у форматі Adobe Illustrator (*. Ai). Але для мене ця програма надто дорого коштує, та й взагалі я прихильник вільного ПЗ. Так що ми будемо розфарбовувати вже заготовлені png файли, благо їх розмір вже скоректований під різну щільність пікселів.
 
 А навіщо? Зрозуміло, великої компанії буде краще найняти професійного дизайнера, який намалює унікальні іконочки з нуля. Або ж допрацює існуючі. Однак якщо робити невеликий додаток на замовлення — немає сенсу вводити новий дизайн. Користувачі Android звикли до стандартного набору значків, до їх контурах. Мені здається, що варто просто надати цим контурах колір і порадувати користувача.
 
Але головна користь від таких значків — коли програміст робить програму для себе, і у нього немає бажання і часу займатися дизайном. Хочеться, щоб програма виглядала як у всіх, але при цьому надавала якісь свої унікальні функції. Наприклад, якщо ви початківець програміст і вивчаєте Android — буде дуже корисно паралельно з навчанням розробляти якусь свою програму і продемонструвати в ній отримані знання. При цьому з розфарбованими значками вона виглядатиме значно краще.
 
 Що ми маємо Розглянемо сірий набір значків більш докладно. Для кожного значка є чотири версії, відповідні різної щільності пікселів. Ви в програмі всього лише використовуєте кінцеве назву — наприклад R.id.ic_action_important , і Android сам вибирає потрібну папку. Це дуже зручно і виглядає приголомшливо в силу того, що на екранах для мобільних пристроїв ppi значно вище, ніж на звичайному моніторі. Зображення здається більш згладженим.
 
До речі кажучи, значки досить універсальні і їх можна використовувати не тільки в Action Bar.
 
Перша проблема, з якою я зіткнувся — немає спільного огляду всіх значків. Двадцять хвилин програмування — і вже готовий Java-код, який пробігається по каталогах і зчитує від туди значки, склеює їх в одну загальну картинку. Ось вона:
 
 
 
Тепер же — спробуємо їх розфарбувати. Я буду використовувати для цих цілей десктопну Java. Як би її не сварили, вона надає безліч готових і працюючих рішень. Будемо використовувати awt — бібліотеки для роботи з 2D графікою. Перше, що я зробив — довантажити картиночку в BufferedImage і пройшовся по кожному пікселю, виділивши його 4 складові (ARGB). Побіжний аналіз виведення показав, що картинка по суті використовує тільки один колір — сірий. І в тих місцях де саме зображення згладжено — просто зменшений альфа канал.
 
Виходячи з цього, щоб розфарбувати значок — нам потрібно всього лише замінити сірий колір на необхідний, без зачіпання альфа каналу. Я спробував взяти зірочку і розфарбувати її в синій колір, а потім протестувати на моєму пристрої — і вона відмінно там виглядала!
 
 Програма Попрацювавши ще якийсь час, я зробив такий скрипт, який переганяє всі значки з бібліотеки в заданий колір. Правда в каталозі повинні бути тільки значки і папки — нічого зайвого.
 
Думаю, що більшість Android-розробників мало хоча б невеликий досвід з десктопной Джаві — компіляція і запуск не викличе труднощів. В принципі, тут все просто.
 
 Main.java
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Main {
    static final int COLUMNS_COUNT = 15;
    static final String DIR_WITH_GRAY_IMAGES = "E:\\wsys\\prj\\ImagePainter\\test\\gray";
    static final String OUTPUT_DIR = "E:\\wsys\\prj\\ImagePainter\\test";
    static final Color myColor = new Color(177, 0, 140);//Цвет, в который перекрашиваем

    static List<File> fileList = new ArrayList<>();

    public static void main(String[] strings) throws Throwable {
        painter();
    }

    private static void outputImages(File dir) {
        for (File subDir : dir.listFiles()) {
            if (subDir.getName().contains("hdpi")) {
                File pngFile = subDir.listFiles()[0];
                fileList.add(pngFile);
                break;
            }
            if (subDir.isDirectory()) {
                outputImages(subDir);
            }
        }
    }

    private static void painter() throws Throwable {
        File dirWithImages = new File(DIR_WITH_GRAY_IMAGES);
        File outputDir = new File(OUTPUT_DIR);
        String nameFolder = Integer.toHexString(myColor.getRGB());

        for (File subDir : dirWithImages.listFiles()) {
            for (File drawable : subDir.listFiles()) {
                System.out.println(drawable);
                for (File pngFile : drawable.listFiles()) {
                    System.out.println(pngFile);
                    BufferedImage okImage = handlePngFile(pngFile, myColor);
                    String partPath = pngFile.getAbsolutePath().replace(dirWithImages.getAbsolutePath(), "");
                    File newPngPath = new File(outputDir.getAbsolutePath() + "\\" + nameFolder + "\\" + partPath);
                    newPngPath.mkdirs();
                    ImageIO.write(okImage, "png", newPngPath);
                }
            }
        }

        File targetDir = new File(outputDir, "\\" + nameFolder);
        outputImages(targetDir);
        ImageIO.write(getComplexImage(), "png", new File(targetDir, "all.png"));
    }

    private static BufferedImage getComplexImage() {
        BufferedImage bufferedImage = new BufferedImage(800, 500, BufferedImage.TYPE_INT_ARGB);
        Graphics g = bufferedImage.getGraphics();

        int i = 0;
        int j = 0;
        int counter = 0;
        try {
            for (File pngFile : fileList) {
                BufferedImage image = ImageIO.read(pngFile);
                g.drawImage(image, i, j, null);
                i += image.getWidth();
                counter++;
                if (counter == COLUMNS_COUNT) {
                    i = 0;
                    counter = 0;
                    j += image.getHeight();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bufferedImage;
    }

    private static BufferedImage handlePngFile(File pngFile, Color myColor) {
        try {
            BufferedImage image = ImageIO.read(pngFile);

            for (int i = 0; i < image.getWidth(); i++) {
                for (int j = 0; j < image.getHeight(); j++) {
                    Color pixelColor = new Color(image.getRGB(i, j), true);

                    int a = pixelColor.getAlpha();
                    //a += 50;//Повышаем интенсивность - уменьшаем прозрачность

                    if (pixelColor.getRed() != 0) {
                        int r = myColor.getRed();
                        int g = myColor.getGreen();
                        int b = myColor.getBlue();
                        Color newColor = new Color(r, g, b, a);
                        image.setRGB(i, j, newColor.getRGB());
                    }
                }
            }
            return image;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

 Архів і висновок Виклав вже перефарбовані в різні кольори значки — користуйтеся на здоров'я! Або ж можете розібратися зі скриптом і перефарбувати в той колір, який потрібен конкретно вам. І не забувайте про те, що всі значки з альфа каналом, відповідно на білому фоні вони будуть виглядати більш світлими, ніж той колір, який ви задали для них.
 
Крім того, виникла ідея написати скрипт, який існуючий великий значок змінює під різні розміри зі згладжуванням і розпихує по папках для різної щільності пікселів. Якщо немає готових і безкоштовних скриптів, які це роблять в автоматичному режимі — обов'язково напишу свій і викладу.
 
Як з'ясувалося в коментарях, існує сайт http://romannurik.github.io/AndroidAssetStudio/index.html який розфарбовує значки більш зручно і надає ще купу інших функцій. Правда він зобов'язує вказувати зворотне посилання при використанні і не вміє масово обробляти значки, так що в моєму підході теж є якийсь сенс.
    
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.