数组副本排除每个x元素

时间:2014-01-15 20:26:17

标签: java android arrays rgb rgba

我正在将RGBA图像转换为RGB。使用天真数组副本:

for (int j=0, i=0; i<argbBytes.length; i++){
    if (i%4 < 3) {
        thumbRGB888[j++] = argbBytes[i];
    }
}

但是,正如预期的那样,它是超慢的(与System.arraycopy()方法相比),尤其是在Android设备上。有没有一个技巧可以更快地完成它?

4 个答案:

答案 0 :(得分:3)

使用两个索引和System.arraycopy(),每次复制3个元素:

for (int i = 0, j = 0; i < argbBytes.length; i += 4, j += 3)
{
    System.arraycopy(argbBytes, i, thumbRGB888, j, 3);
}

应该明显更快。它不仅摆脱了模数和比较,System.arraycopy()是用本机代码实现的,依赖于memcpy,它比单个赋值更快。

答案 1 :(得分:0)

而不是

if (i%4 < 3)

DO

for (int j=0, i=0; i<argbBytes.length; i++){
   thumbRGB888[j++] = argbBytes[i++];
   thumbRGB888[j++] = argbBytes[i++];
   thumbRGB888[j++] = argbBytes[i++];
}

这个解决方案要快得多,因为模运算和比较成本更高。

答案 2 :(得分:0)

你应该避免使用if语句,它会进行2次操作 从i = 0开始,i%4&lt; 3表示:0,1,2,4,5,6,8,9,10。 我就是这样做的:

int div = 4;
int n = argbBytes.length - argbBytes.length%div;
int i=0;
int j=0;

for (; i<n; i+=div){
    // i = 0, 4, 8 ... then i, i+1,i+2 should pass (i%4<3)  
    thumbRGB888[j++] = argbBytes[i];
    thumbRGB888[j++] = argbBytes[i+1];
    thumbRGB888[j++] = argbBytes[i+2];
}

for(;i<argbBytes.length;i++){
    //i=n,n+1,n+2, since n%4==0 then (i%4<3) is passed
    thumbRGB888[j++] = argbBytes[i];
}

- &GT; i的增量是相同的 用[0,1,2,3,4,5,6,7,8,9,10]测试返回[0,1,2,4,5,6,8,9,10] 使用10,000,000个元素的数组进行测试,以30的循环运行 原码:3191ms
修改代码:1653ms
我已经在C#中测试过,所以结果可能会有所不同。顺便说一句,这可能不是一个很大的改进。

答案 3 :(得分:0)

不是定义明确的答案,而是指针: 从未完成,并且不完全满足您的请求,但请将转换保留为BitmapFactory。完全不确定,但是:

使用BitmapFactory从字节中获取ARGB位图。如果不可变,那么可能没有新的分配。也可能是,您首先需要将字节包装到缓冲区中。

然后Bitmap.copy应该是可能的。

一些疯狂的想法:

BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inMutable = true; // Bitmap generated mutable.
opts.inPreferredConfig = Bitmap.Config.ARGB_8888; // I hope not BGRA.
Bitmap bmARGB = BitmapFactory.decodeByteArray(argbBytes, 0, argbBytes.length,
    opts);

bmARGB.setHasAlpha(false);

DisplayMetrics display = ...;
int[] colors = null; // Palette
Bitmap bmRGB = bmARBG.createBitmap(display, colors, width, height,
    Bitmap.Config.RGB_565); // 16 bit colors only!
bmARGB.recycle();