rgb 值通过什么计算发生变化?

By what calculation are the rgb values changing?

这里我有一些代码可以创建一个隐藏另一个图像的图像。 我打印出一些 rgb 值以查看变化(在实现函数 chopToHide 和函数 shift 之后,但我不明白这些数字是通过什么计算改变的)。这段代码是将一个图像隐藏在另一个图像中(隐写术)的更大程序的一部分。
这是我工作的环境:http://www.dukelearntoprogram.com/course1/example/index.php

var start = new SimpleImage("astrachan.jpg");
var hide = new SimpleImage("duvall.jpg");

print (start);
print(hide);
print ("width and height of astrachan picture");
print (start.getHeight(), start.getWidth());
print ("width and height of duvall picture")
print (hide.getHeight(), hide.getWidth());


var cropWidth = start.getWidth();
if (hide.getWidth() < cropWidth) {
    cropWidth = hide.getWidth();
 }
var cropHeight = start.getHeight();
if (hide.getHeight() < cropHeight) {
    cropHeight = hide.getHeight();
}
start = crop(start,cropWidth, cropHeight);
hide = crop(hide,cropWidth, cropHeight);
print(start);
print(hide);

function crop(image, width, height){
     var n = new SimpleImage(width,height);
     for(var p of image.values()){
       var x = p.getX();
       var y = p.getY();
       if (x < width && y < height){
     var np = n.getPixel(x,y);
     np.setRed(p.getRed());
     np.setBlue(p.getBlue());
     np.setGreen(p.getGreen()); 
}
     }
     return n;
}

//print (start);
//print(hide);
print ("cropped width and height of astrachan picture");
print (start.getHeight(), start.getWidth());
print ("cropped width and height of duvall picture")
print (hide.getHeight(), hide.getWidth());



function chopToHide(image){ 
    for(var px of image.values()){ 
        px.setRed(pixchange(px.getRed())); 
        px.setGreen(pixchange(px.getGreen())); 
        px.setBlue(pixchange(px.getBlue())); 
    } 
    return image; 
}

function pixchange(pixval){ 
    var x = Math.floor(pixval/16) * 16; 
    return x; 
} 

 function shift(oldImage){
    var newImage = new SimpleImage(oldImage.getWidth(), oldImage.getHeight());
    for(var oldPixel of oldImage.values()){
        var x = oldPixel.getX();
        var y = oldPixel.getY();
        var newPixel = newImage.getPixel(x, y);
        newPixel.setRed( Math.floor(oldPixel.getRed()/16) );
        newPixel.setGreen( Math.floor(oldPixel.getGreen()/16) );
        newPixel.setBlue( Math.floor(oldPixel.getBlue()/16) );
    }
    return newImage;
}   









print("before applying the chopToHide function to the image start:");
     for(i = 1; i <= 100; i+=20 ){
    var pixel = start.getPixel(i, i+5);
    print("pixel at (" + pixel.getX() + "," + pixel.getY() + ")-> R= " +    
pixel.getRed() + " : G= " + pixel.getGreen() + " : B= " + pixel.getBlue() );
}
//print (start);
start = chopToHide(start);

 print("After applying the chopToHide function to the image start:");
    for(i = 1; i <= 100; i+=20 ){
    var pixel = start.getPixel(i, i+5);
    print("pixel at (" + pixel.getX() + "," + pixel.getY() + ")-> R= " +   
pixel.getRed() + " : G= " + pixel.getGreen() + " : B= " + pixel.getBlue() );
} 
//print (start);
//print (hide);

print("Before applying the shift function to the image hide:");
for(i = 1; i <= 100; i+=20 ){
    var pixel = hide.getPixel(i, i+5);
    print("pixel at (" + pixel.getX() + "," + pixel.getY() + ")-> R= " +    
pixel.getRed() + " : G= " + pixel.getGreen() + " : B= " + pixel.getBlue() );
}
hide = shift(hide);

print("After applying the shift function to the image hide:");
    for(i = 1; i <= 100; i+=20 ){
        var pixel = hide.getPixel(i, i+5);
        print("pixel at (" + pixel.getX() + "," + pixel.getY() + ")-> R= " 
+ pixel.getRed() + " : G= " + pixel.getGreen() + " : B= " +   
pixel.getBlue() );
}

此代码的想法是将每个颜色通道的颜色范围从 0..255(8 位,"byte")减少到 0..15(4 位,"nybble") 两张图片上的每个颜色通道,然后将两个字节合并为一个字节。颜色在高半字节的图片将给出可察觉的颜色变化(以 16 为增量);隐藏在低nybble中的图片会在不知不觉中遮挡主图像素的颜色。

公式应该是:

steganoImageColour = (overtImageColour & 240) | (covertImageColour >> 4)

或等效(但没有那么快):

steganoImageColour = (Math.floor(overtImageColour / 16) * 16) +
                     Math.floor(covertImageColour / 16)

要提取隐蔽图像,只需将低 nybble 提升到高:

reconstructedCovertImageColour = (steganoImageColour & 15) << 4

或等价地,

reconstructedCovertImageColour = (steganoImageColour % 16) * 16

例如,如果显性图像中有一个黄绿色像素 (173 255 47),隐性图像中有一个浅天蓝色像素 (135 206 250),则生成的像素为 (168 252 47) , 仍然非常接近原来的黄绿色,但是可以从中重构 (128 192 240),非常接近原来的淡天蓝色。

<div style="background-color: rgb(173,255,47)">overt (green-yellow)</div>
<div style="background-color: rgb(135,206,250)">covert (light sky blue)</div>
<div style="background-color: rgb(168,252,47)">stegano (close enough to green-yellow)</div>
<div style="background-color: rgb(128,192,240)">reconstructed covert (close enough to light sky blue)</div>