【问题标题】:While creating two very similar images one is corrupted with artifacts在创建两个非常相似的图像时,其中一个被伪影损坏
【发布时间】:2014-04-08 12:58:00
【问题描述】:

简而言之,该算法需要三张图像: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;
    }
}

【问题讨论】:

    标签: java rgb bufferedimage


    【解决方案1】:

    很抱歉没有给出“答案”。但我很确定几乎没有任何人愿意或能够调试一段涉及

    的代码
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    

    ...8 级嵌套和 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)
        {
        }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-09
      • 1970-01-01
      • 2017-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-01
      相关资源
      最近更新 更多