Android: Как получить пиксели одноканального 16-битного PNG битмапа
У меня есть файл PNG, созданный с помощью Python PIL, который содержит карту высот (положительные значения).
Формат: один канал (уровень серого) на 16 бит, следовательно, 16 бит на пиксель.
Я читаю файл на андроид с BitmapFactory.decodeStream(<...data input stream...>);
Я правильно получаю размер изображения через getWidth()
а также getHeight()
,
Однако, когда я зацикливаю пиксели, вызывающие getPixel(i,j)
Я получаю отрицательные значения, что-то вроде: -16776192 -16250872 -16250872 -16250872 -16250872 -16249848 ....
Вместо этого я ожидаю положительного значения от 0 до 65535.
Я обнаружил, что значение -16250872 в двоичном виде составляет 1111111111111111111111111111111111111111001110011001100000001000
Это показывает, что информация опирается на первые 16 младших значащих битов.
Я пробовал с getPixel(i,j)&0xffff
и я получаю правдоподобные значения, однако я не уверен насчет порядка байтов: я должен перевернуть 2 извлеченных байта?
Есть ли способ сделать это более элегантным и портативным способом этого преобразования?
ПРИМЕЧАНИЕ: файл не является цветным (RGBA) PNG, а представляет собой PNG-изображение уровня серого с одним 16-битным значением для каждого пикселя.
2 ответа
Я сам нашел решение, используя соображения, сделанные в этом посте: Android: загрузка битовой карты альфа-маски
По сути, если вы загружаете напрямую 16-битный PNG-файл серого уровня из фабрики растровых изображений, формат пикселей будет неправильным. Вам необходимо использовать 32-битный цветовой формат RGBA, установив для пикселя формат ARGB_8888. Затем вы должны получить все пиксели с помощью getPixel(i,j) и замаскировать целочисленное значение с помощью 0xffff. Таким образом, вы получите ожидаемые 16-битные значения.
Это часть кода, который я использовал:
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig= Bitmap.Config.ARGB_8888;
Bitmap bmp=BitmapFactory.decodeStream(entity.getContent(),null,opt);
int W=bmp.getWidth();
int H=bmp.getHeight();
int px;
for (int i = 0; i < H; i++)
for (int j = 0; j < W; j++)
{
px= bmp.getPixel(j, i)&0x0000ffff;//in px you will find a value between 0 and 65535
...
}
Я предполагаю, что вы пытаетесь получить RGB для пикселя в изображении. Если это правильно, то вы найдете следующее полезным.
Возвращает цвет в указанном месте. Выдает исключение, если x или y выходят за границы (отрицательные или>= для ширины или высоты соответственно).
Это цитата для Bitmap.getPixel();
Что нужно сделать, чтобы распечатать это так, чтобы оно было читаемым человеком. Я запрограммировал с Android, но не сделал это с Android. Я использовал следующую функцию для одной из моих программ.
public static int[] getRGBValue(BufferedImage bi, int x, int y) {
int argb = bi.getRGB(x, y);
int rgb[] = new int[] {
(argb >> 16) & 0xff, // red
(argb >> 8) & 0xff, // green
(argb ) & 0xff, // blue
};
return rgb;
}
public static String getStringOfRGB(int[] value) {
return "Color: (" + value[0] + ", " + value[1] + ", " + value[2] + ")";
}
Я не знаю точно, что вы пытаетесь сделать точно, поэтому приведенный выше код не ответит на ваш вопрос... но должен помочь вам найти свой ответ, как бы вы ни использовали данные пикселя.
Надеюсь это поможет!:)