Loading Icon, wrong format ? [solved]

Started by Askigh, February 22, 2018, 20:27:20

Previous topic - Next topic

Askigh

Hi everyone 

I am currently trying to render an icon ; here is my code :



ByteBuffer[] buffArray = new ByteBuffer[3];
buffArray[0] = LoaderUtils.toByteBuffer("icon32PNG");
buffArray[1] = LoaderUtils.loadIcon("icon64PNG");
buffArray[2] = LoaderUtils.loadIcon("icon256PNG");
           
Display.setIcon(buffArray);

// LoaderUtils
public static ByteBuffer toByteBuffer(String fileName) throws IOException {

      File file = new File("res/"+fileName+".png");

      FileDataSource fsource = new FileDataSource(file);
      InputStream stream = fsource.getInputStream();

      BufferedImage img = ImageIO.read(stream);
      final int w = img.getWidth();
      final int h = img.getHeight();
      byte rgbData[] = new byte[w * h];
      for (int i = 0; i < rgbData.length; i++) {
         int x = i % w;
         int y = h - 1 - i / w;
         rgbData = (byte) img.getRGB(x, y);
      }
      ByteBuffer buffer = BufferUtils.createByteBuffer(w * h);
      buffer.put(rgbData);
      buffer.flip();
      stream.close();

      return buffer;

   }

The icon changed, but looks very awful. I checked other forums, and I think the problem is that the image need to be in a .rgba format. The problem is that my method toByteBuffer do not recognize the rgba file as an image, so it does not work. Do you have any idea how I can fix that ? Maybe it is simple but I don't master the out/in object a lot, so please be gentle  ;D
Kind regards,
Askigh

Andrew Alfazy

Hi,
I'm not professional :P but I'm Using this code to load RGBA PNG
public class PNG {

	private static final int BYTES_PER_PIXEL = 4;//3 For RGB / 4 for RGBA

	private static ByteBuffer decode(BufferedImage image) {
		int[] pixels = new int[image.getWidth() * image.getHeight()];
		image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0,
				image.getWidth());
		ByteBuffer buffer = BufferUtils.createByteBuffer(
				image.getWidth() * image.getHeight() * BYTES_PER_PIXEL);
		for (int y = 0; y < image.getHeight(); y++) {
			for (int x = 0; x < image.getWidth(); x++) {
				int pixel = pixels[y * image.getWidth() + x];
				buffer.put((byte) ((pixel >> 16) & 0xFF));
				buffer.put((byte) ((pixel >> 8) & 0xFF));
				buffer.put((byte) (pixel & 0xFF));
				buffer.put((byte) ((pixel >> 24) & 0xFF));//Maybe for RGBA (Alpha Chanel)
			}
		}
		buffer.flip();
		return buffer;
	}
	private static BufferedImage readImage(String path) {
		try {
			return ImageIO.read(new File(path));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}

Askigh

Oh, thanks a lot I'll try it tomorrow  ;D

Askigh

Hi again, unfortunately it doesn't work  :'(

ByteBuffer[] buffArray = new ByteBuffer[3];
buffArray[0] = LoaderUtils.loadIcon("icon32PNG");
buffArray[1] = LoaderUtils.loadIcon("icon64PNG");
buffArray[2] = LoaderUtils.loadIcon("icon256PNG");
Display.setIcon(buffArray);

this is the code (which is right i think) I used to set the icon.
Then I copied exactly the code you gave me (or maybe I need glasses :D)

public static ByteBuffer loadIcon(String path) {

		BufferedImage image = readImage(path);

		int[] pixels = new int[image.getWidth() * image.getHeight()];
		image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0,
				image.getWidth());
		ByteBuffer buffer = BufferUtils.createByteBuffer(
				
				image.getWidth() * image.getHeight() * BYTES_PER_PIXEL);
		for (int y = 0; y < image.getHeight(); y++) {
			for (int x = 0; x < image.getWidth(); x++) {
				int pixel = pixels[y * image.getWidth() + x];
				buffer.put((byte) ((pixel >> 16) & 0xFF));
				buffer.put((byte) ((pixel >> 8) & 0xFF));
				buffer.put((byte) (pixel & 0xFF));
				buffer.put((byte) ((pixel >> 24) & 0xFF)); //Maybe for RGBA (Alpha Chanel)
			}
		}
		
		buffer.flip();
		return buffer;

	}
	
	private static BufferedImage readImage(String path) {
		
		try {
			return ImageIO.read(new File("res/"+path+".png"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

No error, but the icon doesn't change at all. The images I select must be good, because it worked with my old method (but looked awful)

Andrew Alfazy

Can you send Icons for me(Upload it on form or Email me androawy@gmail.com) I'll try to find the problem.

Andrew Alfazy

Hi again, :D
1-Make sure that your BYTES_PER_PIXEL = 4;
2-I tried it and worked for me.
my code
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;

public class Main {

	public static void main(String[] args) throws LWJGLException {

		ByteBuffer container[] = new ByteBuffer[4];
		container[0] = decode(readImage("res/icon16PNG.png"));
		container[1] = decode(readImage("res/icon32PNG.png"));
		container[2] = decode(readImage("res/icon64PNG.png"));
		container[3] = decode(readImage("res/icon256PNG.png"));

		Display.setIcon(container);
		Display.setDisplayMode(new DisplayMode(800, 600));
		Display.create();
		while (!Display.isCloseRequested()) {
			glClear(GL_COLOR_BUFFER_BIT);
			Display.update();
		}
		Display.destroy();
		System.exit(0);

	}

	private static final int BYTES_PER_PIXEL = 4;

	public static ByteBuffer decode(BufferedImage image) {
		int[] pixels = new int[image.getWidth() * image.getHeight()];
		image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0,
				image.getWidth());
		ByteBuffer buffer = BufferUtils.createByteBuffer(
				image.getWidth() * image.getHeight() * BYTES_PER_PIXEL);
		for (int y = 0; y < image.getHeight(); y++) {
			for (int x = 0; x < image.getWidth(); x++) {
				int pixel = pixels[y * image.getWidth() + x];
				buffer.put((byte) ((pixel >> 16) & 0xFF));
				buffer.put((byte) ((pixel >> 8) & 0xFF));
				buffer.put((byte) (pixel & 0xFF));
				buffer.put((byte) ((pixel >> 24) & 0xFF));
			}
		}
		buffer.flip();
		return buffer;
	}

	public static BufferedImage readImage(String path) {
		try {
			return ImageIO.read(new File(path));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}

3-to fix the awful look just make 16x16 one with a good program like gimp (scale 32x32 one with liner or cubic) adding alpha channel will help.
the problem is The task bar and icon bar require a 16x16 image so that lwjgl scales 32x32 to 16x16 without filtering (nearest).just make 16x16 one with program like Gimp ,Photoshop,etc.
I'v send the one I've made to your email.

Askigh

Hi again, thanks a lot it works ! My code was right, the problem is that i can't read a javadoc (lol). As an information :

public static int setIcon(java.nio.ByteBuffer[] icons)

Sets one or more icons for the Display. 
On Windows you should supply at least one 16x16 icon and one 32x32.
Linux (and similar platforms) expect one 32x32 icon.
Mac OS X should be supplied one 128x128 icon
The implementation will use the supplied ByteBuffers with image data in RGBA (size must be a power of two) and perform any conversions nescesarry for the specific platform. 
NOTE: The display will make a deep copy of the supplied byte buffer array, for the purpose of recreating the icons when you go back and forth fullscreen mode. You therefore only need to set the icon once per instance.
Parameters:
icons - Array of icons in RGBA mode. Pass the icons in order of preference.
Returns:
number of icons used, or 0 if display hasn't been created