ImageIO not working on Ubuntu - java

I have the following java code, which writes an image to a byte array then back into an image:
BufferedImage bi = ImageIO.read(new File("1.png"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bi,"png",baos);
byte[] img = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(img);
BufferedImage bif = ImageIO.read(bais);
On OS X, this works perfectly fine, but on Ubuntu, bif (the final image) becomes null at the end, meaning there is a problem reading from the ByteArrayInputStream. I'm using the oracle jdk in both cases and don't know what's going on.
Edit: More evidence that I'm going insane: I printed the img byte array to a file using a FileOutputStream on Ubuntu and OSX, then diffed the two files, and they are exactly the same. This means either the ByteArrayInputStream is different or (more likely) the second ImageIO.read isn't working for some reason.

Ubuntu server is usually running in headless mode which can cause problems with java image manipulation.
http://www.oracle.com/technetwork/articles/javase/headless-136834.html
Try tweaking your jvm start-up settings to allow running headless and it should fix it.

Related

GIF image only partially displayed

I got a strange issue with a GIF image in Java. The image is provided by an XML API as Base64 encoded string. To decode the Base64, I use the commons-codec library in version 1.13.
When I just decode the Base64 string and write the bytes out to a file, the image shows properly in browsers and MS Paint (nothing else to test here).
final String base64Gif = "[Base64 as provided by API]";
final byte[] sigImg = Base64.decodeBase64(base64Gif);
File sigGif = new File("C:/Temp/pod_1Z12345E5991872040.org.gif");
try (FileOutputStream fos = new FileOutputStream()) {
fos.write(sigImg);
fos.flush();
}
The resulting file opened in MS Paint:
But when I now start consuming this file using Java (for example creating a PDF document from HTML using the openhtmltopdf library), it is corrupted and does not show properly.
final String htmlLetterStr = "[HTML as provided by API]";
final Document doc = Jsoup.parse(htmlLetterStr);
try (FileOutputStream fos = new FileOutputStream(new File("C:/Temp/letter_1Z12345E5991872040.pdf"))) {
PdfRendererBuilder builder = new PdfRendererBuilder();
builder.useFastMode();
builder.withW3cDocument(new W3CDom().fromJsoup(doc), "file:///C:/Temp/");
builder.toStream(fos);
builder.useDefaultPageSize(210, 297, BaseRendererBuilder.PageSizeUnits.MM);
builder.run();
fos.flush();
}
When I now open the resulting PDF, the image created above looks like this. It seems that only the first pixel lines are printed, some layer is missing, or something like that.
The same happens, if I read the image again with ImageIO and try to convert it into PNG. The resulting PNG looks exactly the same as the image printed in the PDF document.
How can I get the image to display properly in the PDF document?
Edit:
Link to original GIF Base64 as provided by API: https://pastebin.com/sYJv6j0h
As #haraldK pointed out in the comments, the GIF file provided via the XML API does not conform to the GIF standard and thus cannot be parsed by Java's ImageIO API.
Since there does not seem to exist a pure Java tool to repair the file, the workaround I came up with now is to use ImageMagick via Java's Process API. Calling the convert command with the -coalesce option will parse the broken GIF and create a new one that does conform to the GIF standard.
// Decode broken GIF image and write to disk
final String base64Gif = "[Base64 as provided by API]";
final byte[] sigImg = Base64.decodeBase64(base64Gif);
Path gifPath = Paths.get("C:/Temp/pod_1Z12345E5991872040.tmp.gif");
if (!Files.exists(gifPath)) {
Files.createFile(gifPath);
}
Files.write(gifPath, sigImg, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
// Use the Java Process API to call ImageMagick (on Linux you would use the 'convert' binary)
ProcessBuilder procBuild = new ProcessBuilder();
procBuild.command("C:\\Program Files\\ImageMagick-7.0.9-Q16\\magick.exe", "C:\\Temp\\pod_1Z12345E5991872040.tmp.gif", "-coalesce", "C:\\Temp\\pod_1Z12345E5991872040.gif");
Process proc = procBuild.start();
// Wait for ImageMagick to complete its work
proc.waitFor();
The newly created file can be read by Java's ImageIO API and be used as expected.

Fastest way to read/write Images from a File into a BufferedImage?

What is the fastest way to read Images from a File into a BufferedImage in Java/Grails?
What is the fastest way to write Images from a BufferedImage into a File in Java/Grails?
my variant (read):
byte [] imageByteArray = new File(basePath+imageSource).readBytes()
InputStream inStream = new ByteArrayInputStream(imageByteArray)
BufferedImage bufferedImage = ImageIO.read(inStream)
my variant (write):
BufferedImage bufferedImage = // some image
def fullPath = // image page + file name
byte [] currentImage
try{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write( bufferedImage, "jpg", baos );
baos.flush();
currentImage = baos.toByteArray();
baos.close();
}catch(IOException e){
System.out.println(e.getMessage());
}
}
def newFile = new FileOutputStream(fullPath)
newFile.write(currentImage)
newFile.close()
Your solution to read is basically reading the bytes twice, once from the file and once from the ByteArrayInputStream. Don't do that
With Java 7 to read
BufferedImage bufferedImage = ImageIO.read(Files.newInputStream(Paths.get(basePath + imageSource)));
With Java 7 to write
ImageIO.write(bufferedImage, "jpg", Files.newOutputStream(Paths.get(fullPath)));
The call to Files.newInputStream will return a ChannelInputStream which (AFAIK) is not buffered. You'll want to wrap it
new BufferedInputStream(Files.newInputStream(...));
So that there are less IO calls to disk, depending on how you use it.
I'm late to the party, but anyway...
Actually, using:
ImageIO.read(new File(basePath + imageSource));
and
ImageIO.write(bufferedImage, "jpeg", new File(fullPath));
...might prove faster (try it, using a profiler, to make sure).
This is because these variants use RandomAccessFile-backed ImageInputStream/ImageOutputStream implementations behind the scenes, while the InputStream/OutputStream-based versions will by default use a disk-backed seekable stream implementation. The disk-backing involves writing the entire contents of the stream to a temporary file and possibly reading back from it (this is because image I/O often benefits from non-linear data access).
If you want to avoid extra I/O with the stream based versions, at the cost of using more memory, it is possible to call the ambiguously named ImageIO.setUseCache(false), to disable disk caching of the seekable input streams. This is obviously not a good idea if you are dealing with very large images.
You are almost good for writing. Just don't use the intermediate ByteArrayOutputStream. It is a giant bottleneck in your code. Instead wrap the FileOutputStream in a BufferedOutputStream and do the same.
Same goes indeed for your reading. Remove the Itermediate ByteArrayInputStream.

Java ImageIO.write to classpath?

I am trying to use the ImageIO class to save an image and then get the resource using an input stream. My problem is that I keep getting a NullPointerException whenever I try to create the input stream. If I simply go and put an image file in the class path, it works. Here is my code:
ImageIO.write(image, "png", new File("temp.png"));
InputStream imgIs = AptCap.class.getResourceAsStream("temp.png");
byte[] imgData = new byte[imgIs.available()]; // I get null here.
I have also tried specifying direct locations to files on the C drive for both of them, but I still get a null pointer exception. I would rather not do that anyway, but just keep it in the classpath (for purposes of multi OS support).
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // create OutputStream
ImageIO.write(image, "png", baos); // write to OS
InputStream imgIs = new ByteArrayInputStream(baos.toByteArray()); // grab bytes from OS
//..

How to read png images form inputstream in java

There are 2 applications. One application act as server and sends continuously screen shot of desktop by using the following code.
Robot robot=new Robot();
OutputStream os;
BufferedImage image = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
ImageIO.write(image, "png", os);
The second application is Android application acts a client application and has to read continuously the above image stream from inputstream.
Could please help me to read the png images from inputstream in the client application.
Thanks & Regards
Mini.
In client application, read the InputStream via Socket.getInputStream() method.
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
BufferedImage image = ImageIO.read(in);
Android SDK does not support the method ImageIO.read(). Even if you can compile your code, your android application will get crashed and have error about missing libraries like this:
could not find method javax.imageio.imageio.read
What I suggest is using bitmapping instead of this...

java/opengl: loading textures on 64bit VM

it seems my texture loader doesnt work anymore when run in a 64bit environment. im not sure if the cause is the 64bit VM itself or if the file lying on a 64bit filesystem.
the image to load is a RGBA png file, it shows up correctly on 32bit windows systems, but on my 64bit win7 some color channels seem flipped.
here is my code:
InputStream is = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(path);
BufferedImage bi = ImageIO.read(is);
is.close();
byte[] databytes = ((DataBufferByte) bi.getRaster().getDataBuffer()).getData();
ByteBuffer data = ByteBuffer.allocateDirect(databytes.length);
data.order(ByteOrder.nativeOrder());
data.put(databytes, 0, databytes.length);
data.rewind();
IntBuffer texb = IntBuffer.allocate(1);
binding.genTextures(1, texb);
binding.bindTexture(binding.TEXTURE_2D(), texb.get(0));
binding.texParameter(binding.TEXTURE_2D(), binding.TEXTURE_MIN_FILTER(),
binding.LINEAR());
binding.texParameter(binding.TEXTURE_2D(), binding.TEXTURE_MAG_FILTER(),
binding.LINEAR());
binding.texParameter(binding.TEXTURE_2D(), binding.TEXTURE_WRAP_S(),
binding.CLAMP());
binding.texParameter(binding.TEXTURE_2D(), binding.TEXTURE_WRAP_T(),
binding.CLAMP());
binding.texEnvi(binding.TEXTURE_ENV(), binding.TEXTURE_ENV_MODE(),
binding.MODULATE());
binding.texImage2D(binding.TEXTURE_2D(), 0, binding.RGBA(), bi.getWidth(),
bi.getHeight(), 0, binding.RGBA(), binding.UNSIGNED_BYTE(), data);
does anyone know what could be wrong? thanks!
actually it turned out a problem with the latest update java6 u18 which contained some changes to bufferedimage and had nothing to do with 64bit VMs

Categories