Javascript隐写术:将图像隐藏在图像中
我已经在这个程序上停留了一段时间,我完全不知道什么是错误的,我需要修复什么。我试图使用隐写术对封面图像中的秘密图像进行加密,然后对秘密图像进行解密。我得到了部分代码,我必须实现Javascript隐写术:将图像隐藏在图像中,javascript,image,decode,encode,steganography,Javascript,Image,Decode,Encode,Steganography,我已经在这个程序上停留了一段时间,我完全不知道什么是错误的,我需要修复什么。我试图使用隐写术对封面图像中的秘密图像进行加密,然后对秘密图像进行解密。我得到了部分代码,我必须实现encodePixel和decodepoixel函数以及“助手函数” 当我运行程序时,生成的图像是完全黑色的,而不是秘密图像。我不知道我的错误在哪里,它是否在编码或解码函数中,或者它是否在助手函数中 以下是我已经实现的功能: /* * Encodes the given secret pixel into the low
encodePixel
和decodepoixel
函数以及“助手函数”
当我运行程序时,生成的图像是完全黑色的,而不是秘密图像。我不知道我的错误在哪里,它是否在编码或解码函数中,或者它是否在助手函数中
以下是我已经实现的功能:
/*
* Encodes the given secret pixel into the low bits of the
* RGB values of the given cover pixel
* Returns the modified cover pixel
*/
function encodePixel(coverPixel, secretPixel) {
var redBit = secretPixel[RED];
var greenBit = secretPixel[GREEN];
var blueBit = secretPixel[BLUE];
if(redBit >= 128){
setLowestBit(coverPixel[RED], 1);
}else{
setLowestBit(coverPixel[RED], 0);
}
if(blueBit >= 128){
setLowestBit(coverPixel[BLUE], 1);
}else{
setLowestBit(coverPixel[BLUE], 0);
}
if(greenBit >= 128){
setLowestBit(coverPixel[GREEN], 1);
}else{
setLowestBit(coverPixel[GREEN], 0);
return coverPixel;
}
/*
* Extracts the RGB values for a secret pixel from the low bits
* of the given cover pixel
* Returns the resulting secret pixel
*/
function decodePixel(coverPixel) {
var secretPixel = [0, 0, 0];
var redBit = getLowestBit(coverPixel[RED]);
var greenBit = getLowestBit(coverPixel[GREEN]);
var blueBit = getLowestBit(coverPixel[BLUE]);
if(redBit == 1){
setLowestBit(secretPixel[RED], 255);
}else{
setLowestBit(secretPixel[RED], 0);
}
if(blueBit == 1){
setLowestBit(secretPixel[BLUE], 255);
}else{
setLowestBit(secretPixel[BLUE], 0);
}
if(greenBit == 1){
setLowestBit(secretPixel[GREEN], 255);
}else{
setLowestBit(secretPixel[GREEN], 0);
}
return secretPixel;
}
//=========HELPER FUNCTIONS==========\\
// Returns true if the given value is even, false otherwise
function isEven(value) {
return value % 2 == 0;
}
/*
* Given a number, return the lowest bit in the binary representation
* of the number.
* Returns either a 0 or a 1
*/
function getLowestBit(value) {
if(isEven(value)){
return 0;
}else{
return 1;
}
}
/*
* Given a number, return a new number with the same underlying bits
* except the lowest bit is set to the given bitValue.
*/
function setLowestBit(value, bitValue) {
if(bitValue == 0) {
// If value is even, the lowest bit is already 0.
if(isEven(value)) {
return value;
}
// Otherwise, the lowest bit is 1. We subtract 1 to set it to 0.
else {
return value - 1;
}
}
else {
// If value is odd, the lowest bit is already 1
if(!isEven(value)) {
return value;
}
// Otherwise, the lowest bit is 0. We add 1 to set it to 1.
else {
return value + 1;
}
}
}
这是代码的其余部分,我不必更改
//===============================CONSTANTS===========================\\
// Constants for the images
var ORIGINAL_URL = "https://codehs.com/static/img/zebra.jpg";
var SECRET_IMAGE_URL = "https://codehs.com/static/img/about/goldengate.jpg";
// Constants for pixel indices
var RED = 0;
var GREEN = 1;
var BLUE = 2;
// Constants for colors
var MAX_COLOR_VALUE = 255;
var MIN_COLOR_VALUE = 0;
var COLOR_THRESHOLD = 128;
//********************STARTER CODE BELOW******************************
// Constants for spacing
var X_GAP = 10;
var Y_GAP = 25;
var TEXT_Y_GAP = 4;
var IMAGE_WIDTH = getWidth() / 2 - X_GAP * 2;
var IMAGE_HEIGHT = getHeight() / 3 - Y_GAP * 1.1;
var IMAGE_X = 10;
var IMAGE_Y = 25;
// Image width cannot be odd, it messes up the math of the encoding
if(IMAGE_WIDTH % 2 == 1) {
IMAGE_WIDTH -= 1;
}
// We need to wait for the image to load before modifying it
var IMAGE_LOAD_WAIT_TIME = 50;
function start() {
// Set up original image
var original = new WebImage(ORIGINAL_URL);
original.setSize(IMAGE_WIDTH, IMAGE_HEIGHT);
original.setPosition(IMAGE_X, IMAGE_Y);
// Set up secret image
var secret = new WebImage(SECRET_IMAGE_URL);
secret.setSize(IMAGE_WIDTH, IMAGE_HEIGHT);
secret.setPosition(IMAGE_X + original.getWidth() + X_GAP, IMAGE_Y);
// Set up the cover image
// (identical to original, but will be modified to encode the secret image)
var cover = new WebImage(ORIGINAL_URL);
var coverX = getWidth() / 2 - IMAGE_WIDTH / 2;
cover.setSize(IMAGE_WIDTH, IMAGE_HEIGHT);
cover.setPosition(IMAGE_X + IMAGE_WIDTH / 2, IMAGE_Y + Y_GAP + IMAGE_HEIGHT);
// Add originals
add(original);
add(secret);
// Add the cover image that will be used for encrypting the secret image
add(cover);
// Wait for images to load before encrypting and decrypting
setTimeout(function(){
encrypt(cover, secret);
decrypt(cover);
}, IMAGE_LOAD_WAIT_TIME);
// Add labels for each image
var originalLabel = new Text("Original Cover Image", "11pt Arial");
originalLabel.setPosition(original.getX(), original.getY() - TEXT_Y_GAP);
add(originalLabel);
var secretLabel = new Text("Original Secret Image", "11pt Arial");
secretLabel.setPosition(secret.getX(), secret.getY() - TEXT_Y_GAP);
add(secretLabel);
var coverLabel = new Text("Cover Image with Secret Image encoded inside", "11pt Arial");
coverLabel.setPosition(getWidth() / 2 - coverLabel.getWidth() / 2, cover.getY() - TEXT_Y_GAP);
add(coverLabel);
var resultLabel = new Text("Resulting Secret Image decoded from Cover Image", "11pt Arial");
resultLabel.setPosition(getWidth() / 2 - resultLabel.getWidth() / 2, cover.getY() + IMAGE_HEIGHT + Y_GAP - TEXT_Y_GAP );
add(resultLabel);
}
/*
* Encrypts the secret image inside of the cover image.
* For each pixel in the cover image, the lowest bit of each
* R, G, and B value is set to a 0 or 1 depending on the amount of
* R, G, and B in the corresponding secret pixel.
* If an R, G, or B value in the secret image is between 0 and 127,
* set a 0, if it is between 128 and 255, set a 1.
*/
function encrypt(cover, secret) {
// Make sure cover and secret are the same size.
var width = cover.getWidth();
var height = cover.getHeight();
secret.setSize(width, height);
// Loop over each pixel in the image
for(var x = 0; x < width; x++) {
for(var y = 0; y < height; y++) {
// Get the pixels at this location for both images
var coverPixel = cover.getPixel(x, y);
var secretPixel = secret.getPixel(x, y);
// Modify the cover pixel to encode the secret pixel
var newCoverPixel = encodePixel(coverPixel, secretPixel);
// Update this pixel in the cover image to have the
// secret bit encoded
cover.setRed(x, y, newCoverPixel[RED]);
cover.setGreen(x, y, newCoverPixel[GREEN]);
cover.setBlue(x, y, newCoverPixel[BLUE]);
}
}
}
/*
* Decrypts a secret image from an encoded cover image.
*/
function decrypt(coverImage) {
// secretImage will start off the same as the cover image.
// As we loop over the coverImage to discover the secret embedded image,
// we will update secretImage pixel by pixel
var secretImage = new WebImage(coverImage.filename);
// We need to add secretImage to the canvas before we can modify it
secretImage.setSize(coverImage.getWidth(), coverImage.getHeight());
secretImage.setPosition(coverImage.getX(), coverImage.getY() + coverImage.getHeight() + Y_GAP);
add(secretImage);
// Wait for secretImage to load on the canvas before we start
// modifying its pixels.
setTimeout(function(){
computeSecretImage(coverImage, secretImage);
}, IMAGE_LOAD_WAIT_TIME);
}
/*
* Set the pixels in the image secret based on the lowest
* bit values in the pixels of the image cover.
*/
function computeSecretImage(cover, secret) {
// Loop over every pixel in the cover image
for(var x = 0; x < cover.getWidth(); x++) {
for(var y = 0; y < cover.getHeight(); y++) {
//Get the current pixel of the cover image
var coverPixel = cover.getPixel(x, y);
// Compute the secretPixel from this cover pixel
var secretPixel = decodePixel(coverPixel);
// Update the pixel in the secret image to match the computed secret pixel
secret.setRed(x, y, secretPixel[RED]);
secret.setGreen(x, y, secretPixel[GREEN]);
secret.setBlue(x, y, secretPixel[BLUE]);
}
}
}
//==============================================常数===========================\\
//图像的常数
var ORIGINAL_URL=”https://codehs.com/static/img/zebra.jpg";
var SECRET_IMAGE_URL=”https://codehs.com/static/img/about/goldengate.jpg";
//像素索引常数
var-RED=0;
绿色变量=1;
var蓝=2;
//颜色常数
var MAX_COLOR_VALUE=255;
var MIN_COLOR_值=0;
var-COLOR_阈值=128;
//********************起动器代码如下******************************
//间距常数
var X_间隙=10;
var Y_GAP=25;
var TEXT_Y_GAP=4;
var IMAGE_WIDTH=getWidth()/2-X_GAP*2;
var IMAGE_HEIGHT=getHeight()/3-Y_GAP*1.1;
var图像_X=10;
var图像_Y=25;
//图像宽度不能是奇数,它会弄乱编码的数学
如果(图像宽度%2==1){
图像宽度-=1;
}
//我们需要等待图像加载后再修改它
var映像加载等待时间=50;
函数start(){
//设置原始图像
var original=新的WebImage(原始URL);
原始设置大小(图像宽度、图像高度);
原始设置位置(图像X、图像Y);
//树立秘密形象
var secret=新的WebImage(secret\u IMAGE\u URL);
设置大小(图像宽度、图像高度);
secret.setPosition(IMAGE_X+original.getWidth()+X_GAP,IMAGE_Y);
//设置封面图像
//(与原始图像相同,但将进行修改以对机密图像进行编码)
var cover=新的网络图像(原始URL);
var coverX=getWidth()/2-图像宽度/2;
封面尺寸(图像宽度、图像高度);
封面设置位置(图像X+图像宽度/2,图像Y+图像间隙+图像高度);
//添加原件
增加(原件);
添加(机密);
//添加将用于加密机密图像的封面图像
增加(封面);
//在加密和解密之前,请等待图像加载
setTimeout(函数(){
加密(封面、秘密);
解密(封面);
},图像加载等待时间);
//为每个图像添加标签
var originalLabel=新文本(“原始封面图像”,“11pt Arial”);
originalLabel.setPosition(original.getX(),original.getY()-TEXT_Y_GAP);
添加(原始标签);
var secretLabel=新文本(“原始机密图像”,“11pt Arial”);
secretLabel.setPosition(secret.getX(),secret.getY()-TEXT_Y_GAP);
添加(secretLabel);
var coverLabel=新文本(“内部编码秘密图像的封面图像”,“11pt Arial”);
coverLabel.setPosition(getWidth()/2-coverLabel.getWidth()/2,cover.getY()-TEXT\u Y\u GAP);
添加(封面标签);
var resultLabel=新文本(“从封面图像解码的结果秘密图像”,“11pt Arial”);
resultLabel.setPosition(getWidth()/2-resultLabel.getWidth()/2,cover.getY()+图像高度+Y间距-文本Y间距);
添加(结果标签);
}
/*
*加密封面图像内部的机密图像。
*对于封面图像中的每个像素,每个像素的最低位
*R、G和B值设置为0或1,具体取决于
*对应的秘密像素中的R、G和B。
*如果机密图像中的R、G或B值介于0和127之间,
*设置0,如果介于128和255之间,则设置1。
*/
函数加密(封面、秘密){
//确保封面和秘密尺寸相同。
var width=cover.getWidth();
var height=cover.getHeight();
秘密。设置大小(宽度、高度);
//在图像中的每个像素上循环
对于(变量x=0;xfunction encodePixel(coverPixel, secretPixel) {
var returnedPixel = [0,0,0];
var redBit = secretPixel[RED];
var greenBit = secretPixel[GREEN];
var blueBit = secretPixel[BLUE];
if(redBit >= 128){
returnedPixel[RED] = setLowestBit(coverPixel[RED], 1);
}else{
returnedPixel[RED] = setLowestBit(coverPixel[RED], 0);
}
// repeat for blue/green
//
// then
return returnedPixel;
}
function decodePixel(coverPixel) {
var secretPixel = [0, 0, 0];
var redBit = getLowestBit(coverPixel[RED]);
var greenBit = getLowestBit(coverPixel[GREEN]);
var blueBit = getLowestBit(coverPixel[BLUE]);
if(redBit == 1){
secretPixel[RED] = 255;
}
// repeat for green and blue
//
// then
return secretPixel;
}
const encodePixel = (coverPixel, secretPixel) => coverPixel.map((part, index) => (part & 254) | ((secretPixel[index] >> 7) & 1));
const decodePixel = coverPixel => coverPixel.map(part => (part & 1) * 255);
var encodePixel = function encodePixel(coverPixel, secretPixel) {
return coverPixel.map(function (part, index) {
return (part & 254) | ((secretPixel[index] >> 7) & 1);
});
};
var decodePixel = function decodePixel(coverPixel) {
return coverPixel.map(function (part) {
return (part & 1) * 255;
});
};