About convert Image to byte[] and reverse in Java - java

i have one problem when i convert image to byte[] and reverse:
I have 2 function convert image to byte[] as follow
public byte[] extractBytes2 (String ImageName) throws IOException {
File imgPath = new File(ImageName);
BufferedImage bufferedImage = ImageIO.read(imgPath);
WritableRaster raster = bufferedImage .getRaster();
DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
return ( data.getData() );
}
and
public byte[] extractBytes (String ImageName) throws IOException
{
Path path = Paths.get(ImageName);
byte[] data = Files.readAllBytes(path);
return data;
}
I will have byte[] byteArray
byteArray = extractBytes2("image/pikachu.png");
or
byteArray = extractBytes("image/pikachu.png");
when i convert byte[] to Image i use
Graphics g = panelMain.getGraphics();
Graphics2D g2D = (Graphics2D) g;
try {
InputStream in = new ByteArrayInputStream(byteArray);
BufferedImage image = ImageIO.read(in);
g2D.drawImage(image, 0, 0, GiaoDienChinh.this);
g2D.setPaint(Color.BLACK);
panelMain.setOpaque(true);
panelMain.paintComponents(g2D);
}
catch ( Exception e ) {
}
finally {
}
but i only draw with byteArray use function "extractBytes" not with "extractBytes2" !!!
Anyone can explain me how i can draw image with byteArray which got from "extractByte2"?
Thanks for all support!

Let's start with the paint code.
ImageIO.read(in) is expecting a valid image format that one of it's pluggable service provides knows how to read and convert to a BufferedImage.
When you pass the byes from extractBytes, you're simply passing back an array of bytes that represents the actual image file. I'd be the same as saying Image.read(new File("image/pikachu.png"))
However, the data buffer returned from your extractBytes2 is returning a internal representation of the image data, which may not be "readable" by ImageIO.
UPDATED
A BufferedImage is an accessible buffer of image data, essentially
pixels, and their RGB colors. The BufferedImage provides a powerful
way to manipulate the Image data. A BufferedImage object is made up of
two parts a ColorModel object and a Raster object.
Referenced from here
UPDATED
I had this wacky idea on the way home of how to convert a BufferedImage to a byte array...
The basic idea is to use ImageIO.write to write out the BufferedImage to a ByteOutputStream...
public static byte[] extractBytes2(String ImageName) throws IOException {
File imgPath = new File(ImageName);
BufferedImage bufferedImage = ImageIO.read(imgPath);
ByteOutputStream bos = null;
try {
bos = new ByteOutputStream();
ImageIO.write(bufferedImage, "png", bos);
} finally {
try {
bos.close();
} catch (Exception e) {
}
}
return bos == null ? null : bos.getBytes();
}
Here's my test...
public class TestByteImage {
public static void main(String[] args) {
new TestByteImage();
}
public static byte[] extractBytes2(String ImageName) throws IOException {
File imgPath = new File(ImageName);
BufferedImage bufferedImage = ImageIO.read(imgPath);
ByteOutputStream bos = null;
try {
bos = new ByteOutputStream();
ImageIO.write(bufferedImage, "png", bos);
} finally {
try {
bos.close();
} catch (Exception e) {
}
}
return bos == null ? null : bos.getBytes();
}
public TestByteImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new ImagePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ImagePane extends JPanel {
private BufferedImage original;
private byte[] byteData;
private BufferedImage fromBytes;
public ImagePane() {
String name = "/path/to/your/image";
try {
original = ImageIO.read(new File(name));
byteData = extractBytes2(name);
} catch (IOException ex) {
ex.printStackTrace();
}
setFont(UIManager.getFont("Label.font").deriveFont(Font.BOLD, 48f));
}
#Override
public Dimension getPreferredSize() {
return original == null ? super.getPreferredSize() : new Dimension(original.getWidth() * 2, original.getHeight());
}
protected void drawText(Graphics2D g2d, String text, int x, int width) {
BufferedImage img = new BufferedImage(width, getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D tmpg = img.createGraphics();
tmpg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
tmpg.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
tmpg.setFont(g2d.getFont());
tmpg.setColor(Color.RED);
FontMetrics fm = tmpg.getFontMetrics();
int xPos = ((width - fm.stringWidth(text)) / 2);
int yPos = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();
tmpg.drawString(text, xPos, yPos);
tmpg.dispose();
AffineTransform transform = g2d.getTransform();
g2d.setTransform(AffineTransform.getRotateInstance(Math.toRadians(-10), x + (x + width) / 2, getHeight() / 2));
g2d.drawImage(img, x, 0, this);
g2d.setTransform(transform);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (original != null) {
g.drawImage(original, 0, 0, this);
drawText((Graphics2D) g, "Original", 0, original.getWidth());
}
if (byteData != null && fromBytes == null) {
try {
fromBytes = ImageIO.read(new ByteInputStream(byteData, byteData.length));
} catch (IOException exp) {
exp.printStackTrace();
}
}
if (fromBytes != null) {
g.drawImage(fromBytes, getWidth() - fromBytes.getWidth(), 0, this);
drawText((Graphics2D) g, "From Bytes", getWidth() - fromBytes.getWidth(), fromBytes.getWidth());
}
}
}
}

Use ImageIo to write bufferedImage into ByteArrayOutputStream, then invoke the toByteArray method of the stream.

Related

RGB value not change correctly after saving image in JAVA

I'm trying to read an Image type JPG/JPEG to BufferedImage , change RGB value of pixel (0,0)
Image file : http://i.upanh.com/rcfutp
but it didn't work correctly
Here is what i've try
Read image
public BufferedImage readImage1(String path)
{
BufferedImage _image = null;
BufferedImage copy = null;
try {
_image = ImageIO.read(new File(path));
copy = new BufferedImage(_image.getWidth(), _image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
copy.getGraphics().drawImage(_image, 0, 0, null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return copy;
}
Write Image
public void writeImage1(String path,BufferedImage _image)
{
try {
ImageIO.write(_image, "jpg", new File(path));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Client Code
BufferedImage image = readImage1("E:/2.jpg");
System.out.print((image.getRGB(0, 0))&0xFFFFFF);
System.out.print("-");
image.setRGB(0, 0, 0x00000F);
System.out.print((image.getRGB(0, 0))&0xFFFFFF);
System.out.print("-");
writeImage1("E:/3.jpg", image);
image = readImage1("E:/3.jpg");
System.out.print((image.getRGB(0, 0))&0xFFFFFF);
System.out.print return
7736127-15-5439516
I hope it was 7736127-15-15,but it return 7736127-15-5439516
please help me to correct ,thank you very much guy
This is not possible because of how jpg compresses data, when you are operating on every pixel of the image it is the unpacked version of the image you are operating on, the jpg format is a lossy compression format. Compressing an image then decompressing it will not yield the original image. This is why pixel values are different.
This can be clearly seen in the following image. Notice the "lines" to the right, the right side is the jpg compression then decompression of the left side.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.beans.Transient;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class ImageTest extends JPanel {
private BufferedImage image;
private BufferedImage saved;
public ImageTest(int w, int h) {
image = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
randomizeImage(image);
saveAndLoadImage();
saveResultToLossLess();
}
private void saveResultToLossLess() {
BufferedImage result = new BufferedImage(image.getWidth() * 2,
image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
result.getGraphics().drawImage(image, 0, 0, null);
result.getGraphics().drawImage(saved, image.getWidth(), 0, null);
try {
ImageIO.write(result, "png", new File("comparison.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void randomizeImage(BufferedImage image) {
// Draw a blue gradient, note that in the array below
// pixels[i] = blue, pixels[i+1] = green, pixels[i+2] = red
byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer())
.getData();
for (int i = 0; i < pixels.length; i += 3) {
pixels[i] = (byte) (255.0 * i / pixels.length);
pixels[i + 1] = (byte) (128.0 * i / pixels.length);
pixels[i + 2] = (byte) (64.0 * i / pixels.length);
}
}
private void saveAndLoadImage() {
try {
ImageIO.write(image, "jpg", new File("image.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
saved = ImageIO.read(new File("image.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
if (saved != null)
g.drawImage(saved, image.getWidth(), 0, null);
}
#Override
#Transient
public Dimension getPreferredSize() {
return new Dimension(image.getWidth() * 2, image.getHeight());
}
public static void main(String[] args) {
ImageTest test = new ImageTest(600, 600);
JFrame frame = new JFrame();
frame.getContentPane().add(test);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}

RGBImageFilter not affecting my image

I am trying to change the colors in a .png-file using RGBImageFilter and FilteredImageSource and then save the file to disk, and it seems to be working fine.. but when I open the new file after the program has finished, it looks just like the original, i.e. I have just copied the file.
The codes looks like this:
public class ChangeImageColor {
public static void main(String[] args) {
BufferedImage image = null;
try {
image = ImageIO.read(new File("png_test.png") );
ImageFilter colorfilter = new RedBlueSwapFilter();
FilteredImageSource filteredImageSource = new FilteredImageSource(image.getSource(), colorfilter );
Image filteredImage = Toolkit.getDefaultToolkit().createImage(filteredImageSource);
BufferedImage filtered = new BufferedImage(
filteredImage.getWidth(null), filteredImage.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = filtered.createGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
save(filtered, "png");
} catch( IOException e){
//do something
System.out.print(e.getMessage());
}
}
private static void save(BufferedImage image, String ext) {
String fileName = "png_test_manipulated";
File file = new File(fileName + "." + ext);
try {
ImageIO.write(image, ext, file); // ignore returned boolean
} catch(IOException e) {
System.out.println("Write error for " + file.getPath() +
": " + e.getMessage());
}
}
static class RedBlueSwapFilter extends RGBImageFilter {
public RedBlueSwapFilter() {
// The filter's operation does not depend on the
// pixel's location, so IndexColorModels can be
// filtered directly.
canFilterIndexColorModel = true;
}
#Override
public int filterRGB(int x, int y, int rgb) {
/*return ((rgb & 0xff00ff00)
| ((rgb & 0xff0000) >> 16)
| ((rgb & 0xff) << 16));*/
return 0x00000000;
}
}
}
your problem:
g2.drawImage(image, 0, 0, null);
you draw the old image with this code, try to remove this lines:
Graphics2D g2 = filtered.createGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();

Drawing an image from URL

It's for a pacman game and it works perfectly when I import it from my computer. But when I try to take it from an URL, my game starts lagging and the image doesn't show.
URL url = new URL("https://www.dropbox.com/s/xpc49t8xpqt8dir/pacman%20down.jpg");
image = ImageIO.read(url);
G.drawImage(image, x, y, 20,20,null);
Image
( http://i.stack.imgur.com/Cp1XL.png at IMGUR )
https://www.dropbox.com/s/xpc49t8xpqt8dir/pacman%20down.jpg is return HTML text not image data.
This is a hack, but try https://www.dropbox.com/s/xpc49t8xpqt8dir/pacman%20down.jpg?dl=1 instead. Be warned though, it's possible that drop box could change this query in the future.
public class TestURL02 {
public static void main(String[] args) {
new TestURL02();
}
public TestURL02() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PacPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PacPane extends JPanel {
private BufferedImage image;
public PacPane() {
InputStream is = null;
try {
URL url = new URL("https://www.dropbox.com/s/xpc49t8xpqt8dir/pacman%20down.jpg?dl=1");
// StringBuilder sb = new StringBuilder(1024);
// byte[] buffer = new byte[1024 * 1024];
// is = url.openStream();
// int in = -1;
// while ((in = is.read(buffer)) != -1) {
// sb.append(new String(buffer));
// }
// System.out.println(sb.toString());
image = ImageIO.read(url);
} catch (IOException exp) {
exp.printStackTrace();
} finally {
try {
is.close();
} catch (Exception e) {
}
}
}
#Override
public Dimension getPreferredSize() {
return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
int x = (getWidth() - image.getWidth()) / 2;
int y = (getHeight() - image.getHeight()) / 2;
g.drawImage(image, x, y, this);
}
}
}
}
I think that it may lag because the program downloads the image each time you draw it with your Graphics object. You should use a cache system for your image or download it once for all the program execution.
My guess, and it's only a guess because you don't tell us, but could you possibly be trying to read in the Image from the URL from within a Swing or AWT paint(...) or paintComponent(...) method? If so, don't do this. Read the image in once, and then use it in the paintComponent(...) method.
If this doesn't help, please do tell us the details we'll need to know to be able to help you.

Java Image Cropping Not Accurate

Heres my code, when you select and area you want to crop and then push enter, the cropped image isn't the same size/picture as the original selected area.
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();
}
}
}
Can someone look through my code and find why it doesn't crop the exact same size?
There's nothing wrong with your cropping logic, the problem is with you paint logic.
Firstly, you should never (okay, rearly) override paint on a top level container (like a JFrame). There are lots of reasons and you just discovered one of them.
Secondly, you should ALWAYS call super.paintXxx(g), not doing so is a REALLY bad idea.
To be honest, I've got no idea of what half this code is trying to do (other then double buffering), which wouldn't be required if you used something like 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);
}
This doesn't allow for the fact that the frame is actually leaving space for the frames decorations (0x0 is actually the very top left hand corner of the window, not the inner drawing surface)...
So I've taken to you're code and rewritten it...
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();
}
}
}
}
}
Now it works...
Quick answer
The problem you asked about was that the window decorations (the "frame", titlebar etc.) cover parts of the cropped image. (That's why I thought comparing with expected results or the result uploaded/saved to file might help).
In terms of a solution you basically have to ensure that you do not resize the window as by its outer boundaries, but give the content the space needed. There are several ways to do that. MadProgrammer moved most of your code to a panel class and added an instance of that as the JFrame's content.
Alternatively you could keep using the JFrame contentPane and just ensure that you set the size on it instead of the frame:
getContentPane().setPreferredSize(new Dimension(newWidth, newHeight));
pack();
(methods are called on your JFrame instance, the solution works from Java 5 on)
Finding the answer yourself
The image cropping itself is fine. Your problem lies somewhere else and I want to help you find it yourself.
Minimize the problem
You have to narrow down where in your code the "strange things" happen. So do not stare at all your code but make a copy and, as a first step throw out what is not needed for the cropping.
Throw out the upload stuff, you don't need it for cropping.
A lot of your code deals with getting a filename by drag and drop. Shorten it down to either a command line option or a plain hardcoded string (hardcoded stuff is bad in general, but for debugging it's okay). And so on.
Actually cropping does not need any GUI, really. So what happens if you write your cropped image to a file instead of displaying it in a window?
Know what to expect
GUI or not, put out the position(x,y) and dimension(width,height) of your selection. Now, how does the image cropped by your program compare to the same image cropped with the same parameters using gimp/ImageMagick/... ? Which parts of the image are missing?
Ask good questions
Following those steps and asking such questions, you should know what's wrong with your program. At the very least you will be able to ask a short and precise question about your problem. And on StackOverflow there will probably be someone who can answer it!

ImageIcon not loading

So I am trying to make a small game for a project in college. I have an image class that loads the images etc. I know this class works because I tested it all when I made it. But then I decided to use a form maker, in this case WindowsBuilder Pro to make a form that was better then I could code. I am now trying to call a function that in theory will load call the images class and load the image then add that image as an imageicon to a label within a jPanel. But I am getting nothing. Any help?
private void loadres(){
String PROGRAM_DIRECTORY = "E:/WordGame/bin/Images/";
Functions.Resources rs = new Functions.Resources();
rs.loadResources();
Functions.ImageLib iL = rs.getIL();
try {
BGImage = new JLabel(new ImageIcon(iL.mergeImages(iL.getImageArray(0),iL.getImage(PROGRAM_DIRECTORY + "Astroid1Image.png"))));
} catch (IOException e) {
e.printStackTrace();
}
BGImage.revalidate();
BGImage.repaint();
}
And here is the Image functions I am using:
public class ImageLib {
private ArrayList<BufferedImage> BIArray = new ArrayList<BufferedImage>();
public ImageLib(){
}
public BufferedImage getImage(String ref){
BufferedImage Bi = null;
try{
Bi = ImageIO.read(new File(ref));
}catch (Exception e) {
e.printStackTrace();
}
return Bi;
}
public BufferedImage resizeImage(BufferedImage Bi, int nW, int nH){
int w = Bi.getWidth();
int h = Bi.getHeight();
BufferedImage nBi = new BufferedImage(nW, nH, Bi.getType());
Graphics2D g = nBi.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(Bi,0,0,nW,nH,0,0,w,h,null);
g.dispose();
return nBi;
}
public void addToArray(BufferedImage img){
BIArray.add(img);
}
public BufferedImage getImageArray(int index){
return (BufferedImage) BIArray.get(index);
}
public BufferedImage mergeImages(BufferedImage I1, BufferedImage I2) throws IOException{
int w = Math.max(I1.getWidth(), I2.getWidth());
int h = Math.max(I1.getHeight(), I2.getHeight());
BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = combined.getGraphics();
g.drawImage(I1, 0, 0, null);
g.drawImage(I2, 0, 0, null);
g.dispose();
return combined;
}
}
Here is my answer ^^
ClassLoader cldr = this.getClass().getClassLoader();
java.net.URL imageURL = cldr.getResource("path/to/your/images/picture.gif");
ImageIcon imgIcon = new ImageIcon(imageURL);

Categories