/* * 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"); } } }