在创建两个非常相似的图像时,其中一个被伪像破坏

时间:2014-04-08 12:58:01

标签: java rgb bufferedimage

简而言之,该算法需要三个图像:source1,source2,hidden。然后它隐藏source1和source2中的隐藏图像(生成output1和output2)。如果将output1放在output2上,则可以看到隐藏的图像。然而,output2以某种方式被破坏,而一般的想法工作,隐藏的图像(和source1)可以在其中看到。 (这很难,但可能)

我正在尝试从http://datagenetics.com/blog/november32013/index.html实施算法。 (向下滚动到“这个魔法如何工作?”跳过介绍)。

编辑:事实证明setTwo方法以某种方式获得相同的空白。执行和重新随机化blank2可以解决问题。但是,我仍然不知道相同的数据是如何进入的......毕竟,在调用setTwo算法之前,我总是随机化两个不同的数字..任何人都能看到它的原因吗?

EDIT2:在每次调用setTwo之前添加检查以测试参数是否相等。检查每次都失败,而setTwo中的检查会解决问题。我不知道数据是如何破坏的。

1st image - source1, source2

2nd image - hidden

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;
    }
}

1 个答案:

答案 0 :(得分:1)

抱歉不给出“答案”。但我很确定任何人都不愿意或能够调试一段涉及的代码

                            }
                        }
                    }
                }
            }
        }
    }
}

......八级嵌套和28次nextInt

无论你在那里做什么:我认为这更容易。 很多更容易。通过仔细查看2x2像素的模式,您可以识别非常简单的规则:初始模式是

WB
BW

“掷硬币”确定像素是否水平翻转,以产生

BW
WB

在第二张图像中,如果(并且仅当)输入像素为黑色,则这些图案仅垂直翻转。

以下是一个示例实现,也许您会发现它很有帮助。

enter image description here

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)
    {
    }


}