简体   繁体   English

数组副本排除每个x元素

[英]Array copy exclude each x element

I am converting an RGBA image to RGB. 我正在将RGBA图像转换为RGB。 Using naive array copy: 使用天真数组副本:

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

But, as expected, it is ultra slow (in comparison to System.arraycopy() method), especially on an Android device. 但是,正如预期的那样,它是超慢的(与System.arraycopy()方法相比),尤其是在Android设备上。 Is there a trick to do it faster? 有没有一个技巧可以更快地完成它?

Use two indexes and System.arraycopy() , copying 3 elements each time: 使用两个索引和System.arraycopy() ,每次复制3个元素:

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

Should be significantly faster. 应该明显更快。 Not only does it get rid of the modulo and comparison, System.arraycopy() is implemented with native code, relying on memcpy which is going to be faster than individual assignments. 它不仅摆脱了模数和比较, System.arraycopy()是用本机代码实现的,依赖于memcpy ,它比单独的赋值更快。

Instead of 代替

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++];
}

This solution is far faster, because modulo operation and compare are more costfull. 这种解决方案要快得多,因为模运算和比较成本更高。

You should avoid the if statement, it does 2 operations. 你应该避免使用if语句,它会进行2次操作。
Start with i=0, i%4<3 means: 0,1,2, 4,5,6, 8,9,10. 从i = 0开始,i%4 <3表示:0,1,2,4,5,6,8,9,10。 Here's how I'd do: 这是我的方式:

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];
}

-> increments of i are the same - > i增量是相同的
tested with [ 0,1,2,3,4,5,6,7,8,9,10] return [0,1,2,4,5,6,8,9,10] test with array of 10,000,000 elements, run in a loop of 30 用[0,1,2,3,4,5,6,7,8,9,10]测试返回[0,1,2,4,5,6,9,9,10]测试,数组为10,000,000元素,以30的循环运行
original code: 3191ms 原码:3191ms
modified code: 1653ms 修改代码:1653ms
I've tested in C# so maybe the result would be different. 我已经在C#中测试过,所以结果可能会有所不同。 Btw, it's may not quite much an improvement. 顺便说一句,这可能不是一个很大的进步。

Not a well defined answer, but a pointer: Never done, and not entirely satisfying your request, but leave the conversion to BitmapFactory . 不是一个定义明确的答案,而是一个指针:从未完成,并且不完全满足您的请求,但将转换保留为BitmapFactory Entirely unsure, but: 完全不确定,但是:

Use a BitmapFactory to get an ARGB Bitmap from the bytes. 使用BitmapFactory从字节中获取ARGB位图。 If not mutable, then maybe no new allocation is done. 如果不可变,那么可能没有新的分配。 Might also be, that you first need to wrap the bytes into a Buffer. 也可能是,您首先需要将字节包装到Buffer中。

Then Bitmap.copy should be possible or so. 那么Bitmap.copy应该是可能的。

Some wild ideas: 一些疯狂的想法:

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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM