Чтобы получить смещение в buffer.array()
для данного пикселя x
, y
в изображении размером width
x height
с bytesPerPixel
байтами на пиксель, используйте следующую формулу:
offsetForPixel = (y * width + x) * bytesPerPixel
Другими словами, первый элемент в массиве - это верхний левый пиксель, а следующие элементы - основные строки. Все данные для пикселя хранятся в соседних байтах и не распределяются по каналам. Это ответ на 1, 2 и 4 выше. Теперь давайте обсудим 3, где все становится сложнее.
Что вы получаете с Bitmap.copyPixelsToBuffer () - это представление необработанных растровых данных, используемое низкоуровневой библиотекой рисования Android skia . Это имеет три существенных последствия:
- Порядок каналов зависит от порядка байтов
- Каналы предварительно умножаются на альфа
- Способ упаковки каналов в содержащие типы данных настраивается
Последний пункт делает неудобным использование Bitmap.copyPixelsToBuffer()
вообще, если вы хотите проверить отдельные пиксели, потому что вы просто не можете знать, как Skia была настроена для упаковки каналов. В качестве эксперимента попробуйте этот код:
int inputPixel = 0x336699cc;
int[] pixels = new int[] { inputPixel };
Bitmap bm = Bitmap.createBitmap(pixels, 1, 1, Config.ARGB_8888);
ByteBuffer bb = ByteBuffer.allocate(4);
bm.copyPixelsToBuffer(bb);
Log.i("TAG", "inputPixel = 0x" + Integer.toHexString(inputPixel));
for (int i = 0; i < 4; i++) {
String byteString = "0x" + Integer.toHexString(bb.array()[i] & 0xff);
Log.i("TAG", "outputPixel byte " + i + " = " + byteString);
}
Когда я запускаю это, я получаю этот вывод:
I/TAG ( 1995): inputPixel = 0x336699cc
I/TAG ( 1995): outputPixel byte 0 = 0x14
I/TAG ( 1995): outputPixel byte 1 = 0x1f
I/TAG ( 1995): outputPixel byte 2 = 0x29
I/TAG ( 1995): outputPixel byte 3 = 0x33
Мы можем видеть, что мы имеем дело с прямым порядком байтов, что представление в памяти предварительно умножено и что каналы были переупорядочены с ARGB на RGBA (мотивированные в исходном коде skia тем, что в представление памяти как OpenGL).
Если вы хотите прочитать данные пикселей, я предлагаю вам использовать Bitmap.getPixels () . Существует некоторое копирование, но, по крайней мере, API указывает, как возвращаемые данные форматируются.