BufferedImage отключить сглаживание при уменьшении цвета с помощью пользовательской ColorModel?

Я создаю изображение с пользовательской палитрой (другими словами, с пользовательской цветовой моделью):

 BufferedImage img = new BufferedImage(orgImg.getWidth(), orgImg.getHeight(),
      BufferedImage.TYPE_BYTE_INDEXED,
      cm);
 Graphics2D g2 = img.createGraphics();
    g2.drawImage(orgImg, 0, 0, null);
    g2.dispose();

Обратите внимание, что переменная «cm» — это моя пользовательская цветовая модель с палитрой из 256 цветов.

Переменная "orgImg" представляет собой полноцветное (24 больших argb) изображение.

Приведенный выше код приводит к копии "orgImg" с 256 цветами с использованием палитры, определенной в цветовой модели.

Это прекрасно работает.

Но java использует сглаживание для уменьшения цветов. Можно ли отключить этот дизеринг?

Обратите внимание, что мне нужно использовать свою собственную палитру, чтобы окончательные изображения соответствовали определенной цветовой палитре.


person Tinus Tate    schedule 20.10.2017    source источник


Ответы (1)


При рисовании изображения в объект Graphics2D различными аспектами рендеринга можно управлять с помощью RenderingHints. Вы должны иметь возможность отключить сглаживание с помощью методов Graphics2D.setRenderingHint или setRenderingHints, передав значения KEY_DITHERING и VALUE_DITHER_DISABLE в качестве параметров:

Graphics2D g2 = img.createGraphics();
// Disable dithering
g2.setRenderingHint(RenderingHint.KEY_DITHERING, RenderingHint.VALUE_DITHER_DISABLE);
g2.drawImage(orgImg, 0, 0, null);
g2.dispose();

Дополнительные сведения см. в руководстве по Java2D.

PS: обратите внимание, что методы/класс называются "hint".

Это может больше не быть проблемой, но в прошлом я сталкивался с тем, что отключение дизеринга с помощью подсказки, как указано выше, не работало. Также невозможно указать используемый алгоритм дизеринга, обычно используется только «упорядоченный» или «алмазный» шаблон дизеринга.

Поэтому я реализовал свои собственные версии различных алгоритмов сглаживания для этого использования. См. CopyDither (который выполняет поиск ближайшего совпадения для каждого пикселя, вероятно, то, что вам нужно здесь) и DiffusionDither (который реализует сглаживание ошибок "Флойда-Стейнберга"). Обе упомянутые реализации основаны на быстром обратном поиске значений цвета. К сожалению, IndexColorModel по умолчанию не выполняет быстрый обратный поиск. Поэтому я реализовал специальный класс и для этого случая, см. InverseColorMapIndexColorModel.

Использование:

BufferedImage img = new BufferedImage(orgImg.getWidth(), orgImg.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, cm);
CopyDither noDither = new CopyDither(new InverseColorMapIndexColorModel(cm)); // cm must be IndexColorModel
noDither.filter(orgImg, img);
person Harald K    schedule 21.10.2017
comment
Использование подсказок рендеринга в этом особом случае не работает (в других/в большинстве случаев оно работает), KEY_DITHERING игнорируется. В Интернете есть несколько тем, посвященных этой проблеме, но ни одна из них не предлагает решения с хорошей производительностью. Просто попробуйте. - person Tinus Tate; 21.10.2017
comment
Я только что видел, как вы отредактировали свой вопрос ;-) Я собираюсь взглянуть на ваши классы, они выглядят хорошо, потому что используются растры, что хорошо для производительности. Я буду держать вас в курсе! - person Tinus Tate; 21.10.2017
comment
Ура @haraldK, сегодня утром потребовалось некоторое время, чтобы разобраться во всем, но после того, как вы нашли ваши зависимости от maven, все прошло гладко. Я использовал CopyDither со своей цветовой моделью, и он сгенерировал версию без сглаживания. И это тоже довольно быстро, мой хакерский setRgb(getRgb) для каждого пикселя на 50% медленнее. Еще раз спасибо! - person Tinus Tate; 23.10.2017
comment
@TinusTate Хороший материал! Прошло некоторое время с тех пор, как я написал этот код, поэтому не стесняйтесь предлагать улучшения. ???? - person Harald K; 23.10.2017
comment
Я планирую просмотреть все ваши уроки, связанные с изображениями, я уже видел несколько интересных. Они также хорошо иллюстрируют, как использовать некоторые из более продвинутых классов изображений Java. Спасибо за создание такой полезной библиотеки. - person Tinus Tate; 23.10.2017