| /* |
| * Copyright (c) 2009-2010 jMonkeyEngine |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
| * may be used to endorse or promote products derived from this software |
| * without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| package com.jme3.texture.plugins; |
| |
| import com.jme3.asset.AssetInfo; |
| import com.jme3.asset.AssetLoadException; |
| import com.jme3.asset.AssetLoader; |
| import com.jme3.asset.TextureKey; |
| import com.jme3.texture.Image; |
| import com.jme3.texture.Image.Format; |
| import com.jme3.util.BufferUtils; |
| import java.awt.Transparency; |
| import java.awt.color.ColorSpace; |
| import java.awt.image.*; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.nio.ByteBuffer; |
| import javax.imageio.ImageIO; |
| |
| public class AWTLoader implements AssetLoader { |
| |
| public static final ColorModel AWT_RGBA4444 = new DirectColorModel(16, |
| 0xf000, |
| 0x0f00, |
| 0x00f0, |
| 0x000f); |
| |
| public static final ColorModel AWT_RGBA5551 |
| = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), |
| new int[]{5, 5, 5, 1}, |
| true, |
| false, |
| Transparency.BITMASK, |
| DataBuffer.TYPE_BYTE); |
| |
| private Object extractImageData(BufferedImage img){ |
| DataBuffer buf = img.getRaster().getDataBuffer(); |
| switch (buf.getDataType()){ |
| case DataBuffer.TYPE_BYTE: |
| DataBufferByte byteBuf = (DataBufferByte) buf; |
| return byteBuf.getData(); |
| case DataBuffer.TYPE_USHORT: |
| DataBufferUShort shortBuf = (DataBufferUShort) buf; |
| return shortBuf.getData(); |
| } |
| return null; |
| } |
| |
| private void flipImage(byte[] img, int width, int height, int bpp){ |
| int scSz = (width * bpp) / 8; |
| byte[] sln = new byte[scSz]; |
| int y2 = 0; |
| for (int y1 = 0; y1 < height / 2; y1++){ |
| y2 = height - y1 - 1; |
| System.arraycopy(img, y1 * scSz, sln, 0, scSz); |
| System.arraycopy(img, y2 * scSz, img, y1 * scSz, scSz); |
| System.arraycopy(sln, 0, img, y2 * scSz, scSz); |
| } |
| } |
| |
| private void flipImage(short[] img, int width, int height, int bpp){ |
| int scSz = (width * bpp) / 8; |
| scSz /= 2; // Because shorts are 2 bytes |
| short[] sln = new short[scSz]; |
| int y2 = 0; |
| for (int y1 = 0; y1 < height / 2; y1++){ |
| y2 = height - y1 - 1; |
| System.arraycopy(img, y1 * scSz, sln, 0, scSz); |
| System.arraycopy(img, y2 * scSz, img, y1 * scSz, scSz); |
| System.arraycopy(sln, 0, img, y2 * scSz, scSz); |
| } |
| } |
| |
| public Image load(BufferedImage img, boolean flipY){ |
| int width = img.getWidth(); |
| int height = img.getHeight(); |
| |
| switch (img.getType()){ |
| case BufferedImage.TYPE_4BYTE_ABGR: // most common in PNG images w/ alpha |
| byte[] dataBuf1 = (byte[]) extractImageData(img); |
| if (flipY) |
| flipImage(dataBuf1, width, height, 32); |
| |
| ByteBuffer data1 = BufferUtils.createByteBuffer(img.getWidth()*img.getHeight()*4); |
| data1.put(dataBuf1); |
| return new Image(Format.ABGR8, width, height, data1); |
| case BufferedImage.TYPE_3BYTE_BGR: // most common in JPEG images |
| byte[] dataBuf2 = (byte[]) extractImageData(img); |
| if (flipY) |
| flipImage(dataBuf2, width, height, 24); |
| |
| ByteBuffer data2 = BufferUtils.createByteBuffer(img.getWidth()*img.getHeight()*3); |
| data2.put(dataBuf2); |
| return new Image(Format.BGR8, width, height, data2); |
| case BufferedImage.TYPE_BYTE_GRAY: // grayscale fonts |
| byte[] dataBuf3 = (byte[]) extractImageData(img); |
| if (flipY) |
| flipImage(dataBuf3, width, height, 8); |
| ByteBuffer data3 = BufferUtils.createByteBuffer(img.getWidth()*img.getHeight()); |
| data3.put(dataBuf3); |
| return new Image(Format.Luminance8, width, height, data3); |
| case BufferedImage.TYPE_USHORT_GRAY: // grayscale heightmap |
| short[] dataBuf4 = (short[]) extractImageData(img); |
| if (flipY) |
| flipImage(dataBuf4, width, height, 16); |
| |
| ByteBuffer data4 = BufferUtils.createByteBuffer(img.getWidth()*img.getHeight()*2); |
| data4.asShortBuffer().put(dataBuf4); |
| return new Image(Format.Luminance16, width, height, data4); |
| default: |
| break; |
| } |
| |
| if (img.getTransparency() == Transparency.OPAQUE){ |
| ByteBuffer data = BufferUtils.createByteBuffer(img.getWidth()*img.getHeight()*3); |
| // no alpha |
| for (int y = 0; y < height; y++){ |
| for (int x = 0; x < width; x++){ |
| int ny = y; |
| if (flipY){ |
| ny = height - y - 1; |
| } |
| |
| int rgb = img.getRGB(x,ny); |
| byte r = (byte) ((rgb & 0x00FF0000) >> 16); |
| byte g = (byte) ((rgb & 0x0000FF00) >> 8); |
| byte b = (byte) ((rgb & 0x000000FF)); |
| data.put(r).put(g).put(b); |
| } |
| } |
| data.flip(); |
| return new Image(Format.RGB8, width, height, data); |
| }else{ |
| ByteBuffer data = BufferUtils.createByteBuffer(img.getWidth()*img.getHeight()*4); |
| // no alpha |
| for (int y = 0; y < height; y++){ |
| for (int x = 0; x < width; x++){ |
| int ny = y; |
| if (flipY){ |
| ny = height - y - 1; |
| } |
| |
| int rgb = img.getRGB(x,ny); |
| byte a = (byte) ((rgb & 0xFF000000) >> 24); |
| byte r = (byte) ((rgb & 0x00FF0000) >> 16); |
| byte g = (byte) ((rgb & 0x0000FF00) >> 8); |
| byte b = (byte) ((rgb & 0x000000FF)); |
| data.put(r).put(g).put(b).put(a); |
| } |
| } |
| data.flip(); |
| return new Image(Format.RGBA8, width, height, data); |
| } |
| } |
| |
| public Image load(InputStream in, boolean flipY) throws IOException{ |
| ImageIO.setUseCache(false); |
| BufferedImage img = ImageIO.read(in); |
| if (img == null){ |
| return null; |
| } |
| return load(img, flipY); |
| } |
| |
| public Object load(AssetInfo info) throws IOException { |
| if (ImageIO.getImageReadersBySuffix(info.getKey().getExtension()) != null){ |
| boolean flip = ((TextureKey) info.getKey()).isFlipY(); |
| InputStream in = null; |
| try { |
| in = info.openStream(); |
| Image img = load(in, flip); |
| if (img == null){ |
| throw new AssetLoadException("The given image cannot be loaded " + info.getKey()); |
| } |
| return img; |
| } finally { |
| if (in != null){ |
| in.close(); |
| } |
| } |
| }else{ |
| throw new AssetLoadException("The extension " + info.getKey().getExtension() + " is not supported"); |
| } |
| } |
| } |