What is ImageIO doing when reading a file? - java

I am a bit confused by ImageIO.read(file). When I try to read a .png file into a BufferedImage, at least on macOS, the focus moves to a new application named after my main class. It appears in the Menu bar. It does so even when I run java from the command line.
The annoying thing is that it moves the focus out of my IDE and I have to return to it manually.
I looked at the source of ImageIO.read(file). I discovered that it is calling ImageIO.createImageInputStream(file) and that is what triggers this behaviour.
My question is: what is ImageIO doing actually, why is my main class showing in the Menu bar when it is just loading information in memory. And most important, how can I avoid it?
Below the code to show the problem. Use any .png to test it.
package misc;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import java.io.File;
import java.io.IOException;
public class ReadImageTest {
public static void main(String[] args) {
try {
File file = new File("out/production/resources/picture.png");
long time = System.currentTimeMillis();
ImageInputStream stream = ImageIO.createImageInputStream(file);
long delay = System.currentTimeMillis() - time;
System.out.println("stream: " + stream.length());
System.out.println("time: " + delay/1000.0);
} catch (IOException e) {
e.printStackTrace();
}
}
}

Using Headless Mode in the Java SE Platform describes what is headless mode and how to use it properly.
Headless mode is a system configuration in which the display device,
keyboard, or mouse is lacking. Sounds unexpected, but actually you can
perform different operations in this mode, even with graphic data.
You can enable it by adding below option to your program:
-Djava.awt.headless=true
See also:
What is the benefit of setting java.awt.headless=true?
How can I prevent command line java processes from stealing focus in OSX?
Setting java.awt.headless=true programmatically

Related

CodenameOne Java String.Format "error: cannot find symbol" on Hello World example

A super-simple String.format("this is a test %d",5) doesn't work in my HelloWorld CodenameOne project: I get "error: cannot find symbol".
It doesn't seem to matter what format I used, I always get the same error. This seems to be an import problem, though I'm not importing any special packages outside of the defaults.
Here is the java source:
package com.test.test;
import static com.codename1.ui.CN.*;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.Dialog;
import com.codename1.ui.Label;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.Resources;
import com.codename1.io.Log;
import com.codename1.ui.Toolbar;
import java.io.IOException;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.io.NetworkEvent;
/**
* This file was generated by Codename One for the purpose
* of building native mobile applications using Java.
*/
public class MyApplication {
private Form current;
private Resources theme;
public void init(Object context) {
// use two network threads instead of one
updateNetworkThreadCount(2);
theme = UIManager.initFirstTheme("/theme");
// Enable Toolbar on all Forms by default
Toolbar.setGlobalToolbar(true);
// Pro only feature
Log.bindCrashProtection(true);
/*
Updating property file: C:\Users\admin\Desktop\test2\build\built-jar.properties
Compile is forcing compliance to the supported API's/features for maximum device compatibility. This allows smaller
code size and wider device support
Compiling 1 source file to C:\Users\admin\Desktop\test2\build\tmp
C:\Users\admin\Desktop\test2\src\com\test\test\MyApplication.java:39: error: cannot find symbol
s = String.format("this is a test %d",5);
symbol: method format(String,int)
location: class String
1 error
C:\Users\admin\Desktop\test2\build.xml:62: Compile failed; see the compiler error output for details.
BUILD FAILED (total time: 0 seconds)
*/
String s;
s = String.format("this is a test %d",5);
addNetworkErrorListener(err -> {
// prevent the event from propagating
err.consume();
if(err.getError() != null) {
Log.e(err.getError());
}
Log.sendLogAsync();
Dialog.show("Connection Error", "There was a networking error in the connection to " + err.getConnectionRequest().getUrl(), "OK", null);
});
}
public void start() {
if(current != null){
current.show();
return;
}
Form hi = new Form("Hi World", BoxLayout.y());
hi.add(new Label("Hi World"));
hi.show();
}
public void stop() {
current = getCurrentForm();
if(current instanceof Dialog) {
((Dialog)current).dispose();
current = getCurrentForm();
}
}
public void destroy() {
}
}
CodenameOne compiles your source code using its own subset of the Java SE API, which is missing some features that the standard Java API includes.
Quoting their FAQ:
What features of Java are supported? What features of Java aren't supported?
The most obvious thing missing is reflections. The main problem is that when we package the VM into devices that don’t have Java, we would have to include EVERYTHING. If reflections were included, they wouldn’t work anyway since we obfuscate the code for the platforms where reflections do work (e.g. Android). On top of that reflection code is generally slow and a bad idea on a mobile device to begin with. As an alternative some developers were successful with bytecode manipulation which is something that is completely seamless to the server and as performant/efficient as handcoding.
Many of the desktop API’s such as java.net, java.io.File etc. aren’t very appropriate for mobile devices and just didn’t make it. We provide our own alternatives which are more portable and better suited for mobile settings.
Of the other missing things, if you run into a missing method or ability, there are cases where that functionality can be added.
Specifically, its version of java.lang.String does not include the format method.
In this case, it can be rewritten using simple string concatenation:
String s = "this is a test " + 5;

Put a program icon depending on the platform

I've realized that my code has a problem with setting a program icon (instead of the java one) in different platforms. I had written this code for windows and mac:
private void putIcon() {
URL url = ClassLoader.getSystemResource("resources/icon.png");
String name = System.getProperty("os.name");
if (name.startsWith("Win")) {
Toolkit kit = Toolkit.getDefaultToolkit();
Image img = kit.createImage(url);
this.setIconImage(img);
} else {
Application.getApplication().setDockIconImage(new ImageIcon(url).getImage());
}
}
While I was testing it in mac there was not problem, but when I tried it windows I realized that won't work because that class isn't in windows:
import com.apple.eawt.Application;
What could I do to solve this issue? For what I've researched it's not possible to have some kind of "if" in the import section of the code, and if that class is there in windows it won't compile.
Check if the specified class Application can be found by using
Class.forName("com.apple.eawt.Application");
If this method does not throw a ClassNotFoundException, invoke the methods you want by using reflection only. Seems a bit hacky but it should work.
Also make sure that you are not importing the class.

Error playing music in Java program

Ok, so today I finally decided to ask what the issue was with my Java program after various attempts to fix it. If you didn't read the title, here is my issue: I'm trying to play music in a program, but it returns an error.
So first, I have to put the most important part; the class
import java.io.File;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class Runawaytrain {
public void play() {
try {
AudioInputStream in = AudioSystem.getAudioInputStream(new File("hard1.wav"));
Clip clip = AudioSystem.getClip();
clip.open(in);
clip.start();
Thread.sleep(clip.getMicrosecondLength());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args){
new Runawaytrain().play();
}
}
This program I actually used as a test, since the music I was using in a game I'm co-creating wouldn't play. So when I made this program, I got the same stack trace:
javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input file
at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1189)
at krap2.Runawaytrain.play(Runawaytrain.java:12)
at krap2.Runawaytrain.main(Runawaytrain.java:22)
The file hard1.wav is included in my project directory. For some reason, it won't play however, and keeps returning that stack trace.
But I found something pretty odd about my program; when I use music from a URL, it works. So I tried inserting a URL using the file:// protocol, but still no luck.
So anyway, to finish this off, I'll put some info that may help in answering the question:
• OS: Mac
• JVM installed: 1.8.0
• Music source: Originally an MP3 file, converted through VLC into a .wav format
Thanks
I'm pretty sure you need to put the entire system path of the file when making the new File() (so on a Windows it would be "Users/username/.../hard1.wav" or whatever it would be on a Mac).

Can Eclipse for Java and Eclipse for WEBMethods be on the same hard drive?

I am new to WEBMethods. I have been working on a Java service for a project. I really need to be able to write some code in regular Java for some quick testing of reading in a simple text expression with some regular expressions. Nothing at all that fancy with the Java part. But eclipse currently is set up for WEBMethods and I need to be in a regular Java mode for Eclipse (If there is such a thing). At home I have the standard eclipse version and have no trouble writting code. But at work I have WEBMethods installed in the Eclipse (Software AG Designer). I think that if I can write the code in regular Java then I can just copy and paste it into the WEBMethods Java services and set up the INPUT and OUTPUT variables and it should work. But currently I cannot find a way to just write Java code like I do from my home computer.
Question: How can I write just a regular Java program (classes, packages, ...etc...) with a machine with WEBMethods installed? Do I have to install another session of Eclipse on my hard drive? (I tried this a while back and there was an issue with having more than one session of Eclipse on the machine).
Java Web Services Code:
package DssAccessBackup.services.flow;
import com.wm.data.*;
import com.wm.util.Values;
import com.wm.app.b2b.server.Service;
import com.wm.app.b2b.server.ServiceException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public final class new_javaService_SVC
{
/**
* The primary method for the Java service
*
* #param pipeline
* The IData pipeline
* #throws ServiceException
*/
public static final void new_javaService(IData pipeline)
throws ServiceException {
// pipeline
IDataCursor pipelineCursor = pipeline.getCursor();
String inputFileName = IDataUtil.getString( pipelineCursor, "inputFileName" );
pipelineCursor.destroy();
// pipeline
IDataCursor pipelineCursor_1 = pipeline.getCursor();
IDataUtil.put( pipelineCursor_1, "fileName", "fileName" );
// outDoc
IData outDoc = IDataFactory.create();
IDataUtil.put( pipelineCursor_1, "outDoc", outDoc );
pipelineCursor_1.destroy();
String fileName = new String();
fileName = null;
try {
BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\itpr13266\\Desktop\\TestFile.txt"));
String line = null;
//Will read through the file until EOF
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("Try-Catch Message - " + e.getMessage());
e.printStackTrace();
}
}
// --- <<IS-BEGIN-SHARED-SOURCE-AREA>> ---
// --- <<IS-END-SHARED-SOURCE-AREA>> ---
}
You don't need to install another Eclipse for Java development. WebMethods Designer (v9) comes with Java tooling. Just open the Java perspective and use it.
Besides that you should use the Service Development perspective, when developing WebMethods Java Services, because WM Designer handles Java services in a special way, which could make importing standard Java files difficult.
There is no problem running multiple instances of Eclipse at the same time as long as they point to different workspaces.
Normally you get a dialog to choose the workspace when Eclipse starts up. If not, check this answer on how to enable that dialog: https://stackoverflow.com/a/8616216/1599890
So if you download, unzip and set up Eclipse for Java development and point it to another workspace than Software AG Designer uses you should be good to go.

Java: CaptureDeviceManager#getDeviceList() is empty?

I am trying to print out all of the capture devices that are supported using the #getDeviceList() method in the CaptureDeviceManager class and the returned Vector has a size of 0.
Why is that? I have a webcam that works - so there should be at least one. I am running Mac OS X Lion - using JMF 2.1.1e.
Thanks!
CaptureDeviceManager.getDeviceList(Format format) does not detect devices. Instead it reads from the JMF registry which is the jmf.properties file. It searches for the jmf.properties file in the classpath.
If your JMF install has succeeded, then the classpath would have been configured to include all the relevant JMF jars and directories. The JMF install comes with a jmf.properties file included in the 'lib' folder under the JMF installation directory. This means the jmf.properties would be located by JMStudio and you would usually see the JMStudio application executing correctly. (If your JMF install is under 'C:\Program Files', then run as administrator to get around UAC)
When you create your own application to detect the devices, the problem you described above might occur. I have seen a few questions related to the same problem. This is because your application's classpath might be different and might not include the environment classpath. Check out your IDE's properties here. The problem is that CaptureDeviceManager cannot find the jmf.properties file because it is not there.
As you have found out correctly, you can copy the jmf.properties file from the JMF installation folder. It would contain the correct device list since JMF detects it during the install (Check it out just to make sure anyway).
If you want do device detection yourself, then create an empty jmf.properties file and put it somewhere in your classpath (it might throw a java.io.EOFException initially during execution but that's properly handled by the JMF classes). Then use the following code for detecting webcams...
import javax.media.*;
import java.util.*;
public static void main(String[] args) {
VFWAuto vfwObj = new VFWAuto();
Vector devices = CaptureDeviceManager.getDeviceList(null);
Enumeration deviceEnum = devices.elements();
System.out.println("Device count : " + devices.size());
while (deviceEnum.hasMoreElements()) {
CaptureDeviceInfo cdi = (CaptureDeviceInfo) deviceEnum.nextElement();
System.out.println("Device : " + cdi.getName());
}
}
The code for the VFWAuto class is given below. This is part of the JMStudio source code. You can get a good idea on how the devices are detected and recorded in the registry. Put both classes in the same package when you test. Disregard the main method in the VFWAuto class.
import com.sun.media.protocol.vfw.VFWCapture;
import java.util.*;
import javax.media.*;
public class VFWAuto {
public VFWAuto() {
Vector devices = (Vector) CaptureDeviceManager.getDeviceList(null).clone();
Enumeration enum = devices.elements();
while (enum.hasMoreElements()) {
CaptureDeviceInfo cdi = (CaptureDeviceInfo) enum.nextElement();
String name = cdi.getName();
if (name.startsWith("vfw:"))
CaptureDeviceManager.removeDevice(cdi);
}
int nDevices = 0;
for (int i = 0; i < 10; i++) {
String name = VFWCapture.capGetDriverDescriptionName(i);
if (name != null && name.length() > 1) {
System.err.println("Found device " + name);
System.err.println("Querying device. Please wait...");
com.sun.media.protocol.vfw.VFWSourceStream.autoDetect(i);
nDevices++;
}
}
}
public static void main(String [] args) {
VFWAuto a = new VFWAuto();
System.exit(0);
}
}
Assuming you are on a Windows platform and you have a working web-cam, then this code should detect the device and populate the jmf.properties file. On the next run you can also comment out the VFWAuto section and it's object references and you can see that CaptureDeviceManager reads from the jmf.properties file.
The VFWAuto class is part of jmf.jar. You can also see the DirectSoundAuto and JavaSoundAuto classes for detecting audio devices in the JMStudio sample source code. Try it out the same way as you did for VFWAuto.
My configuration was Windows 7 64 bit + JMF 2.1.1e windows performance pack + a web-cam.
I had the same issue and I solved by invoking flush() on my ObjectInputStream object.
According to the API documentation for ObjectInputStream's constructor:
The stream header containing the magic number and version number are read from the stream and verified. This method will block until the corresponding ObjectOutputStream has written and flushed the header.
This is a very important point to be aware of when trying to send objects in both directions over a socket because opening the streams in the wrong order will cause deadlock.
Consider for example what would happen if both client and server tried to construct an ObjectInputStream from a socket's input stream, prior to either constructing the corresponding ObjectOutputStream. The ObjectInputStream constructor on the client would block, waiting for the magic number and version number to arrive over the connection, while at the same time the ObjectInputStream constructor on the server side would also block for the same reason. Hence, deadlock.
Because of this, you should always make it a practice in your code to open the ObjectOutputStream and flush it first, before you open the ObjectInputStream. The ObjectOutputStream constructor will not block, and invoking flush() will force the magic number and version number to travel over the wire. If you follow this practice in both your client and server, you shouldn't have a problem with deadlock.
Credit goes to Tim Rohaly and his explanation here.
Before calling CaptureDeviceManager.getDeviceList(), the available devices must be loaded into the memory first.
You can do it manually by running JMFRegistry after installing JMF.
or do it programmatically with the help of the extension library FMJ (Free Media in Java). Here is the code:
import java.lang.reflect.Field;
import java.util.Vector;
import javax.media.*;
import javax.media.format.RGBFormat;
import net.sf.fmj.media.cdp.GlobalCaptureDevicePlugger;
public class FMJSandbox {
static {
System.setProperty("java.library.path", "D:/fmj-sf/native/win32-x86/");
try {
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
GlobalCaptureDevicePlugger.addCaptureDevices();
Vector deviceInfo = CaptureDeviceManager.getDeviceList(new RGBFormat());
System.out.println(deviceInfo.size());
for (Object obj : deviceInfo ) {
System.out.println(obj);
}
}
}
Here is the output:
USB2.0 Camera : civil:\\?\usb#vid_5986&pid_02d3&mi_00#7&584a19f&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global
RGB, -1-bit, Masks=-1:-1:-1, PixelStride=-1, LineStride=-1

Categories