【问题标题】:Android SetPixels() Explanation and Example?Android SetPixels() 解释和例子?
【发布时间】:2013-10-01 22:11:55
【问题描述】:

我正在尝试在我的 android 应用程序中将可变位图中的像素区域设置为不同的颜色。不幸的是,我无法让 setPixels() 正常工作。我不断收到 ArrayOutOfBoundsExceptions。我认为这可能与步幅有关,但我真的不确定。这是我仍然不明白的唯一参数。我在 setPixels(不是 setPixel)上看到的唯一其他帖子是:drawBitmap() and setPixels(): what's the stride?,但它对我没有帮助。我尝试将步幅设置为 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;
}

在这种情况下似乎可以工作,不知道有什么区别

【问题讨论】:

  • 步幅应该是宽度。这是一维数组中的数量,当它伪装成二维数组时,您需要向前下降一个。
  • 这不起作用,因为 setPixels() 需要一个 intarray。时期。您的 4 色样本字节数组正在变成各种深浅不一的蓝色。 0baaaaaaaarrrrrrrrrggggggggbbbbbbbbbb

标签: android bitmap


【解决方案1】:

我认为,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 作为源并剪切出不同大小的不同图像。 如果我错了,请随时更正算法。

所以,假设您在pixels 中有一个带有pixelsWidthpixelsHeight 的图像。 然后,您想将pixelsXpixelsY 处的部分与widthheight 复制到位置bitmapXbitmapYbitmap。 这应该是电话:

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

【讨论】:

    【解决方案2】:

    应该是这样的:

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

    因为您已将 byte 转换为 int。您的错误是 ArrayOutOfBoundsExceptions。检查大小是否intBuf.remaining() = width * height / 4

    【讨论】:

    • 我认为我的数组大小是正确的。如果我创建一个 1300 x 700 字节输入的假输入(因此 1300 x 700 x 4 字节 = 3,640,000),则会创建一个长度为 91,000 的 intarray,这是总数的四分之一。在 ARGB_8888 格式中,每个像素都是一个 32 位整数,因此 91,000 = 1300 x 700,因此应该有足够的像素数据填充位图的 1300x700 部分。但是,当我做 1300 x 700 x 4 x 4 像素时,它会填充适量的空间而不会崩溃。我的数学有什么问题吗? -编辑:请参阅上文了解我如何构造假输入
    • 您的代码在哪一行崩溃?intBuf.remaining() 或 screenBitmap.setPixels?你的步幅值是多少?无法显示
    • 宽度和高度值是否等于screenBitmap的大小?
    • 我的代码在 bitmap.setPixels(...) 上崩溃。我大步尝试了很多事情,但似乎没有一个对我通过套接字接收的数据有效。出于某种原因,当我在假数据中添加 4 倍的像素时,它会起作用。我不明白为什么我需要做 height * width * 16 来将位图的新部分写入我的图像。目前我正在通过套接字接收一个 20x20 像素的数据块。结果为 1600 字节(20 x 20 像素 x 4 字节/像素),我已验证为 400 个整数。所以从数字上看,它似乎应该工作,但它不是......
    • 您的 screenBitmap 的宽度和高度是多少?你是如何创建它的?
    【解决方案3】:

    如果您尝试在位图上绘图,最好的方法是放弃此方法并改用画布:

    Canvas canvas = new Canvas(screenBitmap);
    

    然后您可以绘制特定点(如果您想绘制像素),或其他形状,如矩形、圆形等:

    canvas.drawPoint(x, y, paint);
    

    希望这会有所帮助。

    【讨论】:

    • 好吧,我不是想在位图上绘图。我正在尝试模拟实时视频源,因此我将使用新的图像数据更新位图。所以我不想绘制,我想将像素设置为新值
    猜你喜欢
    • 2011-04-26
    • 1970-01-01
    • 2011-11-03
    • 2011-06-15
    • 1970-01-01
    • 2011-10-09
    • 2012-11-17
    • 1970-01-01
    • 2012-02-21
    相关资源
    最近更新 更多