位运算(含lsb水印相关运用)

学习内容来自:

https://www.bilibili.com/video/BV1YT4y117AH/?share_source=copy_web&vd_source=615eb03d223cf19a23232ca4a7b70c1e

https://www.runoob.com/w3cnote/bit-operation.html


二元运算符

& 位于

两十进制数,转换为二进制,按位比较,两个都为1才为1,否则为0,再把二进制结果转换为十进制,得到最终结果。

(有0则0,全1才1)

| 位或

两个都为0为0,否则为1。

(有1则1,全0才0)

^ 异或

两个不同时为1,否则为0。

注:与0相异或值不变。

(同0异1)

<< 左移

x << y -- 将x转换为二进制,所有位向左偏移y位,若不足y位补0。

>> 右移

x >> y -- 与左移类似,不同的是:若x是非负数,高位补0;若x是负数,则高位补1。
e.g.: 1100 >> 3 == 1

一元运算符

~按位取反

对当前数字转换为二进制以后,1变0,0变1。

位运算的用途

清零

与一个各位都为零的数值相与,结果为零。

取一个二进制数的指定位

比如取数 X=1010 1110 的低4位,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行&按位与运算(X&Y=0000 1110)即可得到X的指定位。

x & 1,x | 0 都可以得二进制x的某位。
前者在lsb水印中的使用例:
(编码时改变原图r、g最后一位为0,再将数字水印按位与最后一位的0进行 | 或运算,就可以将数字水印嵌入图片r、g值中)

    # 将两个数值的二进制表示依次嵌入到前10个像素的R和G通道的最低有效位中
    for i in range(10):
        pixel = list(pixels[i])
        pixel[0] = (pixel[0] & 0xFE) | int(bin_num1[i]) # R通道。前面不变,最后一位变0。
        pixel[1] = (pixel[1] & 0xFE) | int(bin_num2[i]) # G通道
        pixels[i] = tuple(pixel)  # 将修改后的像素值放回到像素列表中

后者在lsb水印中的使用例:
(解码时将原图r、g &按位与1,得到r、g最后一位,即嵌入的数字水印。)

    # 获取前10个像素的R和G通道的LSB
    n1 = ""
    n2 = ""
    pixels = list(img.getdata())[:10]
    for pixel in pixels:
        r_lsb = pixel[0] & 1
        g_lsb = pixel[1] & 1 # 返回的是十进制,下面再转换为字符串以连接
        n1 += str(r_lsb)
        n2 += str(g_lsb)

判断奇偶

最未位为0就是偶数,为1就是奇数。
故可用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数。

把一个数据的某些位设置为1

比如将数 X=1010 1110 的低4位设置为1,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行按位或运算(X|Y=1010 1111)即可得到。

翻转指定位

比如将数 X=1010 1110 的低4位进行翻转,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行异或运算(X^Y=1010 0001)即可得到。

发表评论