Home | History | Annotate | Download | only in plugins
      1 /*
      2  * Copyright (c) 2009-2010 jMonkeyEngine
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  * * Redistributions of source code must retain the above copyright
     10  *   notice, this list of conditions and the following disclaimer.
     11  *
     12  * * Redistributions in binary form must reproduce the above copyright
     13  *   notice, this list of conditions and the following disclaimer in the
     14  *   documentation and/or other materials provided with the distribution.
     15  *
     16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
     17  *   may be used to endorse or promote products derived from this software
     18  *   without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 package com.jme3.texture.plugins;
     34 
     35 import com.jme3.asset.AssetInfo;
     36 import com.jme3.asset.AssetLoadException;
     37 import com.jme3.asset.AssetLoader;
     38 import com.jme3.asset.TextureKey;
     39 import com.jme3.texture.Image;
     40 import com.jme3.texture.Image.Format;
     41 import com.jme3.util.BufferUtils;
     42 import java.awt.Transparency;
     43 import java.awt.color.ColorSpace;
     44 import java.awt.image.*;
     45 import java.io.IOException;
     46 import java.io.InputStream;
     47 import java.nio.ByteBuffer;
     48 import javax.imageio.ImageIO;
     49 
     50 public class AWTLoader implements AssetLoader {
     51 
     52     public static final ColorModel AWT_RGBA4444 = new DirectColorModel(16,
     53                                                                        0xf000,
     54                                                                        0x0f00,
     55                                                                        0x00f0,
     56                                                                        0x000f);
     57 
     58     public static final ColorModel AWT_RGBA5551
     59             = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
     60                                       new int[]{5, 5, 5, 1},
     61                                       true,
     62                                       false,
     63                                       Transparency.BITMASK,
     64                                       DataBuffer.TYPE_BYTE);
     65 
     66     private Object extractImageData(BufferedImage img){
     67         DataBuffer buf = img.getRaster().getDataBuffer();
     68         switch (buf.getDataType()){
     69             case DataBuffer.TYPE_BYTE:
     70                 DataBufferByte byteBuf = (DataBufferByte) buf;
     71                 return byteBuf.getData();
     72             case DataBuffer.TYPE_USHORT:
     73                 DataBufferUShort shortBuf = (DataBufferUShort) buf;
     74                 return shortBuf.getData();
     75         }
     76         return null;
     77     }
     78 
     79     private void flipImage(byte[] img, int width, int height, int bpp){
     80         int scSz = (width * bpp) / 8;
     81         byte[] sln = new byte[scSz];
     82         int y2 = 0;
     83         for (int y1 = 0; y1 < height / 2; y1++){
     84             y2 = height - y1 - 1;
     85             System.arraycopy(img, y1 * scSz, sln, 0,         scSz);
     86             System.arraycopy(img, y2 * scSz, img, y1 * scSz, scSz);
     87             System.arraycopy(sln, 0,         img, y2 * scSz, scSz);
     88         }
     89     }
     90 
     91     private void flipImage(short[] img, int width, int height, int bpp){
     92         int scSz = (width * bpp) / 8;
     93         scSz /= 2; // Because shorts are 2 bytes
     94         short[] sln = new short[scSz];
     95         int y2 = 0;
     96         for (int y1 = 0; y1 < height / 2; y1++){
     97             y2 = height - y1 - 1;
     98             System.arraycopy(img, y1 * scSz, sln, 0,         scSz);
     99             System.arraycopy(img, y2 * scSz, img, y1 * scSz, scSz);
    100             System.arraycopy(sln, 0,         img, y2 * scSz, scSz);
    101         }
    102     }
    103 
    104     public Image load(BufferedImage img, boolean flipY){
    105         int width = img.getWidth();
    106         int height = img.getHeight();
    107 
    108         switch (img.getType()){
    109             case BufferedImage.TYPE_4BYTE_ABGR: // most common in PNG images w/ alpha
    110                byte[] dataBuf1 = (byte[]) extractImageData(img);
    111                if (flipY)
    112                    flipImage(dataBuf1, width, height, 32);
    113 
    114                ByteBuffer data1 = BufferUtils.createByteBuffer(img.getWidth()*img.getHeight()*4);
    115                data1.put(dataBuf1);
    116                return new Image(Format.ABGR8, width, height, data1);
    117             case BufferedImage.TYPE_3BYTE_BGR: // most common in JPEG images
    118                byte[] dataBuf2 = (byte[]) extractImageData(img);
    119                if (flipY)
    120                    flipImage(dataBuf2, width, height, 24);
    121 
    122                ByteBuffer data2 = BufferUtils.createByteBuffer(img.getWidth()*img.getHeight()*3);
    123                data2.put(dataBuf2);
    124                return new Image(Format.BGR8, width, height, data2);
    125             case BufferedImage.TYPE_BYTE_GRAY: // grayscale fonts
    126                 byte[] dataBuf3 = (byte[]) extractImageData(img);
    127                 if (flipY)
    128                     flipImage(dataBuf3, width, height, 8);
    129                 ByteBuffer data3 = BufferUtils.createByteBuffer(img.getWidth()*img.getHeight());
    130                 data3.put(dataBuf3);
    131                 return new Image(Format.Luminance8, width, height, data3);
    132             case BufferedImage.TYPE_USHORT_GRAY: // grayscale heightmap
    133                 short[] dataBuf4 = (short[]) extractImageData(img);
    134                 if (flipY)
    135                     flipImage(dataBuf4, width, height, 16);
    136 
    137                 ByteBuffer data4 = BufferUtils.createByteBuffer(img.getWidth()*img.getHeight()*2);
    138                 data4.asShortBuffer().put(dataBuf4);
    139                 return new Image(Format.Luminance16, width, height, data4);
    140             default:
    141                 break;
    142         }
    143 
    144         if (img.getTransparency() == Transparency.OPAQUE){
    145             ByteBuffer data = BufferUtils.createByteBuffer(img.getWidth()*img.getHeight()*3);
    146             // no alpha
    147             for (int y = 0; y < height; y++){
    148                 for (int x = 0; x < width; x++){
    149                     int ny = y;
    150                     if (flipY){
    151                         ny = height - y - 1;
    152                     }
    153 
    154                     int rgb = img.getRGB(x,ny);
    155                     byte r = (byte) ((rgb & 0x00FF0000) >> 16);
    156                     byte g = (byte) ((rgb & 0x0000FF00) >> 8);
    157                     byte b = (byte) ((rgb & 0x000000FF));
    158                     data.put(r).put(g).put(b);
    159                 }
    160             }
    161             data.flip();
    162             return new Image(Format.RGB8, width, height, data);
    163         }else{
    164             ByteBuffer data = BufferUtils.createByteBuffer(img.getWidth()*img.getHeight()*4);
    165             // no alpha
    166             for (int y = 0; y < height; y++){
    167                 for (int x = 0; x < width; x++){
    168                     int ny = y;
    169                     if (flipY){
    170                         ny = height - y - 1;
    171                     }
    172 
    173                     int rgb = img.getRGB(x,ny);
    174                     byte a = (byte) ((rgb & 0xFF000000) >> 24);
    175                     byte r = (byte) ((rgb & 0x00FF0000) >> 16);
    176                     byte g = (byte) ((rgb & 0x0000FF00) >> 8);
    177                     byte b = (byte) ((rgb & 0x000000FF));
    178                     data.put(r).put(g).put(b).put(a);
    179                 }
    180             }
    181             data.flip();
    182             return new Image(Format.RGBA8, width, height, data);
    183         }
    184     }
    185 
    186     public Image load(InputStream in, boolean flipY) throws IOException{
    187         ImageIO.setUseCache(false);
    188         BufferedImage img = ImageIO.read(in);
    189         if (img == null){
    190             return null;
    191         }
    192         return load(img, flipY);
    193     }
    194 
    195     public Object load(AssetInfo info) throws IOException {
    196         if (ImageIO.getImageReadersBySuffix(info.getKey().getExtension()) != null){
    197             boolean flip = ((TextureKey) info.getKey()).isFlipY();
    198             InputStream in = null;
    199             try {
    200                 in = info.openStream();
    201                 Image img = load(in, flip);
    202                 if (img == null){
    203                     throw new AssetLoadException("The given image cannot be loaded " + info.getKey());
    204                 }
    205                 return img;
    206             } finally {
    207                 if (in != null){
    208                     in.close();
    209                 }
    210             }
    211         }else{
    212             throw new AssetLoadException("The extension " + info.getKey().getExtension() + " is not supported");
    213         }
    214     }
    215 }
    216