0

这是我的代码,当您选择要裁剪的区域然后按回车键时,裁剪的图像与原始选定区域的大小/图片不同。

public class DragNDrop extends JFrame implements DropTargetListener {

private static final long serialVersionUID = 1872019741456690593L;

private Graphics g;
private BufferedImage image, origiImage;
private Rectangle area;
private Rectangle currentRect;
private Rectangle rectToDraw = null;
private Image buffer;

public static void main(String args[]) {
    new DragNDrop();
}

public DragNDrop() {
    super("Drop Test");
    setSize(300, 300);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setDropTarget(new DropTarget(getContentPane(), this));
    setVisible(true);

    CaptureListener listener = new CaptureListener();
    addMouseListener(listener);
    addMouseMotionListener(listener);
}

public void drop(DropTargetDropEvent dtde) {
    try {
        Transferable tr = dtde.getTransferable();
        DataFlavor[] flavors = tr.getTransferDataFlavors();
        dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
        Object list = tr.getTransferData(flavors[0]);
    list = list.toString().substring(1, list.toString().length()-1);
        if (isValidImage(list)) {
            Image droppedImage = Toolkit.getDefaultToolkit().getImage(list.toString());
            image = toBufferedImage(droppedImage);
            origiImage = toBufferedImage(droppedImage);
            area = new Rectangle(image.getWidth(), image.getHeight());
            if (droppedImage != null) {
                setSize(image.getWidth(), image.getHeight());
                dtde.dropComplete(true);
                addKeyListener(new KeyListener() {

                    @Override
                    public void keyTyped(KeyEvent e) {
                    }

                    @Override
                    public void keyReleased(KeyEvent e) {
                        if (e.getKeyCode() == 10) {
                            capture();
                        }
                    }

                    @Override
                    public void keyPressed(KeyEvent e) {

                    }
                });
                return;
            }
        }
        dtde.rejectDrop();
    } catch (Exception e) {
        dtde.rejectDrop();
    }
}

public void paint() {
    if (area != null && image != null) {
        g.clearRect(area.x, area.y, area.width, area.height);
        g.drawImage(image, 0, 0, null);
    }
    if (currentRect != null) {
        g.setColor(Color.RED);
        g.drawRect(rectToDraw.x, rectToDraw.y, rectToDraw.width, rectToDraw.height);
        g.setColor(new Color(255,255,255,150));
        g.fillRect(rectToDraw.x, rectToDraw.y, rectToDraw.width, rectToDraw.height);
    }
}

@Override
public void paint(Graphics gr) {
    if (buffer == null && area != null) {
        this.buffer = createImage(area.width, area.height);
        this.g = buffer.getGraphics();
    }
    paint();
    if (buffer != null)
        gr.drawImage(buffer, 0, 0, this);
}

public boolean isValidImage(Object list) {
    System.out.println(list.toString());
    for (String string : ImageIO.getReaderFormatNames())
        if (list.toString().contains(string))
            return true;
    return false;
}

public BufferedImage toBufferedImage(Image image) {
    if (image instanceof BufferedImage) {
        return (BufferedImage) image;
    }
    image = new ImageIcon(image).getImage();
    boolean hasAlpha = hasAlpha(image);
    BufferedImage bimage = null;
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    int transparency = Transparency.OPAQUE;
    if (hasAlpha == true) {
        transparency = Transparency.BITMASK;
    }
    GraphicsDevice gs = ge.getDefaultScreenDevice();
    GraphicsConfiguration gc = gs.getDefaultConfiguration();
    bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
    if (bimage == null) {
        int type = BufferedImage.TYPE_INT_RGB;
        if (hasAlpha == true) {
            type = BufferedImage.TYPE_INT_ARGB;
        }
        bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
    }
    Graphics g = bimage.createGraphics();
    g.drawImage(image, 0, 0, null);
    g.dispose();
    return bimage;
}

public static boolean hasAlpha(Image image) {
    if (image instanceof BufferedImage) {
        return ((BufferedImage) image).getColorModel().hasAlpha();
    }
    PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
    try {
        pg.grabPixels();
    } catch (InterruptedException e) {
    }
    return pg.getColorModel().hasAlpha();
}

private void updateRectangle(int compWidth, int compHeight) {
    int x = currentRect.x;
    int y = currentRect.y;
    int width = currentRect.width;
    int height = currentRect.height;
    if (width < 0) {
        width = 0 - width;
        x = x - width + 1;
        if (x < 0) {
            width += x;
            x = 0;
        }
    }
    if (height < 0) {
        height = 0 - height;
        y = y - height + 1;
        if (y < 0) {
            height += y;
            y = 0;
        }
    }
    if ((x + width) > compWidth) {
        width = compWidth - x;
    }
    if ((y + height) > compHeight) {
        height = compHeight - y;
    }
    if (rectToDraw != null) {
        rectToDraw.setBounds(x, y, width, height);
    } else {
        rectToDraw = new Rectangle(x, y, width, height);
    }
}

public void capture() {
    BufferedImage croppedImage = origiImage.getSubimage(rectToDraw.x, rectToDraw.y, rectToDraw.width, rectToDraw.height);
    setSize(rectToDraw.width, rectToDraw.height);
    image = croppedImage;
}

public void upload(BufferedImage image) {
    String IMGUR_POST_URI = "http://api.imgur.com/2/upload.xml";
    String IMGUR_API_KEY = "b84e430b4a65d16a6955358141f21a61";
    String readLine = null;
    try {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "png", outputStream);
        URL url = new URL(IMGUR_POST_URI);

        String data = URLEncoder.encode("image", "UTF-8") + "=" + URLEncoder.encode(Base64.encodeBase64String(outputStream.toByteArray()).toString(), "UTF-8") + "&" + URLEncoder.encode("key", "UTF-8") + "=" + URLEncoder.encode(IMGUR_API_KEY, "UTF-8");

        URLConnection urlConnection = url.openConnection();
        urlConnection.setDoOutput(true);
        OutputStreamWriter wr = new OutputStreamWriter(urlConnection.getOutputStream());
        wr.write(data);
        wr.flush();
        // Get the response
        InputStream inputStream;
        if (((HttpURLConnection) urlConnection).getResponseCode() == 400) {
            inputStream = ((HttpURLConnection) urlConnection).getErrorStream();
        } else {
            inputStream = urlConnection.getInputStream();
        }
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        while ((line = reader.readLine()) != null) {
            readLine = line;
        }
        wr.close();
        reader.close();
    } catch(Exception e){
        e.printStackTrace();
    }
    //Prints the url link of the image uploaded
    System.out.println(readLine.substring(readLine.indexOf("<original>") + 10, readLine.indexOf("</original>")));
}

public void dragEnter(DropTargetDragEvent dtde) {

}

public void dragExit(DropTargetEvent dte) {

}

public void dragOver(DropTargetDragEvent dtde) {

}

public void dropActionChanged(DropTargetDragEvent dtde) {

}

private class CaptureListener extends MouseInputAdapter {
    public void mouseDragged(MouseEvent e) {
        updateSize(e);
    }

    public void mousePressed(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        currentRect = new Rectangle(x, y, 0, 0);
        updateRectangle(getWidth(), getHeight());
        repaint();
    }

    public void mouseReleased(MouseEvent e) {
        updateSize(e);
    }

    public void updateSize(MouseEvent e) {
        currentRect.setSize(e.getX() - currentRect.x, e.getY() - currentRect.y);
        updateRectangle(getWidth(), getHeight());
        repaint();
    }
}

} 

有人可以查看我的代码并找出为什么它不裁剪完全相同的大小吗?

4

2 回答 2

2

您的裁剪逻辑没有问题,问题在于您的绘画逻辑。

首先,您永远不应该(好吧,paint在后面)覆盖顶级容器(如 a JFrame)。有很多原因,而您只是发现了其中一个。

其次,你应该总是打电话super.paintXxx(g),不这样做是一个非常糟糕的主意。

老实说,我不知道这段代码试图做什么(除了双缓冲),如果你使用类似的东西就不需要JPanel

public void paint() {
    if (area != null && image != null) {
        g.clearRect(area.x, area.y, area.width, area.height);
        g.drawImage(image, 0, 0, null);
    }
    if (currentRect != null) {
        g.setColor(Color.RED);
        g.drawRect(rectToDraw.x, rectToDraw.y, rectToDraw.width, rectToDraw.height);
        g.setColor(new Color(255,255,255,150));
        g.fillRect(rectToDraw.x, rectToDraw.y, rectToDraw.width, rectToDraw.height);
    }
}

@Override
public void paint(Graphics gr) {
    if (buffer == null && area != null) {
        this.buffer = createImage(area.width, area.height);
        this.g = buffer.getGraphics();
    }
    paint();
    if (buffer != null)
        gr.drawImage(buffer, 0, 0, this);
}

这不允许框架实际上为框架装饰留出空间(0x0 实际上是窗口的左上角,而不是内部绘图表面)......

所以我把你的代码拿来重写了......

public class DragNDrop extends JFrame {

    private static final long serialVersionUID = 1872019741456690593L;

    public static void main(String args[]) {
        new DragNDrop();
    }

    public DragNDrop() {
        super("Drop Test");
        setLayout(new BorderLayout());
        add(new ImagePane());
        setSize(300, 300);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    protected class ImagePane extends JPanel implements DropTargetListener {

        private BufferedImage image, origiImage;
        private Rectangle currentRect;
        private Rectangle rectToDraw = null;

        public ImagePane() {

            setDropTarget(new DropTarget(getContentPane(), this));
            CaptureListener listener = new CaptureListener();
            addMouseListener(listener);
            addMouseMotionListener(listener);

            setFocusable(true);
            requestFocusInWindow();

            // Keybindings are better the KeyListeners, as the generally work...
            InputMap im = getInputMap(WHEN_FOCUSED);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Capture");
            am.put("Capture", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    capture();
                }
            });

        }

        @Override
        protected void paintComponent(Graphics g) {
            // Look how simple this is...

            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g;
            if (image != null) {
                g2d.drawImage(image, 0, 0, this);
            }

            if (currentRect != null) {
                g2d.setColor(Color.RED);
                g2d.drawRect(rectToDraw.x, rectToDraw.y, rectToDraw.width, rectToDraw.height);
                g2d.setColor(new Color(255, 255, 255, 150));
                g2d.fillRect(rectToDraw.x, rectToDraw.y, rectToDraw.width, rectToDraw.height);
            }
        }

        public void drop(DropTargetDropEvent dtde) {
            try {
                Transferable tr = dtde.getTransferable();
                DataFlavor[] flavors = tr.getTransferDataFlavors();
                dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                Object list = tr.getTransferData(flavors[0]);
                list = list.toString().substring(1, list.toString().length() - 1);
                if (isValidImage(list)) {
                    Image droppedImage = Toolkit.getDefaultToolkit().getImage(list.toString());
                    image = toBufferedImage(droppedImage);
                    origiImage = toBufferedImage(droppedImage);
                    if (droppedImage != null) {
                        setSize(image.getWidth(), image.getHeight());
                        dtde.dropComplete(true);
                        // This is a bad idea, apart from KeyListeners are just a bad idea,
                        // Each time you drop a new image, your registering a new key listener :P
//                        addKeyListener(new KeyListener() {
//                            @Override
//                            public void keyTyped(KeyEvent e) {
//                            }
//
//                            @Override
//                            public void keyReleased(KeyEvent e) {
//                                if (e.getKeyCode() == 10) {
//                                    capture();
//                                }
//                            }
//
//                            @Override
//                            public void keyPressed(KeyEvent e) {
//                            }
//                        });
                        return;
                    }
                }
                dtde.rejectDrop();
            } catch (Exception e) {
                dtde.rejectDrop();
            }
        }

        public boolean isValidImage(Object list) {
            System.out.println(list.toString());
            for (String string : ImageIO.getReaderFormatNames()) {
                if (list.toString().contains(string)) {
                    return true;
                }
            }
            return false;
        }

        public BufferedImage toBufferedImage(Image image) {
            if (image instanceof BufferedImage) {
                return (BufferedImage) image;
            }
            image = new ImageIcon(image).getImage();
            boolean hasAlpha = hasAlpha(image);
            BufferedImage bimage = null;
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            int transparency = Transparency.OPAQUE;
            if (hasAlpha == true) {
                transparency = Transparency.BITMASK;
            }
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
            if (bimage == null) {
                int type = BufferedImage.TYPE_INT_RGB;
                if (hasAlpha == true) {
                    type = BufferedImage.TYPE_INT_ARGB;
                }
                bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
            }
            Graphics g = bimage.createGraphics();
            g.drawImage(image, 0, 0, null);
            g.dispose();
            return bimage;
        }

        public boolean hasAlpha(Image image) {
            if (image instanceof BufferedImage) {
                return ((BufferedImage) image).getColorModel().hasAlpha();
            }
            PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
            try {
                pg.grabPixels();
            } catch (InterruptedException e) {
            }
            return pg.getColorModel().hasAlpha();
        }

        private void updateRectangle(int compWidth, int compHeight) {
            int x = currentRect.x;
            int y = currentRect.y;
            int width = currentRect.width;
            int height = currentRect.height;
            if (width < 0) {
                width = 0 - width;
                x = x - width + 1;
                if (x < 0) {
                    width += x;
                    x = 0;
                }
            }
            if (height < 0) {
                height = 0 - height;
                y = y - height + 1;
                if (y < 0) {
                    height += y;
                    y = 0;
                }
            }
            if ((x + width) > compWidth) {
                width = compWidth - x;
            }
            if ((y + height) > compHeight) {
                height = compHeight - y;
            }
            if (rectToDraw != null) {
                rectToDraw.setBounds(x, y, width, height);
            } else {
                rectToDraw = new Rectangle(x, y, width, height);
            }
        }

        public void capture() {
            BufferedImage croppedImage = origiImage.getSubimage(rectToDraw.x, rectToDraw.y, rectToDraw.width, rectToDraw.height);
            setSize(rectToDraw.width, rectToDraw.height);
            image = croppedImage;

            currentRect = null;

            repaint();
        }

        public void upload(BufferedImage image) {
          // Sorry, you can uncomment this can't you
//        String IMGUR_POST_URI = "http://api.imgur.com/2/upload.xml";
//        String IMGUR_API_KEY = "b84e430b4a65d16a6955358141f21a61";
//        String readLine = null;
//        try {
//            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//            ImageIO.write(image, "png", outputStream);
//            URL url = new URL(IMGUR_POST_URI);
//
//            String data = URLEncoder.encode("image", "UTF-8") + "=" + URLEncoder.encode(Base64.encodeBase64String(outputStream.toByteArray()).toString(), "UTF-8") + "&" + URLEncoder.encode("key", "UTF-8") + "=" + URLEncoder.encode(IMGUR_API_KEY, "UTF-8");
//
//            URLConnection urlConnection = url.openConnection();
//            urlConnection.setDoOutput(true);
//            OutputStreamWriter wr = new OutputStreamWriter(urlConnection.getOutputStream());
//            wr.write(data);
//            wr.flush();
//            // Get the response
//            InputStream inputStream;
//            if (((HttpURLConnection) urlConnection).getResponseCode() == 400) {
//                inputStream = ((HttpURLConnection) urlConnection).getErrorStream();
//            } else {
//                inputStream = urlConnection.getInputStream();
//            }
//            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
//            String line;
//            while ((line = reader.readLine()) != null) {
//                readLine = line;
//            }
//            wr.close();
//            reader.close();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        //Prints the url link of the image uploaded
//        System.out.println(readLine.substring(readLine.indexOf("<original>") + 10, readLine.indexOf("</original>")));
        }

        public void dragEnter(DropTargetDragEvent dtde) {
        }

        public void dragExit(DropTargetEvent dte) {
        }

        public void dragOver(DropTargetDragEvent dtde) {
        }

        public void dropActionChanged(DropTargetDragEvent dtde) {
        }

        protected class CaptureListener extends MouseInputAdapter {

            public void mouseDragged(MouseEvent e) {
                updateSize(e);
            }

            public void mousePressed(MouseEvent e) {

                requestFocusInWindow();

                int x = e.getX();
                int y = e.getY();
                currentRect = new Rectangle(x, y, 0, 0);
                updateRectangle(getWidth(), getHeight());
                repaint();
            }

            public void mouseReleased(MouseEvent e) {
                updateSize(e);
            }

            public void updateSize(MouseEvent e) {
                if (currentRect != null) {
                    currentRect.setSize(e.getX() - currentRect.x, e.getY() - currentRect.y);
                    updateRectangle(getWidth(), getHeight());
                    repaint();
                }
            }
        }
    }
}

现在它工作...

于 2012-09-19T04:20:08.340 回答
0

快速回答

您问的问题是窗口装饰(“框架”、标题栏等)覆盖了裁剪图像的一部分。(这就是为什么我认为与预期结果或上传/保存到文件的结果进行比较可能会有所帮助)。

就解决方案而言,您基本上必须确保您不会像外部边界那样调整窗口大小,而是为内容提供所需的空间。有几种方法可以做到这一点。MadProgrammer 将您的大部分代码移至面板类,并将其实例添加为 JFrame 的内容。

或者,您可以继续使用 JFrame contentPane 并确保在其上设置大小而不是框架:

getContentPane().setPreferredSize(new Dimension(newWidth, newHeight));
pack();

(在您的 JFrame 实例上调用方法,该解决方案从 Java 5 开始有效)


自己寻找答案

图像裁剪本身很好。您的问题出在其他地方,我想帮助您自己找到它。

最小化问题

您必须缩小代码中“奇怪的事情”发生的位置。所以不要盯着你的所有代码,而是复制一份,作为第一步,扔掉裁剪不需要的东西。扔掉上传的东西,你不需要它来裁剪。您的许多代码都涉及通过拖放获取文件名。将其缩短为命令行选项或纯硬编码字符串(硬编码的东西通常很糟糕,但对于调试它没关系)。等等。

实际上,裁剪不需要任何 GUI,真的。那么,如果您将裁剪后的图像写入文件而不是在窗口中显示,会发生什么情况呢?

知道会发生什么

无论是否使用 GUI,都列出您选择的位置(x,y)和尺寸(宽度,高度)。现在,您的程序裁剪的图像与使用 gimp/ImageMagick/... 以相同参数裁剪的相同图像相比如何?图像的哪些部分缺失?

问好问题

按照这些步骤并提出这些问题,您应该知道您的程序出了什么问题。至少,您将能够就您的问题提出一个简短而准确的问题。而且在 StackOverflow 上可能会有人可以回答!

于 2012-09-19T02:26:00.013 回答