简而言之,该算法需要三个图像:source1,source2,hidden。然后它隐藏source1和source2中的隐藏图像(生成output1和output2)。如果将output1放在output2上,则可以看到隐藏的图像。然而,output2以某种方式被破坏,而一般的想法工作,隐藏的图像(和source1)可以在其中看到。 (这很难,但可能)
我正在尝试从http://datagenetics.com/blog/november32013/index.html实施算法。 (向下滚动到“这个魔法如何工作?”跳过介绍)。
编辑:事实证明setTwo方法以某种方式获得相同的空白。执行和重新随机化blank2可以解决问题。但是,我仍然不知道相同的数据是如何进入的......毕竟,在调用setTwo算法之前,我总是随机化两个不同的数字..任何人都能看到它的原因吗?
EDIT2:在每次调用setTwo之前添加检查以测试参数是否相等。检查每次都失败,而setTwo中的检查会解决问题。我不知道数据是如何破坏的。
3rd image - output 1 - correct
4th image - output 2 - problems
package visualcryptography;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JLabel;
/**
*
* @author Ugnius
*/
public class VisualCryptography {
BufferedImage sourceOne;
BufferedImage sourceTwo;
BufferedImage hiddenImage;
BufferedImage outputOne;
BufferedImage outputTwo;
GUI loadingBar;
static final int black = java.awt.Color.BLACK.getRGB();
static final int white = java.awt.Color.WHITE.getRGB();
static final int whiteToWrite = (new Color(255, 255, 255, 0)).getRGB();
Random r = new Random();
//Color cl;
/**
* @param args the command line arguments
*/
public VisualCryptography(BufferedImage source1, BufferedImage source2, BufferedImage hidden, GUI loadingBar) throws Exception {
if ((source1.getHeight() != source2.getHeight()) || (source2.getHeight() != hidden.getHeight())) {
throw new Exception();
}
if ((source1.getWidth() != source2.getWidth()) || (source2.getWidth() != hidden.getWidth())) {
throw new Exception();
}
sourceOne = source1;
sourceTwo = source2;
hiddenImage = hidden;
this.loadingBar = loadingBar;
//cl = java.awt.Color.WHITE;
//cl = new Color(cl.getRed(), cl.getGreen(), cl.getBlue(), 0);
//white = cl.getRGB();
//System.out.println("this is WHITE:" + cl.getRGB());
//System.out.println("this is my white:" + (new Color(0,0,0).getRGB()));
//white = 1;
//cl = new Color(255, 255, 255, 255);
//white = cl.getRGB();
//white = -1;
//white = 16777215;
//white = java.awt.Color.WHITE.getRGB();
//byte alpha = (byte) 0xff;
//int mc = (alpha << 24) | 0x00ffffff;
//white = white & mc;
//System.out.println("this is my transparent white:" + white);
//System.out.println("this is black" + black);
}
public void process() throws IOException {
int total = sourceOne.getHeight();
outputOne = new BufferedImage(sourceOne.getWidth() * 2, sourceOne.getHeight() * 2, BufferedImage.TYPE_INT_ARGB);
outputTwo = new BufferedImage(sourceTwo.getWidth() * 2, sourceTwo.getHeight() * 2, BufferedImage.TYPE_INT_ARGB);
for (int height = 0; height < sourceOne.getHeight(); height++) {
System.out.println(height + " / " + total);
//loadingBar.repaint();
for (int width = 0; width < sourceOne.getWidth(); width++) {
//Random r = new Random();
//if ((height > 87) && (width > 190)){
//System.out.println("Hello");
//}
if (hiddenImage.getRGB(width, height) != white) {
//when the hidden image pixel is BLACK
//the combined two cypgher images (OR) have to have all four subpixels set.
if ((sourceOne.getRGB(width, height) != white) && (sourceTwo.getRGB(width, height) != white)) {
//when bouth source images also have a black pixel, this is easy. Both cypher images need to have three out of
//the four subpixels set. The only constraint is that the missing subpixel is not the same on both layers.
//one pixel is randomly selected on the first layer, and one is randomly select from the other three on the
//second layer
int randomized = r.nextInt(4);
//randomized = 0; top left
//randomized = 1; top right
//randomized = 2; bottom left
//randomized = 3; bottom right
this.setThree(width, height, randomized, outputOne);
int newRandomized = r.nextInt(4);
while (randomized == newRandomized) {
newRandomized = r.nextInt(4);
}
this.setThree(width, height, newRandomized, outputTwo);
} else {
if ((sourceOne.getRGB(width, height) != white) && (sourceTwo.getRGB(width, height) == white)) {
//When the first image has a black pixel (requiring three subpixels set), and the second image
//has a white pixel (requiring two subpixels set), as above, first, a random single subpixel is
//selected on the black layer to remove. Next two subpixels are randomly selected on the second
//layer with the constraint that one of the selected subpixels is the same as the gap in the
//first layer. In this way, when the two are combined, four black subpixels are displayed.
int randomized = r.nextInt(4);
//randomized = 0; top left
//randomized = 1; top right
//randomized = 2; bottom left
//randomized = 3; bottom right
this.setThree(width, height, randomized, outputOne);
int random1 = r.nextInt(4);
while (random1 == randomized) {
random1 = r.nextInt(4);
}
int random2 = r.nextInt(4);
while ((random2 == randomized) || random1 == random2) {
random2 = r.nextInt(4);
}
this.setTwo(width, height, random1, random2, outputTwo);
} else {
if ((sourceOne.getRGB(width, height) == white) && (sourceTwo.getRGB(width, height) != white)) {
//the opposite happens when the first layer is white, and the second layer is black
int randomized = r.nextInt(4);
//randomized = 0; top left
//randomized = 1; top right
//randomized = 2; bottom left
//randomized = 3; bottom right
this.setThree(width, height, randomized, outputTwo);
int random1 = r.nextInt(4);
while (random1 == randomized) {
random1 = r.nextInt(4);
}
int random2 = r.nextInt(4);
while ((random2 == randomized) || random1 == random2) {
random2 = r.nextInt(4);
}
this.setTwo(width, height, random1, random2, outputOne);
} else {
if ((sourceOne.getRGB(width, height) == white) && (sourceTwo.getRGB(width, height) == white)) {
int randomized = r.nextInt(4);
int randomized1 = r.nextInt(4);
while (randomized == randomized1) {
randomized1 = r.nextInt(4);
}
this.setTwo(width, height, randomized, randomized1, outputOne);
int[] remaining = new int[2];
int counter = 0;
int number = 0;
while (counter != 2) {
if ((number != randomized) && (number != randomized1)) {
remaining[counter] = number;
counter++;
}
number++;
}
this.setTwo(width, height, remaining[0], remaining[1], outputTwo);
}
}
}
}
} else {
//when the hidden image pixel is WHITE
//the combined two cypher images (OR) have to have any three subpixels set
if ((sourceOne.getRGB(width, height) != white) && (sourceTwo.getRGB(width, height) != white)) {
//When both source images have a black pixel, this is easy. Both cypher images need to have
//three out of the four subpixels set, and these need to be the same subpixels. Three subpixels
//are randomly selected and these are set on both of the cypher image layers.
int random = r.nextInt(4);
this.setThree(width, height, random, outputOne);
this.setThree(width, height, random, outputTwo);
} else {
if ((sourceOne.getRGB(width, height) != white) && (sourceTwo.getRGB(width, height) == white)) {
//When the first image has a black pixel (requiring three subpixels set), and the second image
//has a white pixel (requiring two subpixels set), as above, first, three random subpixels
//are selected on the first layer. Next one of these three subpixels is randomly selected for
//removal and this pattern is used on the second layer.
int random = r.nextInt(4);
this.setThree(width, height, random, outputOne);
int random1 = r.nextInt(4);
while (random == random1) {
random1 = r.nextInt(4);
}
this.setTwo(width, height, random, random1, outputTwo);
} else {
if ((sourceOne.getRGB(width, height) == white) && (sourceTwo.getRGB(width, height) != white)) {
int random = r.nextInt(4);
this.setThree(width, height, random, outputTwo);
int random1 = r.nextInt(4);
while (random == random1) {
random1 = r.nextInt(4);
}
this.setTwo(width, height, random, random1, outputOne);
} else {
if ((sourceOne.getRGB(width, height) == white) && (sourceTwo.getRGB(width, height) == white)) {
//Finally, if both source pixels are white (requiring two subpixels set), two are selected
//at random on the first layer, then one of these is duplicated on the second layer, and a
//second random subpixel is selected on the second layer (from the two white subpixels not
//selected on the first layer). Both layers have two subpixels, and when combined, there are
//three subpixels visbile.
int random = r.nextInt(4);
//this.setThree(width, height, random, outputTwo);
int random1 = r.nextInt(4);
while (random == random1) {
random1 = r.nextInt(4);
}
this.setTwo(width, height, random, random1, outputOne);
int random2 = r.nextInt(4);
if (random2 == random) {
random2 = r.nextInt(4);
}
this.setTwo(width, height, random, random2, outputTwo);
}
}
}
}
}
}
}
}
void setThree(int x, int y, int blank, BufferedImage im) {
//blank = 0; top left
//blank = 1; top right
//blank = 2; bottom left
//blank = 3; bottom right
im.setRGB(2 * x, 2 * y, black);
im.setRGB(2 * x + 1, 2 * y, black);
im.setRGB(2 * x, 2 * y + 1, black);
im.setRGB(2 * x + 1, 2 * y + 1, black);
switch (blank) {
case 0:
im.setRGB(2 * x, 2 * y, whiteToWrite);
break;
case 1:
im.setRGB(2 * x + 1, 2 * y, whiteToWrite);
break;
case 2:
im.setRGB(2 * x, 2 * y + 1, whiteToWrite);
break;
case 3:
im.setRGB(2 * x + 1, 2 * y + 1, whiteToWrite);
break;
}
}
private void setTwo(int x, int y, int blank1, int blank2, BufferedImage im) {
//blank = 0; top left
//blank = 1; top right
//blank = 2; bottom left
//blank = 3; bottom right
im.setRGB(2 * x, 2 * y, black);
im.setRGB(2 * x + 1, 2 * y, black);
im.setRGB(2 * x, 2 * y + 1, black);
im.setRGB(2 * x + 1, 2 * y + 1, black);
switch (blank1) {
case 0:
im.setRGB(2 * x, 2 * y, whiteToWrite);
break;
case 1:
im.setRGB(2 * x + 1, 2 * y, whiteToWrite);
break;
case 2:
im.setRGB(2 * x, 2 * y + 1, whiteToWrite);
break;
case 3:
im.setRGB(2 * x + 1, 2 * y + 1, whiteToWrite);
break;
}
switch (blank2) {
case 0:
im.setRGB(2 * x, 2 * y, whiteToWrite);
break;
case 1:
im.setRGB(2 * x + 1, 2 * y, whiteToWrite);
break;
case 2:
im.setRGB(2 * x, 2 * y + 1, whiteToWrite);
break;
case 3:
im.setRGB(2 * x + 1, 2 * y + 1, whiteToWrite);
break;
}
}
public BufferedImage[] getOutput() {
BufferedImage[] output = new BufferedImage[2];
output[0] = outputOne;
output[1] = outputTwo;
return output;
}
}
答案 0 :(得分:1)
抱歉不给出“答案”。但我很确定任何人都不愿意或能够调试一段涉及的代码
}
}
}
}
}
}
}
}
......八级嵌套和28次nextInt
。
无论你在那里做什么:我认为这更容易。 很多更容易。通过仔细查看2x2像素的模式,您可以识别非常简单的规则:初始模式是
WB
BW
“掷硬币”确定像素是否水平翻转,以产生
BW
WB
在第二张图像中,如果(并且仅当)输入像素为黑色,则这些图案仅垂直翻转。
以下是一个示例实现,也许您会发现它很有帮助。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class VisualCryptographyTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new BorderLayout());
BufferedImage image = createImage("Password");
JLabel originalImageLabel =
new JLabel(new ImageIcon(image));
f.getContentPane().add(originalImageLabel, BorderLayout.NORTH);
BufferedImage cypherImage0 = createCypherImage(image, true);
BufferedImage cypherImage1 = createCypherImage(image, false);
VisualCryptographyPanel visualCryptographyPanel =
new VisualCryptographyPanel(cypherImage0, cypherImage1);
f.getContentPane().add(visualCryptographyPanel, BorderLayout.CENTER);
f.setSize(800, 800);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static BufferedImage createCypherImage(BufferedImage image, boolean first)
{
Random random = new Random(0);
int w = image.getWidth();
int h = image.getHeight();
BufferedImage cypherImage = new BufferedImage(
w+w,h+h,BufferedImage.TYPE_INT_ARGB);
final int BLACK = Color.BLACK.getRGB();
final int WHITE = 0;
for (int y=0; y<h; y++)
{
for (int x=0; x<w; x++)
{
int cx = x+x;
int cy = y+y;
int rgb = image.getRGB(x, y);
int p00 = WHITE;
int p10 = BLACK;
int p01 = BLACK;
int p11 = WHITE;
int temp = 0;
boolean flipH = random.nextBoolean();
if (flipH)
{
temp=p00; p00=p10; p10=temp;
temp=p01; p01=p11; p11=temp;
}
if (first && rgb == Color.BLACK.getRGB())
{
temp=p00; p00=p01; p01=temp;
temp=p10; p10=p11; p11=temp;
}
cypherImage.setRGB(cx+0, cy+0, p00);
cypherImage.setRGB(cx+1, cy+0, p10);
cypherImage.setRGB(cx+0, cy+1, p01);
cypherImage.setRGB(cx+1, cy+1, p11);
}
}
return cypherImage;
}
private static BufferedImage createImage(String message)
{
float fontSize = 50.0f;
int w = 300;
int h = 100;
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = image.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, w, h);
g.setColor(Color.BLACK);
g.setFont(g.getFont().deriveFont(fontSize));
g.drawString(message, 30, 75);
g.dispose();
return image;
}
}
class VisualCryptographyPanel extends JPanel
implements MouseMotionListener, KeyListener
{
private final BufferedImage cypherImage0;
private final BufferedImage cypherImage1;
private int imageX = 0;
private int imageY = 0;
VisualCryptographyPanel(
BufferedImage cypherImage0,
BufferedImage cypherImage1)
{
setFocusable(true);
this.cypherImage0 = cypherImage0;
this.cypherImage1 = cypherImage1;
addMouseMotionListener(this);
addKeyListener(this);
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
int x = (getWidth() - cypherImage0.getWidth()) / 2;
int y = (getHeight() - cypherImage0.getHeight()) / 2;
g.drawImage(cypherImage0, x, y, null);
g.drawImage(cypherImage1, imageX, imageY, null);
}
@Override
public void mouseMoved(MouseEvent e)
{
imageX = e.getX();
imageY = e.getY();
repaint();
}
@Override
public void mouseDragged(MouseEvent e)
{
}
@Override
public void keyTyped(KeyEvent e)
{
}
@Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_UP)
{
imageY--;
}
if (e.getKeyCode() == KeyEvent.VK_DOWN)
{
imageY++;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT)
{
imageX--;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
{
imageX++;
}
repaint();
}
@Override
public void keyReleased(KeyEvent e)
{
}
}