Мне нужно прочитать и обработать большое количество PNG-файлов, которые находятся в оттенках серого. Под этим я подразумеваю, что если они открываются в Photoshop или GIMP, режим изображения - Grayscale - не RGB-изображение с оттенками серого.Чтение черно-белых изображений изображений PNG без искажений
ImageIO, похоже, не достиг этого. Кажется, что все файлы изображений рассматриваются как sRGB. Это изменяет значения оттенков серого. Мне нужно прочитать и обработать эти файлы PNG, где (в моем коде) каждый пиксель имеет точно такое же значение, как если бы я открыл файл в градациях серого в Photoshop или GIMP. Кто-нибудь знает о каком-то программном обеспечении с открытым исходным кодом, которое может это сделать, пожалуйста? Или лучше, как добиться этого, используя ImageIO.
Дополнительная информация:
Я использую getRGB() на BufferedImage. Базовый пиксель в файле изображения равен 0x86. Я понимаю, что это не обязательно соответствует пикселю ARGB, содержащему 0xFF868686, так как это зависит от яркости/гамма. Однако, в отсутствие геттера с аргументом типа гамма, я ожидал, что сопоставление по умолчанию будет соответствовать ARGB = 0xFF868686. Если я использую GIMP или Photoshop для преобразования изображения в оттенках серого, содержащего пиксель со значением 0x86 в RGB, тогда пиксель становится 0xFF868686. Это очевидный дефолт.
Однако ImageIO, похоже, использует странную гамму (независимо от того, нравится вам это или нет) с изображениями в градациях серого, что делает оттенки серого очень легкими после отображения в ARGB. В этом случае 0x86 сопоставляется с 0xFFC0C0C0. Это не только очень легко, но также может привести к значительной потере данных, так как многие значения оттенков серого могут быть сопоставлены с меньшим количеством значений ARGB. Единственный раз, когда это искажение не приведет к потере данных, для очень темных изображений в оттенках серого. Соответствующая гамма зависит от контекста, разные физические среды будут искажать яркость по-разному. Однако при отсутствии контекста отображение: 0x86 -> 0xFF868686 имеет наибольшее значение - свидетельствуйте о выборе, сделанных для GIMP и Photoshop.
Оставив проблему getRGB() с одной стороны, загрузив изображение в градациях серого (используя ImageIO.read (imageFile)), метод getType() BufferedImage возвращает Type = 0 (Custom), а не Type = 10 (TYPE_BYTE_GRAY), как я и ожидал.
Короче говоря, ImageIO, похоже, не обеспечивает приятный и простой способ высокого уровня чтения и управления существующими изображениями в оттенках серого. Я надеялся, что вам не придется возиться под обложками с Rasters, ICC, сэмплированием и т. Д. Также я не хочу, чтобы физически преобразовывать все файлы изображений в оттенках серого в RGB. Все, что я хотел, это метод load() API для BufferedImage, который работает так же, как открытый файл в GIMP или Photoshop. Я не смог этого добиться. Я надеюсь, что это мое невежество, а не ограничение Java ImageIO.
Возможное решение:
После копаться я следующее, чтобы предложить в качестве возможного метода для низкоуровневого доступа к градации серого значения:
final File imageFile = new File("test.png");
final BufferedImage image = ImageIO.read(imageFile);
// --- Confirm that image has ColorSpace Type is GRAY and PixelSize==16
final Raster raster = image.getData();
// --- Confirm that: raster.getTransferType() == DataBuffer.TYPE_BYTE
for(int x=0, xLimit=image.getWidth(); x < xLimit; x++) {
for(int y=0, yLimit=image.getHeight(); y < yLimit; y++) {
final Object dataObject = raster.getDataElements(x, y, null);
// --- Confirm that dataObject is instance of byte[]
final byte[] pixelData = (byte[]) dataObject;
// --- Confirm that: pixelData.length == 2
final int grayscalePixelValue = pixelData[0] & 0xFF;
final int grayscalePixelAlpha = pixelData[1] & 0xFF;
// --- Do something with the grayscale pixel data
}
}
документация Javadoc не велика, поэтому я не могу гарантировать, что это правильно, но, похоже, это работает для меня.
Как вы проверяете значения пикселей вашего изображения? Если вы вызываете 'image.getRGB (x, y)', то есть по определению значения ARGB в цветовом пространстве sRGB (независимо от того, как пиксели хранятся в памяти или на диске). Если вы получаете растровый и базовый буфер данных, вы должны увидеть исходные значения серого. Пожалуйста, напишите какой-нибудь код с тем, что вы пробовали до сих пор, и, возможно, мы сможем его решить. Также опубликуйте хотя бы одно образцовое изображение. :-) – haraldK
Спасибо за ваш добрый ответ. Я добавил дополнительную информацию в оригинальную публикацию. –
Если вы хотите попробовать третью сторону (мой) lib: https://github.com/leonbloy/pngj/ – leonbloy