Как выполнить НЕСКОЛЬКО составных эффектов с использованием Graphics2D - PullRequest
4 голосов
/ 12 марта 2009

У меня есть два разных объекта javax.swing.Icon, и я хочу создать новую иконку, которая является смесью этих двух. Я хочу, чтобы композит был МНОГОКРАТНЫМ эффектом, похожим на то, что вы получите в любом фотошоп-подобном приложении для редактирования изображений, когда выберете эту опцию. В частности, для каждого пикселя, если у вас есть цвет Ca и Cb из изображения 1 и изображения соответственно

Ca = (Ra, Ga, Ba) Cb = (Rb, Gb, Bb)

я хочу, чтобы вывод был

Cc = (Ra Rb, Ga Gb, Ba * Bb)

Я хочу сделать это на лету (в режиме реального времени), поэтому я должен делать это, используя только операции Graphics2D. Я посмотрел на AlphaComposite и не вижу, что это можно сделать. У кого-нибудь есть идеи?

Ответы [ 2 ]

3 голосов
/ 13 марта 2009

Что вам нужно, так это «умножить» альфа-композит. Для удобства я недавно задал тот же вопрос о «экранном» эффекте. Мне указали на http://www.curious -creature.org / 2006/09/20 / new-blendings -modes-for-java2d / , в котором есть требуемый кратный композит.

1 голос
/ 07 ноября 2015

Поскольку большинство ответов на этот вопрос указывают на множество сторонних ресурсов, я подумал, что предоставлю полную реализацию здесь. По сути, это то же самое, что и большие библиотеки режимов наложения, которые вы, возможно, видели, но я убрал абстракцию только для реализации конкретного режима наложения.

Некоторые примечания по поводу кода ниже:

  • Для использования просто g.setComposite(MultiplyComposite.Multiply)

  • Класс MultiplyComposite реализует как Composite, так и CompositeContext, поскольку для моих нужд между ними нет ничего особенного. Если у вас есть режим смешивания, в котором параметры можно регулировать или смешивание применяется по-разному, вам нужно будет реализовать два класса отдельно.

  • Этот код работает только с 32-разрядными целочисленными буферами. Вам необходимо изменить это для работы с 16-битным цветом (смещение и маскировка для 5/6 битов вместо 8)

  • Этот код работает с последним байтом в качестве альфа-канала. Вам нужно будет изменить код для работы с данными без альфа-канала (24-битный).

  • Сдвиг вправо на 8 в методе mixPixel - это быстрый способ деления на 256. Например. (a * b) >> 8 вместо (a * b) / 256

  • Пиксели обрабатываются по одной строке за раз слева направо. Если у вас есть больше памяти, вы можете изменить это, чтобы обрабатывать весь буфер сразу.


public class MultiplyComposite implements Composite, CompositeContext {
    protected void checkRaster(Raster r) {
        if (r.getSampleModel().getDataType() != DataBuffer.TYPE_INT) {
            throw new IllegalStateException("Expected integer sample type");
        }
    }

    @Override
    public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
        checkRaster(src);
        checkRaster(dstIn);
        checkRaster(dstOut);

        int width = Math.min(src.getWidth(), dstIn.getWidth());
        int height = Math.min(src.getHeight(), dstIn.getHeight());
        int x, y;
        int[] srcPixels = new int[width];
        int[] dstPixels = new int[width];

        for (y=0; y < height; y++) {
            src.getDataElements(0, y, width, 1, srcPixels);
            dstIn.getDataElements(0, y, width, 1, dstPixels);

            for (x=0; x < width; x++) {
                dstPixels[x] = mixPixel(srcPixels[x], dstPixels[x]);
            }

            dstOut.setDataElements(0, y, width, 1, dstPixels);
        }
    }

    private static int mixPixel(int x, int y) {
        int xb = (x) & 0xFF;
        int yb = (y) & 0xFF;
        int b = (xb * yb) / 255;

        int xg = (x >> 8) & 0xFF;
        int yg = (y >> 8) & 0xFF;
        int g = (xg * yg) / 255;

        int xr = (x >> 16) & 0xFF;
        int yr = (y >> 16) & 0xFF;
        int r = (xr * yr) / 255;

        int xa = (x >> 24) & 0xFF;
        int ya = (y >> 24) & 0xFF;
        int a = Math.min(255, xa + ya);

        return (b) | (g << 8) | (r << 16) | (a << 24);
    }


    @Override
    public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints) {
        return this;
    }

    @Override
    public void dispose() {

    }

    public static final MultiplyComposite Multiply = new MultiplyComposite();

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...