Предполагая, что я правильно о рамках Каталано, вы должны быть в состоянии переписать свои методы, как это:
private static void testIndexedColor() throws IOException {
BufferedImage bi = ImageIO.read(new File("test.png"));
FastBitmap input = new FastBitmap(bi);
Graphics2D g = bi.createGraphics();
try {
g.drawImage(input.toBufferedImage(), 0, 0, null);
}
finally {
g.dispose(); // Good practice ;-)
}
ImageIO.write(bi, "PNG", new File("test_result.png"));
}
По крайней мере, вы должны уйти с фиксированной палитрой и артефактов.
Однако, вероятно, это будет еще изменить PPI (но это не повлияет на пиксели). И даже в некоторых случаях изображение может быть записано как PNG без палитры.
Update: Кажется PNGImageWriter
(через PNGMetadata
) на самом деле вновь пишет IndexColorModel
, содержащий идеальный оттенки серого, в оттенках серого PNG по умолчанию. Обычно это хорошая идея, так как вы уменьшаете размер файла, не записывая блок PLTE. Вы должны быть в состоянии обойти эту проблему, путем передачи метаданных от оригинала, наряду с данными пикселей изображения, чтобы инструктировать писатель держать IndexColorModel
(то есть писать PLTE кусок.):
private static void testIndexedColor() throws IOException {
File in = new File("test.png");
File out new File("test_result.png");
try (ImageInputStream input = ImageIO.createImageInputStream(in);
ImageOutputStream output = ImageIO.createImageOutputStream(out)) {
ImageReader reader = ImageIO.getImageReaders(input).next(); // Will fail if no reader
reader.setInput(input);
ImageWriter writer = ImageIO.getImageWriter(reader); // Will obtain a writer that understands the metadata from the reader
writer.setOutput(output); // Will fail if no writer
// Now, the important part, we'll read the pixel AND metadata all in one go
IIOImage image = reader.readAll(0, null); // PNGs only have a single image, so index 0 is safe
// You can now access and modify the image data using:
BufferedImage bi = (BufferedImage) image.getRenderedImage();
FastBitmap fb = new FastBitmap(bi);
// ...do stuff...
Graphics2D g = bi.createGraphics();
try {
g.drawImage(fb.toBufferedImage(), 0, 0, null);
}
finally {
g.dispose();
}
// Write pixel and metadata back
writer.write(null, image, writer.getDefaultWriteParam());
}
}
Этот должен (в качестве бонуса) также сохраняйте свой ИЦП как есть.
PS: Для производства кода, вы также хотите dispose()
в reader
и writer
выше, но я оставил его, чтобы сосредоточиться и избежать дальнейшего обсуждения на try/finally
. ;-)
Что здесь происходит, так это то, что ваш '' '' '' BufferedImage' создан с по умолчанию 'IndexColorModel' (который бывает того же цвета, что и 256-цветная« веб-безопасная »палитра). Вам нужно получить записи IndexColorModel или палитры в той или иной форме, начиная с 'input'. Если это невозможно, в худшем случае вы можете снова прочитать входной файл, используя «ImageIO», чтобы получить его (медленнее) или даже создать «лучшую» палитру для измененного изображения, используя некоторую форму уменьшения цвета (медленнее) , Не уверен, что произошло с ИЦП (или, если это даже имеет значение). – haraldK
PS: Является ли библиотека, на которую вы ссылаетесь, * Catal ** ** ** без рамки? – haraldK
Также стоит упомянуть, конкретное изображение черно-белое. Когда я открываю его в режиме gimp, он говорит о индексированном цвете. Однако, если я загружу это изображение с помощью ImageIO в BufferedImage и сразу же напишу тот же файл BufferedImage в файл с помощью ImageIO, режим станет мистическим в оттенках серого. Я даже не уверен, что оттенки серого и индексированный цвет являются взаимоисключающими или могут использовать палитру изображений с оттенками серого? И почему это преобразование происходит? –