Android SetPixels() Объяснение и пример?

Я пытаюсь установить область пикселей в изменяемой битовой карте другого цвета в моем приложении для Android. К сожалению, я не могу заставить setPixels() работать должным образом. Я постоянно получаю ArrayOutOfBoundsExceptions. Я думаю, что это может иметь какое-то отношение к шагу, но я действительно не уверен. Это единственный параметр, который я до сих пор не понимаю. Единственный другой пост, который я видел на setPixels (не на setPixel), находится здесь: drawBitmap () и setPixels(): какой шаг? и это не помогло мне. Я попытался установить шаг как 0, как ширину растрового изображения, как ширину растрового изображения - область, которую я пытаюсь нарисовать, и она все еще падает. Вот мой код:

public void updateBitmap(byte[] buf, int offset, int x, int y, int width, int height) {
    // transform byte[] to int[]
    IntBuffer intBuf = ByteBuffer.wrap(buf).asIntBuffer();
    int[] intarray = new int[intBuf.remaining()];
    intBuf.get(intarray);                                       

    int stride = ??????
    screenBitmap.setPixels(intarray, offset, stride, x, y, width, height); // crash here

Мое растровое изображение изменчиво, поэтому я знаю, что это не проблема. Я также уверен, что мой байтовый массив правильно преобразован в целочисленный массив. Но я продолжаю получать ArrayOutOfBoundsExceptions и не понимаю почему. Пожалуйста, помогите мне разобраться в этом

РЕДАКТИРОВАТЬ - вот как я создаю ложный ввод:

int width = 1300;
int height = 700;
byte[] buf = new byte[width * height * 4 * 4]; // adding another * 4 here seems to work... why?     
for (int i = 0; i < width * height * 4 * 4; i+=4) {
    buf[i] = (byte)255;
    buf[i + 1] = 3;
    buf[i + 2] = (byte)255;
    buf[i + 3] = 3;         
}
//(byte[] buf, int offset, int x, int y, int width, int height)  - for reference        
siv.updateBitmap(buf, 0, 0, 0, width, height);

Таким образом, ширина и высота - это правильное количество дюймов (по крайней мере, так должно быть).

EDIT2 - вот код для оригинального создания screenBitmap:

public Bitmap createABitmap() {
int w = 1366;
int h = 766;

byte[] buf = new byte[h * w * 4];

for (int i = 0; i < h * w * 4;i+=4) {
        buf[i] = (byte)255;
    buf[i+1] = (byte)255;
    buf[i+2] = 0;
    buf[i+3] = 0;
}

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

IntBuffer intBuf = ByteBuffer.wrap(buf).asIntBuffer();  
int[] intarray = new int[intBuf.remaining()];
intBuf.get(intarray);                                           

Bitmap bmp = Bitmap.createBitmap(metrics, w, h, itmap.Config.valueOf("ARGB_8888"));
bmp.setPixels(intarray, 0, w, 0, 0, w, h);
return bmp;
}

Кажется, работает в этом случае, не уверен, в чем разница

2 ответа

Короче думаю,stride ширина изображения в пикселях.

длинный

Что я беру из документации, алгоритм должен работать примерно так:

public void setPixels (int[] pixels, 
            int offset, 
            int stride, 
            int x, 
            int y, 
            int width, 
            int height)
    for (int rowIndex = 0; rowIndex < height; rowIndex++) {
        int rowStart = offset + stride * rowIndex; // row position in pixels
        int bitmapY = y + rowIndex; // y position in the bitmap
        for (int columnIndex = 0; columnIndex < width; columnIndex++) {
            int bitmapX = x + columnIndex; // x position in the bitmap
            int pixelsIndex = rowStart + columnIndex; // position in pixels
            setPixel(bitmapX, bitmapY, pixels[pixelsIndex]);

        }
    }
}

По крайней мере, это то, что я бы сделал с этими аргументами, потому что это позволяет вам иметь один pixelsв качестве источника и вырезать разные изображения разных размеров. Не стесняйтесь поправлять алгоритм, если я ошибаюсь.

Итак, допустим, у вас есть изображение с pixelsWidth а также pixelsHeight в pixels. Затем вы хотите скопировать раздел вpixelsX а также pixelsY с width а также height к bitmap на позиции bitmapX а также bitmapY. Это должен быть звонок:

bitmap.setPixels(
    pixelsWidth * pixelsY + pixelsX, // offset
    pixelsWidth, // stride
    bitmapX, // x
    bitmapY, // y
    width,
    height)

Наверное должно быть

screenBitmap.setPixels(intarray, 0, width / 4, x, y, width / 4, height);

потому что вы конвертировали байт в int. ваша ошибка ArrayOutOfBoundsExceptions. проверить, подходит ли размер intBuf.remaining() = width * height / 4,

Если вы пытаетесь рисовать на растровом изображении, лучше всего отказаться от этого метода и использовать вместо него холст:

Canvas canvas = new Canvas(screenBitmap);

Затем вы можете нарисовать определенные точки (если вы хотите нарисовать пиксель) или другие фигуры, такие как прямоугольники, круги и т. Д.:

canvas.drawPoint(x, y, paint);

так далее

Надеюсь это поможет.

Другие вопросы по тегам