Setting the Cursor

Started by CodeBunny, November 04, 2010, 21:44:26

Previous topic - Next topic

CodeBunny

Okay, I'm really confused here.  ???

I changed the method I use to see if your method would work, but I get almost the same problem as before.

Here's what I do to load the IntBuffer for the cursor:

int numBytes = 3;
		if(type == "PNG" || type == "TGA")
		{
			numBytes = 4;
		}
		int width = texture.getImageWidth();
		int height = texture.getImageHeight();
		int[] imageData = new int[width * height];
		byte[] bytes = texture.getTextureData();
		
		for(int y = 0; y < height; y++)
		{
			for(int x = 0; x < width; x++)
			{
				int i = y * width + x * numBytes;

				int r = bytes[i] & 0xFF;
				int g = bytes[i + 1] & 0xFF;
				int b = bytes[i + 2] & 0xFF;
				int a = 0xFF;

				if(numBytes == 4)
				{
					a = bytes[i + 3] & 0xFF;

					if(a > 0)
					{
						double ap = a / 255.0;
						r = (int)Math.round(r * ap);
						g = (int)Math.round(g * ap);
						b = (int)Math.round(b * ap);
						a = 0xFF;
					}
				}
				imageData[y * width + x] = (a << 24) | (r << 16) | (g << 8) | (b);
			}
		}
		return IntBuffer.wrap(imageData);


I tried the method with both a bmp and a png image and both became screwed up.

jediTofu

The only thing that I noticed wrong was your i variable, should be this:

int i = y * width * numBytes + x * numBytes;

Also, I forgot about texture.hasAlpha(), you can replace <code>type == "PNG" || type == "TGA"</code> with that.

If that still doesn't give you what you want, you can try an alpha tolerance as I suggested:

//parameter
double alphaTolerancePercentage; //between 0.0 and 1.0, play around with this; try 0.5 at first

//up at very top
int alphaTolerance = 256 * alphaTolerancePercentage; //256 so that "<" works

				//replace in middle of code
				if(numBytes == 4)
				{
					a = bytes[i + 3] & 0xFF;

					if(a < alphaTolerance) {
						a = 0;
					}
					else {
						a = 0xFF;
					}
				}
cool story, bro

jediTofu

Quote from: CodeBunny on November 10, 2010, 16:06:23
One question - if you try to supply an intbuffer that holds data for translucent images, and the computer only supports 1-bit alpha cursors, does it simply convert the image, or does it mess up the cursor?

My machine only supports 1-bit alpha cursors.  When trying a PNG with varying alpha values, everything that is below 0xFF is truncated to 0, so only one pixel in the center of the image is shown (the only pixel with 0xFF alpha).

Also, I used a 64x64 image for all of my tests, forgot to mention this, so you might want to try a 64x64 image until you get your code working, and I tested it with a BMP, TGA (with and without transparency), and PNG; all worked fine.
cool story, bro

CodeBunny

You're right -

When I test it as a 64 x 64, it works fine. If I use different dimensions, it blows up.

I checked 32 x 64, and that worked. It looks like it needs to be a power of two, for whatever reason.

jediTofu

Quote from: CodeBunny on November 10, 2010, 20:01:21
You're right -

When I test it as a 64 x 64, it works fine. If I use different dimensions, it blows up.

I checked 32 x 64, and that worked. It looks like it needs to be a power of two, for whatever reason.

Since I had my testing project open, I tried a 32x40 image, and it worked.  I think that there is just a minimum cursor size.  I couldn't find an equivalent LWJGL method for this, but the Toolkit works fine:

Dimension d = Toolkit.getDefaultToolkit().getBestCursorSize(0,0);

On my machine, d.height and d.weight are 32, so I assume any height/width below 32 won't work, and from my testing, it doesn't need to be power of 2 (at least on my machine).
cool story, bro

CodeBunny

*sigh*

I found why it was locking to square roots of 2 - I needed to change

int i = y * width + x * numBytes;


To multiply y by the texture width, not the image width.



So, now the method sort of works for most images. There are two problems, though:

First, I'm getting the right colors but the alpha is still messed up somehow - sections that should be transparent appear black, and, more disturbingly, sections that should be opaque and colored in are showing images behind them.

Secondly, the method seems to break when the cursor gets very small for some reason. If I make the image something like 7 x 12, it starts getting wonky again.

If I make the cursor read the entire image, not just the image on top of it, it works better.

jediTofu

Quote from: CodeBunny on November 10, 2010, 20:34:24
If I make the image something like 7 x 12, it starts getting wonky again.

Yes, this is probably due to the minimum cursor size I bet.  When passing in an int buffer below 32x32, it's all "wonky" for me.

Yeah, completely forgot should be using texture width/height and not image width/height, but this does perplex me...as my 32x40 image worked using the image height/width and not the texture height/width.  Your width still needs to be multiplied by numBytes though.

I'm not sure about your alpha problems, as it works fine for me.  You could upload the image you're trying to your post and post the code for setting the cursor, and I could try it.
cool story, bro

Matzon

Quote from: jediTofu on November 10, 2010, 20:08:16
Since I had my testing project open, I tried a 32x40 image, and it worked.  I think that there is just a minimum cursor size.  I couldn't find an equivalent LWJGL method for this, but the Toolkit works fine:

Dimension d = Toolkit.getDefaultToolkit().getBestCursorSize(0,0);

http://lwjgl.org/javadoc/org/lwjgl/input/Cursor.html

get*CursorSize ?

jediTofu

cool story, bro

CodeBunny

I've managed to fix the cursor code for all supplied images, finally. It'll work when the image is under size by just making the additional needed space have no alpha.

Thanks for the help. :) That was an annoying problem.