将RGB转换为int的最有效方法?

时间:2014-08-06 13:41:25

标签: colors bit-manipulation rgb

我在各个地方遇到过以下RGB-to-int方法:

//r,g, and b are bytes
int c = r;
c = (C << 8) | g;
c = (c << 8) | b;
return c;

但说:

是否更有效率
return (r << 16) | (g << 8) | r;

似乎第一种方式会导致大量不必要的存储/加载指令。是不是每个人都喜欢第一种方式而不是第二种方式?

1 个答案:

答案 0 :(得分:1)

在第二个表达式中,你做了一个小错字:两次使用&#34; r&#34;,从不&#34; b&#34;。我想,你的意思是:

return (r << 16) | (g << 8) | b;

关于您的问题:结果非常依赖于您的计算机体系结构和编译器版本。我用clang CC,FreeBSD OS,-O3构建了两个版本。 源代码:

int rgb1(int r, int g, int b) {
  int c = r;
  c = (c << 8) | g;
  c = (c << 8) | b;
  return c;
}

int rgb2(int r, int g, int b) {
    return (r << 16) | (g << 8) | b;
}

unsigned int rgb3(unsigned int r, unsigned int g, unsigned int b) {
    return (r * 256*256) + (g * 256) + b;
}

汇编代码如下:

 rgb1:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
        sall    $8, %eax
        orl     12(%ebp), %eax
        sall    $8, %eax
        orl     16(%ebp), %eax
        popl    %ebp
        ret
        .size   rgb1, .-rgb1
        .p2align 4,,15
.globl rgb2
        .type   rgb2, @function
rgb2:
        pushl   %ebp
        movl    %esp, %ebp
        movl    12(%ebp), %eax
        movl    8(%ebp), %edx
        sall    $8, %eax
        orl     16(%ebp), %eax
        popl    %ebp
        sall    $16, %edx
        orl     %edx, %eax
        ret
        .size   rgb2, .-rgb2
        .p2align 4,,15
.globl rgb3
        .type   rgb3, @function
rgb3:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
        sall    $8, %eax
        addl    12(%ebp), %eax
        sall    $8, %eax
        addl    16(%ebp), %eax
        popl    %ebp
        ret

如您所见,第一个功能是9个指令,第二个功能是10.因此,第一个功能似乎更有效率。但是,在现实生活中,它很大程度上取决于您的编译器行为。 例如,rgb3()使用了许多数学运算,但编译器将其优化为非常接近rgb1()的东西。