⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ddsloader.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2003-2009 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.jme.image.util;

import java.io.DataInput;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;

import com.jme.image.Image;
import com.jme.image.Image.Format;
import com.jme.util.LittleEndien;
import com.jme.util.geom.BufferUtils;
import java.util.ArrayList;
import java.util.logging.Logger;

/**
 * 
 * <code>DDSLoader</code> is an image loader that reads in a DirectX DDS file.
 * Supports DXT1, DXT3, DXT5, RGB, RGBA, Grayscale, Alpha pixel formats.
 * 2D images, mipmapped 2D images, and cubemaps.
 * 
 * @author Gareth Jenkins-Jones
 * @author Kirill Vainer
 * @version $Id: DDSLoader.java,v 2.0 2008/8/15
 */
public final class DDSLoader {
    
    private static final Logger logger = Logger.getLogger(DDSLoader.class.getName());
    
    private DDSLoader() {
    }

    public static Image loadImage(InputStream fis) throws IOException {
        return loadImage(fis, false);
    }
    
    public static Image loadImage(InputStream fis, boolean flip) throws IOException {
        DDSReader reader = new DDSReader(fis);
        reader.loadHeader();
        ArrayList<ByteBuffer> data = reader.readData(flip);

        return new Image(reader.pixelFormat_, reader.width_, reader.height_, 0, data, reader.sizes_);
    }

    /**
     * DDS reader
     * 
     * @author Gareth
     */
    public static class DDSReader {
        private static final int DDSD_MANDATORY = 0x1007;
        private static final int DDSD_MIPMAPCOUNT = 0x20000;
        private static final int DDSD_LINEARSIZE = 0x80000;
        private static final int DDSD_DEPTH = 0x800000;

        private static final int DDPF_ALPHAPIXELS = 0x1;
        private static final int DDPF_FOURCC = 0x4;
        private static final int DDPF_RGB = 0x40;
        // used by compressonator to mark grayscale images, red channel mask is used for data and bitcount is 8
        private static final int DDPF_GRAYSCALE = 0x20000;
        // used by compressonator to mark alpha images, alpha channel mask is used for data and bitcount is 8 
        private static final int DDPF_ALPHA = 0x2;

        
        private static final int DDSCAPS_COMPLEX = 0x8;
        private static final int DDSCAPS_TEXTURE = 0x1000;
        private static final int DDSCAPS_MIPMAP = 0x400000;

        private static final int DDSCAPS2_CUBEMAP = 0x200;
        private static final int DDSCAPS2_VOLUME = 0x200000;

        private static final int PF_DXT1 = 0x31545844;
        private static final int PF_DXT3 = 0x33545844;
        private static final int PF_DXT5 = 0x35545844;

        private static final double LOG2 = Math.log(2);

        private int width_;
        private int height_;
        private int depth_; // currently unused
        private int flags_;
        private int pitchOrSize_;
        private int mipMapCount_;
        private int caps1_;
        private int caps2_;

        private boolean compressed_;
        private boolean grayscaleOrAlpha_;
        private Image.Format pixelFormat_;
        private int bpp_;
        private int[] sizes_;

        private int redMask_, greenMask_, blueMask_, alphaMask_;

        private DataInput in_;

        public DDSReader(InputStream in) {
            in_ = new LittleEndien(in);
        }

        /**
         * Reads the header (first 128 bytes) of a DDS File
         */
        public void loadHeader() throws IOException {
            if (in_.readInt() != 0x20534444 || in_.readInt() != 124) {
                throw new IOException("Not a DDS file");
            }

            flags_ = in_.readInt();

            if (!is(flags_, DDSD_MANDATORY)) {
                throw new IOException("Mandatory flags missing");
            }
            if (is(flags_, DDSD_DEPTH)) {
                throw new IOException("Depth not supported");
            }

            height_ = in_.readInt();
            width_ = in_.readInt();
            pitchOrSize_ = in_.readInt();
            depth_ = in_.readInt();
            mipMapCount_ = in_.readInt();
            in_.skipBytes(44);
            readPixelFormat();
            caps1_ = in_.readInt();
            caps2_ = in_.readInt();
            in_.skipBytes(12);

            if (!is(caps1_, DDSCAPS_TEXTURE)) {
                throw new IOException("File is not a texture");
            }
            
            if (is(caps2_, DDSCAPS2_VOLUME)) {
                throw new IOException("Volume textures not supported");
            }else{
                depth_ = 0;
            }

            int expectedMipmaps = 1 + (int) Math.ceil(Math.log(Math.max(height_, width_)) / LOG2);

            if (is(caps1_, DDSCAPS_MIPMAP)) {
                if (!is(flags_, DDSD_MIPMAPCOUNT)) {
                    mipMapCount_ = expectedMipmaps;
                } else if (mipMapCount_ != expectedMipmaps) {
                    // changed to warning- images often do not have the required amount,
                    // or specify that they have mipmaps but include only the top level..
                    logger.warning("Got " + mipMapCount_ + "mipmaps, expected" + expectedMipmaps);
                }
            } else {
                mipMapCount_ = 1;
            }

            loadSizes();
        }

        /**
         * Reads the PixelFormat structure in a DDS file
         */
        private void readPixelFormat() throws IOException {
            int pfSize = in_.readInt();
            if (pfSize != 32) {
                throw new IOException("Pixel format size is " + pfSize
                        + ", not 32");
            }

            int flags = in_.readInt();

            if (is(flags, DDPF_FOURCC)) {
                compressed_ = true;
                int fourcc = in_.readInt();
                in_.skipBytes(20);

                switch (fourcc) {
                case PF_DXT1:
                    bpp_ = 4;
                    if (is(flags, DDPF_ALPHAPIXELS)) {
                        pixelFormat_ = Image.Format.NativeDXT1A;
                    } else {
                        pixelFormat_ = Image.Format.NativeDXT1;
                    }
                    break;
                case PF_DXT3:
                    bpp_ = 8;
                    pixelFormat_ = Image.Format.NativeDXT3;
                    break;
                case PF_DXT5:
                    bpp_ = 8;
                    pixelFormat_ = Image.Format.NativeDXT5;
                    break;
                default:
                    throw new IOException("Unknown fourcc: " + string(fourcc));
                }

                int size = ((width_ + 3) / 4) * ((height_ + 3) / 4) * bpp_ * 2;
                
                if (is(flags_, DDSD_LINEARSIZE)) {
                    if (pitchOrSize_ == 0) {
                        logger.warning("Must use linear size with fourcc");
                        pitchOrSize_ = size;
                    } else if (pitchOrSize_ != size) {
                        logger.warning("Expected size = " + size + ", real = " + pitchOrSize_);
                }
            } else {
                    pitchOrSize_ = size;
                }
            } else {
                compressed_ = false;

                // skip fourCC
                in_.readInt();

                bpp_ = in_.readInt();
                redMask_ = in_.readInt();
                greenMask_ = in_.readInt();
                blueMask_ = in_.readInt();
                alphaMask_ = in_.readInt();

                if (is(flags, DDPF_RGB)){
                    if (is(flags, DDPF_ALPHAPIXELS)){
                        pixelFormat_ = Format.RGBA8;
                    }else{
                        pixelFormat_ = Format.RGB8;
            }
                }else if (is(flags, DDPF_GRAYSCALE)){
                    switch (bpp_){
                        case 4:  pixelFormat_ = Format.Luminance4; break;
                        case 8:  pixelFormat_ = Format.Luminance8; break;
                        case 12: pixelFormat_ = Format.Luminance12; break;
                        case 16: pixelFormat_ = Format.Luminance16; break;
                        default: throw new IOException("Unsupported Grayscale BPP: "+bpp_);
        }
                    grayscaleOrAlpha_ = true;
                }else if (is(flags, DDPF_ALPHA)){
                    switch (bpp_){
                        case 4:  pixelFormat_ = Format.Alpha4; break;
                        case 8:  pixelFormat_ = Format.Alpha8; break;
                        case 12: pixelFormat_ = Format.Alpha12; break;
                        case 16: pixelFormat_ = Format.Alpha16; break;
                        default: throw new IOException("Unsupported Alpha BPP: "+bpp_);
                    }
                    grayscaleOrAlpha_ = true;
                }else{
                    throw new IOException("Unknown PixelFormat in DDS file");
                }

                int size = (bpp_ / 8 * width_);
                
                if (is(flags_, DDSD_LINEARSIZE)) {
                    if (pitchOrSize_ == 0) {
                        logger.warning("Linear size said to contain valid value but does not");
                        pitchOrSize_ = size;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -