net.chocolapod.lwjgfont.texture.FontTextureLoader.java Source code

Java tutorial

Introduction

Here is the source code for net.chocolapod.lwjgfont.texture.FontTextureLoader.java

Source

/**
 *  The MIT License (MIT)
 *
 *  Copyright (c) 2014 momokan (http://lwjgfont.chocolapod.net)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
package net.chocolapod.lwjgfont.texture;

import static org.lwjgl.opengl.GL11.GL_LINEAR;
import static org.lwjgl.opengl.GL11.GL_RGBA;
import static org.lwjgl.opengl.GL11.GL_RGBA16;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
import static org.lwjgl.opengl.GL11.GL_NEAREST;
import static org.lwjgl.opengl.GL11.GL_LINEAR_MIPMAP_LINEAR;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL11.glTexImage2D;
import static org.lwjgl.opengl.GL11.glTexParameteri;

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferUShort;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.ContextAttribs;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.PixelFormat;

public class FontTextureLoader {
    private static final Map<String, FontTexture> texturesMap = new HashMap<>();

    public static FontTexture loadTexture(Class clazz, String imagePath) throws IOException {
        FontTexture texture = texturesMap.get(imagePath);

        if (texture == null) {
            texture = makeTexture(clazz, imagePath);
            texturesMap.put(imagePath, texture);
        }

        return texture;
    }

    private static FontTexture makeTexture(Class clazz, String imagePath) throws IOException {
        BufferedImage srcImage;
        int srcImageType;

        srcImage = ImageIO.read(clazz.getResourceAsStream(imagePath));
        srcImageType = srcImage.getType();

        int target = GL_TEXTURE_2D; // target
        int dstPixelFormat = GL_RGBA; // dst pixel format
        int format = GL_UNSIGNED_BYTE; // data type

        //   ? ID ??
        int textureID = GL11.glGenTextures();
        FontTexture texture = new FontTexture(target, textureID);

        //   glTexImage2D() ???? ID ??
        glBindTexture(target, textureID);

        // All RGB bytes are aligned to each other and each component is 1 byte
        //      GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);

        int width = srcImage.getWidth();
        int height = srcImage.getHeight();

        texture.setWidth(width);
        texture.setHeight(height);
        texture.setTextureWidth(width);
        texture.setTextureHeight(height);
        texture.setAlphaPremultiplied(false);

        ByteBuffer byteBuffer;
        Pixel pixel = null;

        //      System.out.println(srcImageType);
        if (srcImageType == BufferedImage.TYPE_INT_ARGB) {
            throw new RuntimeException("Unsupported type: " + srcImage.getType());
        } else if (srcImageType == BufferedImage.TYPE_3BYTE_BGR) {
            pixel = new Pixel3ByteBGR();
        } else if (srcImageType == BufferedImage.TYPE_4BYTE_ABGR) {
            //   Photoshop ? 8bit/?? ?????
            //   ?? ABGR ??????????? 8bit(1Byte) ????
            pixel = new Pixel4ByteABGR();
        } else if (srcImageType == BufferedImage.TYPE_CUSTOM) {
            //   Photoshop ? 16bit/?? ?????
            //   ?? ABGR ??????????? 16bit(2Byte) ????
            //         pixel = new Pixel8ByteABGR();
            //   ?????????
            //   MikMikuStudio/engine/src/core/com/jme3/texture/Image.java
            //   MikMikuStudio/engine/src/jogl2/com/jme3/renderer/jogl/TextureUtil.java
            //   ??????
            //         pixel = new Pixel4ByteABGR();
            /*
            dstPixelFormat = GL_RGBA2;
            dstPixelFormat = GL_RGBA8;
            */
            dstPixelFormat = GL_RGBA16;
            /*
            format = GL_UNSIGNED_SHORT;
            format = GL_SHORT;
            format = GL_UNSIGNED_SHORT_4_4_4_4;
            */

            //   Miku.png (8bit/channel)???????????? Pixel4ByteABGR ???
            pixel = new Pixel4ByteABGR();
        } else {
            throw new RuntimeException("Unsupported type: " + srcImage.getType());
        }

        byteBuffer = pixel.toBuffer(srcImage);
        byteBuffer.order(ByteOrder.nativeOrder());
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int b[] = srcImage.getRaster().getPixel(x, y, pixel.getBuffer());

                pixel.writeBuffer(byteBuffer);
            }
        }
        byteBuffer.flip();

        //   ?????
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

        //   ????????
        glTexImage2D(target, 0, dstPixelFormat, //   ???
                width, height, 0, //   ???????? 0???? 1
                GL_RGBA, //   ??? ? http://wisdom.sakura.ne.jp/system/opengl/gl22.html
                format, //   ????? http://wisdom.sakura.ne.jp/system/opengl/gl22.html
                byteBuffer);

        //   ??
        //      GL30.glGenerateMipmap(GL_TEXTURE_2D);

        byteBuffer.clear();

        return texture;
    }

    public static void dispose() {
        for (FontTexture texture : texturesMap.values()) {
            texture.dispose();
        }
        texturesMap.clear();
    }

    interface Pixel {
        public ByteBuffer toBuffer(BufferedImage srcImage);

        public int[] getBuffer();

        public void writeBuffer(ByteBuffer byteBuffer);
    }

    //   1 ??? 64 ????
    /*
    static class Pixel8ByteABGR implements Pixel {
       private int[]   buffer = new int[8];
        
       @Override
       public int[] getBuffer() {
     return buffer;
       }
        
       @Override
       public byte[] getRed() {
     return new byte[] {(byte)buffer[0]};
    //         return new byte[] {(byte)buffer[0], (byte)buffer[1]};
       }
        
       @Override
       public byte[] getGreen() {
     return new byte[] {(byte)buffer[1]};
    //         return new byte[] {(byte)buffer[2], (byte)buffer[3]};
       }
        
       @Override
       public byte[] getBlue() {
     return new byte[] {(byte)buffer[2]};
    //         return new byte[] {(byte)buffer[4], (byte)buffer[5]};
       }
        
       @Override
       public byte[] getAlpha() {
     return new byte[] {(byte)buffer[3]};
    //         return new byte[] {(byte)buffer[6], (byte)buffer[7]};
       }
           
       @Override
       public ByteBuffer toBuffer(BufferedImage srcImage) {
     DataBufferUShort   imageBuffer = (DataBufferUShort)srcImage.getRaster().getDataBuffer();   
     ByteBuffer         byteBuffer = ByteBuffer.allocateDirect(imageBuffer.getSize() * 2);
         
     return byteBuffer;
       }
    }
    */

    //   1 ??? 32 ????
    static class Pixel4ByteABGR implements Pixel {
        private int[] buffer = new int[4];

        @Override
        public int[] getBuffer() {
            return buffer;
        }

        @Override
        public ByteBuffer toBuffer(BufferedImage srcImage) {
            //   ???? 4 Byte / pixel ????
            //   ?????????????
            DataBufferByte imageBuffer = (DataBufferByte) srcImage.getRaster().getDataBuffer();
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(imageBuffer.getSize());

            return byteBuffer;
        }

        @Override
        public void writeBuffer(ByteBuffer byteBuffer) {
            byteBuffer.put(new byte[] { (byte) buffer[0], //   Red
                    (byte) buffer[1], //   Green
                    (byte) buffer[2], //   Blue
                    (byte) buffer[3] //   Alpha
            });
        }
    }

    static class Pixel3ByteBGR implements Pixel {
        private int[] buffer = new int[3];

        @Override
        public int[] getBuffer() {
            return buffer;
        }

        @Override
        public ByteBuffer toBuffer(BufferedImage srcImage) {
            //   ??? 3 Byte / pixel ????????? 4 Byte / pixel ?????
            //   ???? 3/4 ???????
            DataBufferByte imageBuffer = (DataBufferByte) srcImage.getRaster().getDataBuffer();
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(imageBuffer.getSize() / 3 * 4);

            return byteBuffer;
        }

        @Override
        public void writeBuffer(ByteBuffer byteBuffer) {
            byteBuffer.put(new byte[] { (byte) buffer[0], //   Red
                    (byte) buffer[1], //   Green
                    (byte) buffer[2], //   Blue
                    (byte) 0xff });

        }
    }

}