Индексированная цветовая модель по существу перечисляет все цвета, которые могут использоваться в BufferedImage, с их значениями RGB.
Каждый столбец в
// red, light green, dark green, blue, white, black
new byte[]{-100, 0, 0, 0, -1, 0}, // red part
new byte[]{ 0, -100, 60, 0, -1, 0}, // green part
new byte[]{ 0, 0, 0, -100, -1, 0} // blue part
соответствует одному цвету - я добавил их в строку комментария.
В конечном итоге в конечном изображении будут использоваться только эти цвета, все остальное будет приближено к ближайшему цвету или шаблону из двух ближайших цветов:
(Изображение похищено из Ответ Рекина .)
Если вы хотите уменьшить не только 6 цветов, но и большее количество, вам просто нужно перечислить больше из них. Вы можете использовать здесь предварительно определенный список или адаптировать их по статистике исходного изображения (например, если изображение состоит в основном из голубого неба, включите здесь несколько синих оттенков, но не так много других цветов). Или выберите одну из нескольких предопределенных палитр, вид которой дает наименьшее отличие от исходного изображения.
Вместо использования IndexedColorModel вы также можете использовать одну из других реализаций ColorModel. Например, это будет 64-цветное пространство с 4 уровнями прозрачности, равномерно распределенными (я думаю), использующими один байт на пиксель (два бита на цвет):
new DirectColorModel(8, 0xC0, 0x30, 0x0C, 0x03);
В этом случае для прозрачности будет использоваться только один бит, вместо зеленого - три бита (которые человеческие глаза видят более четко):
new DirectColorModel(8, 0xC0, 0x38, 0x06, 0x01);
Я не тестировал их вместе с кодировщиком PNG, пожалуйста, сделайте это.