J2ME MIDP1 CreateImage problem

S

Steven J Sobol

So I'm playing around with J2ME, since I now have a slick J2ME-enabled
cell phone. Phone in question is a Samsung SPH-A660 using (I think) MIDP 1.0,
but it doesn't matter because this piece of crap doesn't work in the MIDP 2.0
emulator I downloaded from Sun either, so it's not a MIDP implementation issue. Nor does it work in the slightly-modified MIDP emulator I downloaded from
Sprint PCS. (By that I mean that Sprint's Wireless Toolkit is basically Sun's
toolkit but has a couple device profiles customized for Sprint.)

I'm frustrated to the point of putting my fist through the picture tube of
my monitor. The fact that I am using a laptop that has an LCD screen that
has no picture tube only adds to my frustration. :)

The issue is quite simple. This code

try{
g.drawImage(Image.createImage("/x.jpg"),30,30,Graphics.TOP|Graphics.LEFT);
}
catch(Exception e) {System.out.println("IOException: " + e.getMessage() );}

doesn't work, and yes, I've checked that the file is in the proper place.

When running the midlet, the createImage call generates an exception, but
all I see is:

IOException: null

So I have NO clue what steps to take to fix this problem. This createImage
call is part of a subclass of the MIDP Canvas class.

I'd offer more info, but I don't really have anything else to give you...
 
R

Roedy Green

Image.createImage("/x.jpg")

I am puzzled by this. I am not a J2ME programmer, but in regular Java
there is no such method.

There is this one that expects a byte array.

Toolkit.getDefaultToolkit().createImage( baos.toByteArray() );

and there are these methods:

URL url = this.getClass().getResource( "images/blueball.gif" );

// Depending on where getResource found the resource,
// the URL will look like one of the following:

// in local jar:
//
jar:file:/E:/com/mindprod/thepackage/thepackage.jar!/com/mindprod/thepackage/images/blueball.gif

// in remote jar:
//
jar:http://mindprod.com/thepackage.jar!/com/mindprod/thepackage/images/blueball.gif

// in local file:
// file:/E:/com/mindprod/thepackage/images/blueball.gif

// in remote file:
// http://mindprod.com/com/mindprod/thepackage/images/blueball.gif

// Once you have the URL, you can get the image.
Image blueball = component.getToolKit().getImage( url );

// alternatively, you can use

MyClass.class

// instead of

this.getClass()

// and

Toolkit.getDefaultToolkit()

// instead of

component.getToolKit()

// and

createImage( ( ImageProducer ) url.getContent() )

// instead of

getImage( url )


See http://mindprod.com/jgloss/image.html
for various technques of getting images in J2SE.
 
S

Steven J Sobol

Roedy Green said:
I am puzzled by this. I am not a J2ME programmer, but in regular Java
there is no such method.

Indeed there isn't. I believe it only exists in J2ME.
There is this one that expects a byte array.

Toolkit.getDefaultToolkit().createImage( baos.toByteArray() );

and there are these methods:

URL url = this.getClass().getResource( "images/blueball.gif" );

And that's (almost) what Image.createImage(String) does in MIDP 1.0 and 2.0.
The MIDP classes are NOT subclasses of AWT classes, although in some cases they
they have the same names and some of the same method prototypes. Image is
actually javax.microedition.lcdui.Image. Javadoc says:

---------------------------
public static Image createImage(String name)
throws java.io.IOException

Creates an immutable image from decoded image data obtained from the named
resource. The name parameter is a resource name as defined by
Class.getResourceAsStream(name). The rules for resolving resource names are
defined in the Application Resource Files section of the java.lang package
documentation.
---------------------------

I've successfully used the standard process, using the defaultToolkit,
in other situations. Maybe I should try it here.

Is there a Java newsgroup devoted to J2ME?
 
R

Roedy Green

Creates an immutable image from decoded image data obtained from the named
resource. The name parameter is a resource name as defined by
Class.getResourceAsStream(name). The rules for resolving resource names are
defined in the Application Resource Files section of the java.lang package
documentation.

I would focus for a second on the format of that String. Have you
done the similar set of experiments that I did to find out what sorts
of string getResource comes up with in different circumstances so that
you can short circuit it?

I would expect something more concrete to be required than "/x.jpg"
 
S

Steven J Sobol

Roedy Green said:
I would focus for a second on the format of that String. Have you
done the similar set of experiments that I did to find out what sorts
of string getResource comes up with in different circumstances so that
you can short circuit it?

Good question. As far as I'm concerned, a String is a String is a String.
OTOH, I'm wondering if the "rules for resolving resource names" aren't what's
biting me in the butt here.
I would expect something more concrete to be required than "/x.jpg"

Yahbut, the docs only say you need to pass a String... The sample Games
midlet creates a StringBuffer and then uses its toString method, but I am
not sure why just passing a string literal wouldn't work.

The loud noise you hear is me banging my head against the wall. I'll get
back to you with the results of that, as well as the results of further
research...
 
S

Steven J Sobol

Steven J Sobol said:
Good question. As far as I'm concerned, a String is a String is a String.
OTOH, I'm wondering if the "rules for resolving resource names" aren't what's
biting me in the butt here.

Further research reveals...

1. createImage("/path/to/graphic") with a literal string works fine.

2. There seems to be a scope issue. If I put the createImage calls in
the constructor or the init() method, when paint() or another method tries
to use the images in a call to drawImage, I get a null pointer exception.
(This despite the fact that the Image objects are NOT set up using private
variables; they're class members.)

Putting the call to createImage inside the paint() method results in the
images being drawn as they are supposed to be drawn.

I've tried setting the class members containing the Image objects as
private, protected and public; as static and non-static - and unless the
createImage call exists within the paint() method and not in some other
method, the midlet does not work.
 
R

Roedy Green

Yahbut, the docs only say you need to pass a String... The sample Games
midlet creates a StringBuffer and then uses its toString method, but I am
not sure why just passing a string literal wouldn't work.

Yes, but it may have to be a special string, e.g. a URL or something
like a URL.

I suggest you do an experiment to see what sort of String getResource
coughs up.
 
R

Roedy Green

Putting the call to createImage inside the paint() method results in the
images being drawn as they are supposed to be drawn.

In J2SE you must load the images and MediaTrack them. You can't paint
them onto components whose peers don't exist yet. I'd be surprised if
J2ME were much easier.

I suggest reading up on how images work in J2SE, at
http://mindprod.com/jgloss/image.html

Then read the docs on J2ME with that in mind to make sure you are not
overlooking something.
 
D

DigiAl

Steven J Sobol said:
So I'm playing around with J2ME, since I now have a slick J2ME-enabled
cell phone. Phone in question is a Samsung SPH-A660 using (I think) MIDP 1.0,
but it doesn't matter because this piece of crap doesn't work in the MIDP 2.0
emulator I downloaded from Sun either, so it's not a MIDP implementation
issue. Nor does it work in the slightly-modified MIDP emulator I downloaded
from
Sprint PCS. (By that I mean that Sprint's Wireless Toolkit is basically Sun's
toolkit but has a couple device profiles customized for Sprint.)

I'm frustrated to the point of putting my fist through the picture tube of
my monitor. The fact that I am using a laptop that has an LCD screen that
has no picture tube only adds to my frustration. :)

The issue is quite simple. This code

try{
g.drawImage(Image.createImage("/x.jpg"),30,30,Graphics.TOP|Graphics.LEFT);
}
catch(Exception e) {System.out.println("IOException: " + e.getMessage() );}

doesn't work, and yes, I've checked that the file is in the proper place.

When running the midlet, the createImage call generates an exception, but
all I see is:

IOException: null

So I have NO clue what steps to take to fix this problem. This createImage
call is part of a subclass of the MIDP Canvas class.

I'd offer more info, but I don't really have anything else to give you...

--
JustThe.net Internet & New Media Services, http://JustThe.net/
Steven J. Sobol, Geek In Charge / 888.480.4NET (4638) / (e-mail address removed)
PGP Key available from your friendly local key server (0xE3AE35ED)
Apple Valley, California Nothing scares me anymore. I have three kids.


Hi,

Just noticed this thread, two suggestions:

* try opening the .jar file and see if your image is in the root of the
jar - if so "/x.jpg" is correct (scope-wise)

* By standard J2ME implementations only require to give png support - try
converting your image to png.

alan.
 
S

Steven J Sobol

DigiAl said:
Hi,

Just noticed this thread, two suggestions:

* try opening the .jar file and see if your image is in the root of the
jar - if so "/x.jpg" is correct (scope-wise)

* By standard J2ME implementations only require to give png support - try
converting your image to png.

MIDP2 apparently supports JPEG and other formats and when I put the createImage
calls in the paint() method they worked regardless of format, but I noticed
that the original spec only supports PNG and converted my graphics to PNG
anyhow. It look like the issue is one of scope. The files are in the right
place in the JAR and if the CreateImage call in made in the paint() method
it works, but if I put the createImage call anywhere else, the Image object
ends up being null when paint() accesses it. Very weird.
 
S

Steven J Sobol

Steven J Sobol said:
calls in the paint() method they worked regardless of format, but I noticed
that the original spec only supports PNG and converted my graphics to PNG
anyhow. It look like the issue is one of scope. The files are in the right
place in the JAR and if the CreateImage call in made in the paint() method
it works, but if I put the createImage call anywhere else, the Image object
ends up being null when paint() accesses it. Very weird.

I figured out what I did wrong. 1-D-10-T error ;)

I had been putting the calls to the function calling createImage() in the
class constructor, but the class name started with a capital letter and
the constructor didn't, so the createImage() calls were never executed.

Also fixed a couple other problems, and things work great now.
 
D

Darryl L. Pierce

Steven said:
try{
g.drawImage(Image.createImage("/x.jpg"),30,30,Graphics.TOP Graphics.LEFT);
}
catch(Exception e) {System.out.println("IOException: " + e.getMessage()
);}

doesn't work, and yes, I've checked that the file is in the proper place.

When running the midlet, the createImage call generates an exception, but
all I see is:

IOException: null

This says that the file is not actually there. Have you listed the JAR to
see that it is in fact there? Also note that JPG is not a required format
to be supported. It might be that the phone can't handle that encoding. MIDP
only requires PNG to be supported.
So I have NO clue what steps to take to fix this problem. This createImage
call is part of a subclass of the MIDP Canvas class.

Image isn't a subclass of Canvas.
 
D

Darryl L. Pierce

Steven said:
MIDP2 apparently supports JPEG and other formats and when I put the
createImage calls in the paint() method they worked regardless of format,
but I noticed that the original spec only supports PNG and converted my
graphics to PNG anyhow. It look like the issue is one of scope. The files
are in the right place in the JAR and if the CreateImage call in made in
the paint() method it works, but if I put the createImage call anywhere
else, the Image object ends up being null when paint() accesses it. Very
weird.

Can you show us the code where you're loading this image elsewhere? It
sounds like you may be inadvertantly creating a local variable in those
other places.
 
D

Darryl L. Pierce

Roedy said:
Yes, but it may have to be a special string, e.g. a URL or something
like a URL.

It's not. It's a simple value in the form of
"/[directories/]filename.extension".
 
D

Darryl L. Pierce

Steven said:
2. There seems to be a scope issue. If I put the createImage calls in
the constructor or the init() method, when paint() or another method tries
to use the images in a call to drawImage, I get a null pointer exception.
(This despite the fact that the Image objects are NOT set up using private
variables; they're class members.)

Putting the call to createImage inside the paint() method results in the
images being drawn as they are supposed to be drawn.

I've tried setting the class members containing the Image objects as
private, protected and public; as static and non-static - and unless the
createImage call exists within the paint() method and not in some other
method, the midlet does not work.

It is *not* a scope issue. It is a clear bug in your code for creating your
instances of Image. Please post the full source code as is and I'll be glad
to help you with it.
 
R

Roedy Green

I had been putting the calls to the function calling createImage() in the
class constructor, but the class name started with a capital letter and
the constructor didn't, so the createImage() calls were never executed.

If you are really stuck, chances are one of your fundamental
assumptions is wrong. So what you do is put in code to check the
obvious, that the parameters are indeed what you think they are, that
the code is indeed getting called when you think it is, that the
method is in the package you think it is, that the method is returning
an object of the type you expect...

Another thing to do is to google for that methodname and see how other
people use it, or what gotchas they complain about. You are unlikely
the first person on the planet to fall into any given pit.
 
S

Steven J Sobol

Roedy Green said:
If you are really stuck, chances are one of your fundamental
assumptions is wrong. So what you do is put in code to check the
obvious, that the parameters are indeed what you think they are, that
the code is indeed getting called when you think it is, that the
method is in the package you think it is, that the method is returning
an object of the type you expect...

I know. I do this wherever possible. Doing it with the Wireless Toolkit
is a bit of a pain; even more so when you're using an IDE plugin (started
with NetBeans and am now using Eclipse and eclipseme).

But the thing this time was that I missed a typo that I should have caught
earlier..
 
S

Steven J Sobol

Darryl L. Pierce said:
Can you show us the code where you're loading this image elsewhere? It
sounds like you may be inadvertantly creating a local variable in those
other places.

But in a followup elsewhere in this thread, you said it *wasn't* a scope
issue. :)

I figured it out... was a typo, constructor wasn't getting called and that's
where I had the call to the function that called createImage().
 
D

Darryl L. Pierce

Steven said:
But in a followup elsewhere in this thread, you said it *wasn't* a scope
issue. :)

It's not. It's a bug in your code, which is different.
I figured it out... was a typo, constructor wasn't getting called and
that's where I had the call to the function that called createImage().

As I said, it's not a scope issue, it's a bug. ;)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top