I have a network program that sends a stream of BufferedImages through a network using ImageIO.write(..), this is working as intended apart from sometimes the Image received on the other end will just be a series of small black and white squares for a long time, then it will eventually switch back to sending the actual images.
I can't find any help with this anywhere.
I'm using Java version 1.8.0_65, I send the image like so:
BufferedImage capture = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
BufferedImage newImage = new BufferedImage(capture.getWidth(), capture.getHeight(), BufferedImage.TYPE_4BYTE_ABGR_PRE);
newImage.createGraphics().drawImage(capture, 0, 0, newImage.getWidth(), newImage.getHeight(), null);
capture = newImage;
BufferedImage difference = null;
if (lastImage != null) {
difference = getDifferenceImage(capture, lastImage);
} else {
difference = capture;
}
long generated = System.currentTimeMillis() - start;
ImageIO.write(difference, "png", socket.getOutputStream());
socket.getOutputStream().flush();
Try this code:
public byte[] getCustomImageInBytes(BufferedImage originalImage) {
byte[] imageInByte = null;
try {
// convert BufferedImage to byte array
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(originalImage, "png", baos);
baos.flush();
imageInByte = baos.toByteArray();
baos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return imageInByte;
}
socket.getOutputStream().write(getCustomImageInBytes(difference));
socket.getOutputStream().flush();
Related
I have an image and I do somethings with it, finally I get an BufferedImage object(the sub image of original image), now I want to save the sub image to FastDFS without save it in my local, what should I do?
I have already save sub image as file to my local, but I don't want to do like this, because it makes waste.
String oriPicPathInFastDFS = "http://127.0.0.1/xx/xx/xx/xx";
BufferedImage image = null;
try {
image = ImageIO.read(new URL(oriPicPathInFastDFS));
} catch (IOException e) {
e.printStackTrace();
}
// do something
// this is the sub image that I want to save to FastDFS
BufferedImage subImage = image.getSubimage(5, 5, 5, 5);
// these code can save the sub image to my local and then upload to fastDFS
String localPath = "/home/xx/x/xx.jpg";
File detectionFile = new File(localPath);
try {
detectionFile.createNewFile();
ImageIO.write(subImage, "jpg", detectionFile);
} catch (IOException e) {
e.printStackTrace();
}
// upload to fast dfs
I want to upload the subImage to fastDFS without save it to my local.
Fine, I got a method to solve this question.
// change the BufferedImage to byte[]
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
boolean flag = ImageIO.write(sunImage, "jpg", out);
} catch (IOException e) {
e.printStackTrace();
}
byte[] byteArray = out.toByteArray();
// then save the byteArray to fast DFS
I have the code below on a tomcat server. The goal is to save in .jpg an image (that is sent in String) and create the equivalent thumbnails.
The goal is properly achieved nevertheless I noticed that at every execution (even after trying to set almost all used variables "null"), the server memomy increases by 6 Megabytes which are never freed. Since I have a very small RAM's server, this is really problematic. By the way images sent are close to 30 kilobytes only.
public boolean saveImage(String picInString)
throws IOException {
byte[] bytes = null;
try {
bytes = Base64.decode(picInString);
} catch (Base64DecodingException e) {
e.printStackTrace(System.out);
}
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
Iterator<?> readers = ImageIO.getImageReadersByFormatName("png");
ImageReader reader = (ImageReader) readers.next();
Object source = bis;
ImageInputStream iis = ImageIO.createImageInputStream(source);
Graphics2D g2 = null;
try {
reader.setInput(iis, true);
ImageReadParam param = reader.getDefaultReadParam();
Image image = reader.read(0, param);
// got an image file
BufferedImage bufferedImage = new BufferedImage(image.getWidth(null),
image.getHeight(null), BufferedImage.TYPE_INT_RGB);
// bufferedImage is the RenderedImage to be written
g2 = bufferedImage.createGraphics();
g2.drawImage(image, null, null);
ImageIO.write(bufferedImage, "jpg", new File("/image.jpg"));
ImageIO.write(Scalr.resize(MyImageClass.cropImage(bufferedImage), 100, 100),
"jpg", new File("/image_mini.jpg"));
bufferedImage.flush();
bufferedImage = null;
} catch (Exception e) {
e.printStackTrace(System.out);
} finally {
if (reader != null) {
reader.dispose();
}
if (g2 != null) {
g2.dispose();
}
bis.close();
iis.close();
reader = null;
bis = null;
iis = null;
}
return false;
}
Any help will be appreciated!
Someone gave me a clue to the answer but I am not able to see the comment anymore.
Actually, setting the variable "image" to null at the end of the process has solved the issue.
You shouldn't tame an image as it is. You should down sample it like it is done in android. Scaling is a must to prevent memory errors and exceptions. This SO questions is the solution to all your problems.
How to improve the performance of g.drawImage() method for resizing images
I'm designing a program that stores geography data on the JavaFX platform, and whenever I convert an image from a JavaFX Image into a BufferedImage then a ByteArray (for the purpose of serialization) before converting to a Buffered Image and then JavaFX Image again, it gets slightly corrupt. Here's the code I'm using to convert back and forth:
private byte [] loadImageData (Image image){
try{
//creating a byte array output stream from the Image
BufferedImage bi = SwingFXUtils.fromFXImage(image, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
ImageIO.write(bi, "png", baos );
baos.flush();
byte[] imageData = baos.toByteArray();
baos.close();
return imageData;
}catch (Exception e){
e.printStackTrace();
}
}
public Image restoreMapData (byte[] data){
try{
//converting back to an image
InputStream in = new ByteArrayInputStream(data);
BufferedImage bi = ImageIO.read(in);
return SwingFXUtils.toFXImage(bi, null);
}catch(Exception e){
e.printStackTrace();
return null;
}
}
Could there be an error elsewhere? I've attached a corrupted and un-corrupt picture of the data.
I also noticed that if I convert to BufferedImage with a type TYPE_INT_ARGB it greatly diminishes the effect.
I need to obtain the pixel data from a BufferedImage so I can recreate the image from the data. I looked into Raster, but that did not seem to contain the information I need. How can I obtain data from a BufferedImage so I can recreate the image without needing the original file?
You should check out the answers to this question
Java - get pixel array from image
One way to do it is to use
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(originalImage, "jpg", baos);
baos.flush();
byte[] imageBytes = baos.toByteArray();
baos.close();
Now when you want to create a new BufferedImage from the data you use
ByteArrayInputStream bais = new ByteArrayInputStream(imageBytes);
BufferedImage newImage = null;
try {
newImage = ImageIO.read(bais);
} catch (IOException e) {
// handle exception
}
I have created a graphical image with the following sample code.
BufferedImage bi = new BufferedImage(50,50,BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g2d = bi.createGraphics();
// Draw graphics.
g2d.dispose();
// BufferedImage now has my image I want.
At this point I have BufferedImage which I want to convert into an IMG Data URI. Is this possible? For example..
<IMG SRC="data:image/png;base64,[BufferedImage data here]"/>
Not tested, but something like this ought to do it:
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(bi, "PNG", out);
byte[] bytes = out.toByteArray();
String base64bytes = Base64.encode(bytes);
String src = "data:image/png;base64," + base64bytes;
There are lots of different base64 codec implementations for Java. I've had good results with MigBase64.
You could use this solution which doesn't use any external libraries. Short and clean! It uses a Java 6 library (DatatypeConverter). Worked for me!
ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageIO.write(image, "png", output);
DatatypeConverter.printBase64Binary(output.toByteArray());
I use Webdriver, get captcha, like this below:
// formatName -> png
// pathname -> C:/Users/n/Desktop/tmp/test.png
public static String getScreenshot(WebDriver driver, String formatName, String pathname) {
try {
WebElement element = driver.findElement(By.xpath("//*[#id=\"imageCodeDisplayId\"]"));
File screenshot = element.getScreenshotAs(OutputType.FILE);
// base64 data
String base64Str = ImageUtil.getScreenshot(screenshot.toString());
return base64Str;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String getScreenshot(String imgFile) {
InputStream in;
byte[] data = null;
try {
in = new FileInputStream(imgFile);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
String base64Str = new String(Base64.getEncoder().encode(data));
if (StringUtils.isAnyBlank(base64Str)) {
return null;
}
if (!base64Str.startsWith("data:image/")) {
base64Str = "data:image/jpeg;base64," + base64Str;
}
return base64Str;
}