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>
这里我有一些代码可以创建一个隐藏另一个图像的图像。
我打印出一些 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>