|
@@ -1,842 +1,862 @@
|
|
|
-/*
|
|
|
|
|
- * 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;
|
|
|
|
|
-
|
|
|
|
|
-import com.jme3.export.*;
|
|
|
|
|
-import com.jme3.renderer.Caps;
|
|
|
|
|
-import com.jme3.renderer.Renderer;
|
|
|
|
|
-import com.jme3.util.NativeObject;
|
|
|
|
|
-import java.io.IOException;
|
|
|
|
|
-import java.nio.ByteBuffer;
|
|
|
|
|
-import java.util.ArrayList;
|
|
|
|
|
-import java.util.Arrays;
|
|
|
|
|
-import java.util.List;
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * <code>Image</code> defines a data format for a graphical image. The image
|
|
|
|
|
- * is defined by a format, a height and width, and the image data. The width and
|
|
|
|
|
- * height must be greater than 0. The data is contained in a byte buffer, and
|
|
|
|
|
- * should be packed before creation of the image object.
|
|
|
|
|
- *
|
|
|
|
|
- * @author Mark Powell
|
|
|
|
|
- * @author Joshua Slack
|
|
|
|
|
- * @version $Id: Image.java 4131 2009-03-19 20:15:28Z blaine.dev $
|
|
|
|
|
- */
|
|
|
|
|
-public class Image extends NativeObject implements Savable /*, Cloneable*/ {
|
|
|
|
|
-
|
|
|
|
|
- public enum Format {
|
|
|
|
|
- /**
|
|
|
|
|
- * 8-bit alpha
|
|
|
|
|
- */
|
|
|
|
|
- Alpha8(8),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 16-bit alpha
|
|
|
|
|
- */
|
|
|
|
|
- Alpha16(16),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 8-bit grayscale/luminance.
|
|
|
|
|
- */
|
|
|
|
|
- Luminance8(8),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 16-bit grayscale/luminance.
|
|
|
|
|
- */
|
|
|
|
|
- Luminance16(16),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * half-precision floating-point grayscale/luminance.
|
|
|
|
|
- */
|
|
|
|
|
- Luminance16F(16,true),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * single-precision floating-point grayscale/luminance.
|
|
|
|
|
- */
|
|
|
|
|
- Luminance32F(32,true),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 8-bit luminance/grayscale and 8-bit alpha.
|
|
|
|
|
- */
|
|
|
|
|
- Luminance8Alpha8(16),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 16-bit luminance/grayscale and 16-bit alpha.
|
|
|
|
|
- */
|
|
|
|
|
- Luminance16Alpha16(32),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * half-precision floating-point grayscale/luminance and alpha.
|
|
|
|
|
- */
|
|
|
|
|
- Luminance16FAlpha16F(32,true),
|
|
|
|
|
-
|
|
|
|
|
- @Deprecated
|
|
|
|
|
- Intensity8(8),
|
|
|
|
|
-
|
|
|
|
|
- @Deprecated
|
|
|
|
|
- Intensity16(16),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 8-bit blue, green, and red.
|
|
|
|
|
- */
|
|
|
|
|
- BGR8(24), // BGR and ABGR formats are often used on windows systems
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 8-bit red, green, and blue.
|
|
|
|
|
- */
|
|
|
|
|
- RGB8(24),
|
|
|
|
|
-
|
|
|
|
|
- @Deprecated
|
|
|
|
|
- RGB10(30),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 16-bit red, green, and blue.
|
|
|
|
|
- */
|
|
|
|
|
- RGB16(48),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 5-bit red, 6-bit green, and 5-bit blue.
|
|
|
|
|
- */
|
|
|
|
|
- RGB565(16),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 4-bit alpha, red, green, and blue. Used on Android only.
|
|
|
|
|
- */
|
|
|
|
|
- ARGB4444(16),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 5-bit red, green, and blue with 1-bit alpha.
|
|
|
|
|
- */
|
|
|
|
|
- RGB5A1(16),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 8-bit red, green, blue, and alpha.
|
|
|
|
|
- */
|
|
|
|
|
- RGBA8(32),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 8-bit alpha, blue, green, and red.
|
|
|
|
|
- */
|
|
|
|
|
- ABGR8(32),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 16-bit red, green, blue and alpha
|
|
|
|
|
- */
|
|
|
|
|
- RGBA16(64),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * S3TC compression DXT1.
|
|
|
|
|
- * Called BC1 in DirectX10.
|
|
|
|
|
- */
|
|
|
|
|
- DXT1(4,false,true, false),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * S3TC compression DXT1 with 1-bit alpha.
|
|
|
|
|
- */
|
|
|
|
|
- DXT1A(4,false,true, false),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * S3TC compression DXT3 with 4-bit alpha.
|
|
|
|
|
- * Called BC2 in DirectX10.
|
|
|
|
|
- */
|
|
|
|
|
- DXT3(8,false,true, false),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * S3TC compression DXT5 with interpolated 8-bit alpha.
|
|
|
|
|
- * Called BC3 in DirectX10.
|
|
|
|
|
- */
|
|
|
|
|
- DXT5(8,false,true, false),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Luminance-Alpha Texture Compression.
|
|
|
|
|
- * Called BC5 in DirectX10.
|
|
|
|
|
- */
|
|
|
|
|
- LATC(8, false, true, false),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Arbitrary depth format. The precision is chosen by the video
|
|
|
|
|
- * hardware.
|
|
|
|
|
- */
|
|
|
|
|
- Depth(0,true,false,false),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 16-bit depth.
|
|
|
|
|
- */
|
|
|
|
|
- Depth16(16,true,false,false),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 24-bit depth.
|
|
|
|
|
- */
|
|
|
|
|
- Depth24(24,true,false,false),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 32-bit depth.
|
|
|
|
|
- */
|
|
|
|
|
- Depth32(32,true,false,false),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * single-precision floating point depth.
|
|
|
|
|
- */
|
|
|
|
|
- Depth32F(32,true,false,true),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Texture data is stored as {@link Format#RGB16F} in system memory,
|
|
|
|
|
- * but will be converted to {@link Format#RGB111110F} when sent
|
|
|
|
|
- * to the video hardware.
|
|
|
|
|
- */
|
|
|
|
|
- RGB16F_to_RGB111110F(48,true),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * unsigned floating-point red, green and blue that uses 32 bits.
|
|
|
|
|
- */
|
|
|
|
|
- RGB111110F(32,true),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Texture data is stored as {@link Format#RGB16F} in system memory,
|
|
|
|
|
- * but will be converted to {@link Format#RGB9E5} when sent
|
|
|
|
|
- * to the video hardware.
|
|
|
|
|
- */
|
|
|
|
|
- RGB16F_to_RGB9E5(48,true),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 9-bit red, green and blue with 5-bit exponent.
|
|
|
|
|
- */
|
|
|
|
|
- RGB9E5(32,true),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * half-precision floating point red, green, and blue.
|
|
|
|
|
- */
|
|
|
|
|
- RGB16F(48,true),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * half-precision floating point red, green, blue, and alpha.
|
|
|
|
|
- */
|
|
|
|
|
- RGBA16F(64,true),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * single-precision floating point red, green, and blue.
|
|
|
|
|
- */
|
|
|
|
|
- RGB32F(96,true),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * single-precision floating point red, green, blue and alpha.
|
|
|
|
|
- */
|
|
|
|
|
- RGBA32F(128,true),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Luminance/grayscale texture compression.
|
|
|
|
|
- * Called BC4 in DirectX10.
|
|
|
|
|
- */
|
|
|
|
|
- LTC(4, false, true, false),
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 24-bit depth with 8-bit stencil.
|
|
|
|
|
- * Check the cap {@link Caps#PackedDepthStencilBuffer}.
|
|
|
|
|
- */
|
|
|
|
|
- Depth24Stencil8(32, true, false, false);
|
|
|
|
|
-
|
|
|
|
|
- private int bpp;
|
|
|
|
|
- private boolean isDepth;
|
|
|
|
|
- private boolean isCompressed;
|
|
|
|
|
- private boolean isFloatingPoint;
|
|
|
|
|
-
|
|
|
|
|
- private Format(int bpp){
|
|
|
|
|
- this.bpp = bpp;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private Format(int bpp, boolean isFP){
|
|
|
|
|
- this(bpp);
|
|
|
|
|
- this.isFloatingPoint = isFP;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private Format(int bpp, boolean isDepth, boolean isCompressed, boolean isFP){
|
|
|
|
|
- this(bpp, isFP);
|
|
|
|
|
- this.isDepth = isDepth;
|
|
|
|
|
- this.isCompressed = isCompressed;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * @return bits per pixel.
|
|
|
|
|
- */
|
|
|
|
|
- public int getBitsPerPixel(){
|
|
|
|
|
- return bpp;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * @return True if this format is a depth format, false otherwise.
|
|
|
|
|
- */
|
|
|
|
|
- public boolean isDepthFormat(){
|
|
|
|
|
- return isDepth;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * @return True if this is a compressed image format, false if
|
|
|
|
|
- * uncompressed.
|
|
|
|
|
- */
|
|
|
|
|
- public boolean isCompressed() {
|
|
|
|
|
- return isCompressed;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * @return True if this image format is in floating point,
|
|
|
|
|
- * false if it is an integer format.
|
|
|
|
|
- */
|
|
|
|
|
- public boolean isFloatingPont(){
|
|
|
|
|
- return isFloatingPoint;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // image attributes
|
|
|
|
|
- protected Format format;
|
|
|
|
|
- protected int width, height, depth;
|
|
|
|
|
- protected int[] mipMapSizes;
|
|
|
|
|
- protected ArrayList<ByteBuffer> data;
|
|
|
|
|
- protected transient Object efficientData;
|
|
|
|
|
- protected int multiSamples = 1;
|
|
|
|
|
-// protected int mipOffset = 0;
|
|
|
|
|
-
|
|
|
|
|
- // attributes relating to GL object
|
|
|
|
|
- protected boolean mipsWereGenerated = false;
|
|
|
|
|
- protected boolean needGeneratedMips = false;
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Internal use only.
|
|
|
|
|
- * The renderer marks which images have generated mipmaps in VRAM
|
|
|
|
|
- * and which do not, so it can generate them as needed.
|
|
|
|
|
- *
|
|
|
|
|
- * @param generated If mipmaps were generated or not.
|
|
|
|
|
- */
|
|
|
|
|
- public void setMipmapsGenerated(boolean generated) {
|
|
|
|
|
- this.mipsWereGenerated = generated;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Internal use only.
|
|
|
|
|
- * Check if the renderer has generated mipmaps for this image in VRAM
|
|
|
|
|
- * or not.
|
|
|
|
|
- *
|
|
|
|
|
- * @return If mipmaps were generated already.
|
|
|
|
|
- */
|
|
|
|
|
- public boolean isMipmapsGenerated() {
|
|
|
|
|
- return mipsWereGenerated;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * (Package private) Called by {@link Texture} when
|
|
|
|
|
- * {@link #isMipmapsGenerated() } is false in order to generate
|
|
|
|
|
- * mipmaps for this image.
|
|
|
|
|
- */
|
|
|
|
|
- void setNeedGeneratedMipmaps() {
|
|
|
|
|
- needGeneratedMips = true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * @return True if the image needs to have mipmaps generated
|
|
|
|
|
- * for it (as requested by the texture).
|
|
|
|
|
- */
|
|
|
|
|
- public boolean isGeneratedMipmapsRequired() {
|
|
|
|
|
- return needGeneratedMips;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void resetObject() {
|
|
|
|
|
- this.id = -1;
|
|
|
|
|
- this.mipsWereGenerated = false;
|
|
|
|
|
- setUpdateNeeded();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void deleteObject(Object rendererObject) {
|
|
|
|
|
- ((Renderer)rendererObject).deleteImage(this);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public NativeObject createDestructableClone() {
|
|
|
|
|
- return new Image(id);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * @return A shallow clone of this image. The data is not cloned.
|
|
|
|
|
- */
|
|
|
|
|
- @Override
|
|
|
|
|
- public Image clone(){
|
|
|
|
|
- Image clone = (Image) super.clone();
|
|
|
|
|
- clone.mipMapSizes = mipMapSizes != null ? mipMapSizes.clone() : null;
|
|
|
|
|
- clone.data = data != null ? new ArrayList<ByteBuffer>(data) : null;
|
|
|
|
|
- clone.setUpdateNeeded();
|
|
|
|
|
- return clone;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Constructor instantiates a new <code>Image</code> object. All values
|
|
|
|
|
- * are undefined.
|
|
|
|
|
- */
|
|
|
|
|
- public Image() {
|
|
|
|
|
- super(Image.class);
|
|
|
|
|
- data = new ArrayList<ByteBuffer>(1);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- protected Image(int id){
|
|
|
|
|
- super(Image.class, id);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Constructor instantiates a new <code>Image</code> object. The
|
|
|
|
|
- * attributes of the image are defined during construction.
|
|
|
|
|
- *
|
|
|
|
|
- * @param format
|
|
|
|
|
- * the data format of the image.
|
|
|
|
|
- * @param width
|
|
|
|
|
- * the width of the image.
|
|
|
|
|
- * @param height
|
|
|
|
|
- * the height of the image.
|
|
|
|
|
- * @param data
|
|
|
|
|
- * the image data.
|
|
|
|
|
- * @param mipMapSizes
|
|
|
|
|
- * the array of mipmap sizes, or null for no mipmaps.
|
|
|
|
|
- */
|
|
|
|
|
- public Image(Format format, int width, int height, int depth, ArrayList<ByteBuffer> data,
|
|
|
|
|
- int[] mipMapSizes) {
|
|
|
|
|
-
|
|
|
|
|
- this();
|
|
|
|
|
-
|
|
|
|
|
- if (mipMapSizes != null && mipMapSizes.length <= 1) {
|
|
|
|
|
- mipMapSizes = null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- setFormat(format);
|
|
|
|
|
- this.width = width;
|
|
|
|
|
- this.height = height;
|
|
|
|
|
- this.data = data;
|
|
|
|
|
- this.depth = depth;
|
|
|
|
|
- this.mipMapSizes = mipMapSizes;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Constructor instantiates a new <code>Image</code> object. The
|
|
|
|
|
- * attributes of the image are defined during construction.
|
|
|
|
|
- *
|
|
|
|
|
- * @param format
|
|
|
|
|
- * the data format of the image.
|
|
|
|
|
- * @param width
|
|
|
|
|
- * the width of the image.
|
|
|
|
|
- * @param height
|
|
|
|
|
- * the height of the image.
|
|
|
|
|
- * @param data
|
|
|
|
|
- * the image data.
|
|
|
|
|
- * @param mipMapSizes
|
|
|
|
|
- * the array of mipmap sizes, or null for no mipmaps.
|
|
|
|
|
- */
|
|
|
|
|
- public Image(Format format, int width, int height, ByteBuffer data,
|
|
|
|
|
- int[] mipMapSizes) {
|
|
|
|
|
-
|
|
|
|
|
- this();
|
|
|
|
|
-
|
|
|
|
|
- if (mipMapSizes != null && mipMapSizes.length <= 1) {
|
|
|
|
|
- mipMapSizes = null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- setFormat(format);
|
|
|
|
|
- this.width = width;
|
|
|
|
|
- this.height = height;
|
|
|
|
|
- if (data != null){
|
|
|
|
|
- this.data = new ArrayList<ByteBuffer>(1);
|
|
|
|
|
- this.data.add(data);
|
|
|
|
|
- }
|
|
|
|
|
- this.mipMapSizes = mipMapSizes;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Constructor instantiates a new <code>Image</code> object. The
|
|
|
|
|
- * attributes of the image are defined during construction.
|
|
|
|
|
- *
|
|
|
|
|
- * @param format
|
|
|
|
|
- * the data format of the image.
|
|
|
|
|
- * @param width
|
|
|
|
|
- * the width of the image.
|
|
|
|
|
- * @param height
|
|
|
|
|
- * the height of the image.
|
|
|
|
|
- * @param data
|
|
|
|
|
- * the image data.
|
|
|
|
|
- */
|
|
|
|
|
- public Image(Format format, int width, int height, int depth, ArrayList<ByteBuffer> data) {
|
|
|
|
|
- this(format, width, height, depth, data, null);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Constructor instantiates a new <code>Image</code> object. The
|
|
|
|
|
- * attributes of the image are defined during construction.
|
|
|
|
|
- *
|
|
|
|
|
- * @param format
|
|
|
|
|
- * the data format of the image.
|
|
|
|
|
- * @param width
|
|
|
|
|
- * the width of the image.
|
|
|
|
|
- * @param height
|
|
|
|
|
- * the height of the image.
|
|
|
|
|
- * @param data
|
|
|
|
|
- * the image data.
|
|
|
|
|
- */
|
|
|
|
|
- public Image(Format format, int width, int height, ByteBuffer data) {
|
|
|
|
|
- this(format, width, height, data, null);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * @return The number of samples (for multisampled textures).
|
|
|
|
|
- * @see Image#setMultiSamples(int)
|
|
|
|
|
- */
|
|
|
|
|
- public int getMultiSamples() {
|
|
|
|
|
- return multiSamples;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * @param multiSamples Set the number of samples to use for this image,
|
|
|
|
|
- * setting this to a value higher than 1 turns this image/texture
|
|
|
|
|
- * into a multisample texture (on OpenGL3.1 and higher).
|
|
|
|
|
- */
|
|
|
|
|
- public void setMultiSamples(int multiSamples) {
|
|
|
|
|
- if (multiSamples <= 0)
|
|
|
|
|
- throw new IllegalArgumentException("multiSamples must be > 0");
|
|
|
|
|
-
|
|
|
|
|
- if (getData(0) != null)
|
|
|
|
|
- throw new IllegalArgumentException("Cannot upload data as multisample texture");
|
|
|
|
|
-
|
|
|
|
|
- if (hasMipmaps())
|
|
|
|
|
- throw new IllegalArgumentException("Multisample textures do not support mipmaps");
|
|
|
|
|
-
|
|
|
|
|
- this.multiSamples = multiSamples;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <code>setData</code> sets the data that makes up the image. This data
|
|
|
|
|
- * is packed into an array of <code>ByteBuffer</code> objects.
|
|
|
|
|
- *
|
|
|
|
|
- * @param data
|
|
|
|
|
- * the data that contains the image information.
|
|
|
|
|
- */
|
|
|
|
|
- public void setData(ArrayList<ByteBuffer> data) {
|
|
|
|
|
- this.data = data;
|
|
|
|
|
- setUpdateNeeded();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <code>setData</code> sets the data that makes up the image. This data
|
|
|
|
|
- * is packed into a single <code>ByteBuffer</code>.
|
|
|
|
|
- *
|
|
|
|
|
- * @param data
|
|
|
|
|
- * the data that contains the image information.
|
|
|
|
|
- */
|
|
|
|
|
- public void setData(ByteBuffer data) {
|
|
|
|
|
- this.data = new ArrayList<ByteBuffer>(1);
|
|
|
|
|
- this.data.add(data);
|
|
|
|
|
- setUpdateNeeded();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public void addData(ByteBuffer data) {
|
|
|
|
|
- if (this.data == null)
|
|
|
|
|
- this.data = new ArrayList<ByteBuffer>(1);
|
|
|
|
|
- this.data.add(data);
|
|
|
|
|
- setUpdateNeeded();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public void setData(int index, ByteBuffer data) {
|
|
|
|
|
- if (index >= 0) {
|
|
|
|
|
- while (this.data.size() <= index) {
|
|
|
|
|
- this.data.add(null);
|
|
|
|
|
- }
|
|
|
|
|
- this.data.set(index, data);
|
|
|
|
|
- setUpdateNeeded();
|
|
|
|
|
- } else {
|
|
|
|
|
- throw new IllegalArgumentException("index must be greater than or equal to 0.");
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Set the efficient data representation of this image.
|
|
|
|
|
- * <p>
|
|
|
|
|
- * Some system implementations are more efficient at operating
|
|
|
|
|
- * on data other than ByteBuffers, in that case, this method can be used.
|
|
|
|
|
- *
|
|
|
|
|
- * @param efficientData
|
|
|
|
|
- */
|
|
|
|
|
- public void setEfficentData(Object efficientData){
|
|
|
|
|
- this.efficientData = efficientData;
|
|
|
|
|
- setUpdateNeeded();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * @return The efficient data representation of this image.
|
|
|
|
|
- * @see Image#setEfficentData(java.lang.Object)
|
|
|
|
|
- */
|
|
|
|
|
- public Object getEfficentData(){
|
|
|
|
|
- return efficientData;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Sets the mipmap sizes stored in this image's data buffer. Mipmaps are
|
|
|
|
|
- * stored sequentially, and the first mipmap is the main image data. To
|
|
|
|
|
- * specify no mipmaps, pass null and this will automatically be expanded
|
|
|
|
|
- * into a single mipmap of the full
|
|
|
|
|
- *
|
|
|
|
|
- * @param mipMapSizes
|
|
|
|
|
- * the mipmap sizes array, or null for a single image map.
|
|
|
|
|
- */
|
|
|
|
|
- public void setMipMapSizes(int[] mipMapSizes) {
|
|
|
|
|
- if (mipMapSizes != null && mipMapSizes.length <= 1)
|
|
|
|
|
- mipMapSizes = null;
|
|
|
|
|
-
|
|
|
|
|
- this.mipMapSizes = mipMapSizes;
|
|
|
|
|
- setUpdateNeeded();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <code>setHeight</code> sets the height value of the image. It is
|
|
|
|
|
- * typically a good idea to try to keep this as a multiple of 2.
|
|
|
|
|
- *
|
|
|
|
|
- * @param height
|
|
|
|
|
- * the height of the image.
|
|
|
|
|
- */
|
|
|
|
|
- public void setHeight(int height) {
|
|
|
|
|
- this.height = height;
|
|
|
|
|
- setUpdateNeeded();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <code>setDepth</code> sets the depth value of the image. It is
|
|
|
|
|
- * typically a good idea to try to keep this as a multiple of 2. This is
|
|
|
|
|
- * used for 3d images.
|
|
|
|
|
- *
|
|
|
|
|
- * @param depth
|
|
|
|
|
- * the depth of the image.
|
|
|
|
|
- */
|
|
|
|
|
- public void setDepth(int depth) {
|
|
|
|
|
- this.depth = depth;
|
|
|
|
|
- setUpdateNeeded();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <code>setWidth</code> sets the width value of the image. It is
|
|
|
|
|
- * typically a good idea to try to keep this as a multiple of 2.
|
|
|
|
|
- *
|
|
|
|
|
- * @param width
|
|
|
|
|
- * the width of the image.
|
|
|
|
|
- */
|
|
|
|
|
- public void setWidth(int width) {
|
|
|
|
|
- this.width = width;
|
|
|
|
|
- setUpdateNeeded();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <code>setFormat</code> sets the image format for this image.
|
|
|
|
|
- *
|
|
|
|
|
- * @param format
|
|
|
|
|
- * the image format.
|
|
|
|
|
- * @throws NullPointerException
|
|
|
|
|
- * if format is null
|
|
|
|
|
- * @see Format
|
|
|
|
|
- */
|
|
|
|
|
- public void setFormat(Format format) {
|
|
|
|
|
- if (format == null) {
|
|
|
|
|
- throw new NullPointerException("format may not be null.");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- this.format = format;
|
|
|
|
|
- setUpdateNeeded();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <code>getFormat</code> returns the image format for this image.
|
|
|
|
|
- *
|
|
|
|
|
- * @return the image format.
|
|
|
|
|
- * @see Format
|
|
|
|
|
- */
|
|
|
|
|
- public Format getFormat() {
|
|
|
|
|
- return format;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <code>getWidth</code> returns the width of this image.
|
|
|
|
|
- *
|
|
|
|
|
- * @return the width of this image.
|
|
|
|
|
- */
|
|
|
|
|
- public int getWidth() {
|
|
|
|
|
- return width;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <code>getHeight</code> returns the height of this image.
|
|
|
|
|
- *
|
|
|
|
|
- * @return the height of this image.
|
|
|
|
|
- */
|
|
|
|
|
- public int getHeight() {
|
|
|
|
|
- return height;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <code>getDepth</code> returns the depth of this image (for 3d images).
|
|
|
|
|
- *
|
|
|
|
|
- * @return the depth of this image.
|
|
|
|
|
- */
|
|
|
|
|
- public int getDepth() {
|
|
|
|
|
- return depth;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <code>getData</code> returns the data for this image. If the data is
|
|
|
|
|
- * undefined, null will be returned.
|
|
|
|
|
- *
|
|
|
|
|
- * @return the data for this image.
|
|
|
|
|
- */
|
|
|
|
|
- public List<ByteBuffer> getData() {
|
|
|
|
|
- return data;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <code>getData</code> returns the data for this image. If the data is
|
|
|
|
|
- * undefined, null will be returned.
|
|
|
|
|
- *
|
|
|
|
|
- * @return the data for this image.
|
|
|
|
|
- */
|
|
|
|
|
- public ByteBuffer getData(int index) {
|
|
|
|
|
- if (data.size() > index)
|
|
|
|
|
- return data.get(index);
|
|
|
|
|
- else
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Returns whether the image data contains mipmaps.
|
|
|
|
|
- *
|
|
|
|
|
- * @return true if the image data contains mipmaps, false if not.
|
|
|
|
|
- */
|
|
|
|
|
- public boolean hasMipmaps() {
|
|
|
|
|
- return mipMapSizes != null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Returns the mipmap sizes for this image.
|
|
|
|
|
- *
|
|
|
|
|
- * @return the mipmap sizes for this image.
|
|
|
|
|
- */
|
|
|
|
|
- public int[] getMipMapSizes() {
|
|
|
|
|
- return mipMapSizes;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public String toString(){
|
|
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
|
|
- sb.append(getClass().getSimpleName());
|
|
|
|
|
- sb.append("[size=").append(width).append("x").append(height);
|
|
|
|
|
-
|
|
|
|
|
- if (depth > 1)
|
|
|
|
|
- sb.append("x").append(depth);
|
|
|
|
|
-
|
|
|
|
|
- sb.append(", format=").append(format.name());
|
|
|
|
|
-
|
|
|
|
|
- if (hasMipmaps())
|
|
|
|
|
- sb.append(", mips");
|
|
|
|
|
-
|
|
|
|
|
- if (getId() >= 0)
|
|
|
|
|
- sb.append(", id=").append(id);
|
|
|
|
|
-
|
|
|
|
|
- sb.append("]");
|
|
|
|
|
-
|
|
|
|
|
- return sb.toString();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public boolean equals(Object other) {
|
|
|
|
|
- if (other == this) {
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- if (!(other instanceof Image)) {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- Image that = (Image) other;
|
|
|
|
|
- if (this.getFormat() != that.getFormat())
|
|
|
|
|
- return false;
|
|
|
|
|
- if (this.getWidth() != that.getWidth())
|
|
|
|
|
- return false;
|
|
|
|
|
- if (this.getHeight() != that.getHeight())
|
|
|
|
|
- return false;
|
|
|
|
|
- if (this.getData() != null && !this.getData().equals(that.getData()))
|
|
|
|
|
- return false;
|
|
|
|
|
- if (this.getData() == null && that.getData() != null)
|
|
|
|
|
- return false;
|
|
|
|
|
- if (this.getMipMapSizes() != null
|
|
|
|
|
- && !Arrays.equals(this.getMipMapSizes(), that.getMipMapSizes()))
|
|
|
|
|
- return false;
|
|
|
|
|
- if (this.getMipMapSizes() == null && that.getMipMapSizes() != null)
|
|
|
|
|
- return false;
|
|
|
|
|
- if (this.getMultiSamples() != that.getMultiSamples())
|
|
|
|
|
- return false;
|
|
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int hashCode() {
|
|
|
|
|
- int hash = 7;
|
|
|
|
|
- hash = 97 * hash + (this.format != null ? this.format.hashCode() : 0);
|
|
|
|
|
- hash = 97 * hash + this.width;
|
|
|
|
|
- hash = 97 * hash + this.height;
|
|
|
|
|
- hash = 97 * hash + this.depth;
|
|
|
|
|
- hash = 97 * hash + Arrays.hashCode(this.mipMapSizes);
|
|
|
|
|
- hash = 97 * hash + (this.data != null ? this.data.hashCode() : 0);
|
|
|
|
|
- hash = 97 * hash + this.multiSamples;
|
|
|
|
|
- return hash;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public void write(JmeExporter e) throws IOException {
|
|
|
|
|
- OutputCapsule capsule = e.getCapsule(this);
|
|
|
|
|
- capsule.write(format, "format", Format.RGBA8);
|
|
|
|
|
- capsule.write(width, "width", 0);
|
|
|
|
|
- capsule.write(height, "height", 0);
|
|
|
|
|
- capsule.write(depth, "depth", 0);
|
|
|
|
|
- capsule.write(mipMapSizes, "mipMapSizes", null);
|
|
|
|
|
- capsule.write(multiSamples, "multiSamples", 1);
|
|
|
|
|
- capsule.writeByteBufferArrayList(data, "data", null);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public void read(JmeImporter e) throws IOException {
|
|
|
|
|
- InputCapsule capsule = e.getCapsule(this);
|
|
|
|
|
- format = capsule.readEnum("format", Format.class, Format.RGBA8);
|
|
|
|
|
- width = capsule.readInt("width", 0);
|
|
|
|
|
- height = capsule.readInt("height", 0);
|
|
|
|
|
- depth = capsule.readInt("depth", 0);
|
|
|
|
|
- mipMapSizes = capsule.readIntArray("mipMapSizes", null);
|
|
|
|
|
- multiSamples = capsule.readInt("multiSamples", 1);
|
|
|
|
|
- data = (ArrayList<ByteBuffer>) capsule.readByteBufferArrayList("data", null);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-}
|
|
|
|
|
|
|
+/*
|
|
|
|
|
+ * 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;
|
|
|
|
|
+
|
|
|
|
|
+import com.jme3.export.*;
|
|
|
|
|
+import com.jme3.renderer.Caps;
|
|
|
|
|
+import com.jme3.renderer.Renderer;
|
|
|
|
|
+import com.jme3.util.NativeObject;
|
|
|
|
|
+import java.io.IOException;
|
|
|
|
|
+import java.nio.ByteBuffer;
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.Arrays;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * <code>Image</code> defines a data format for a graphical image. The image
|
|
|
|
|
+ * is defined by a format, a height and width, and the image data. The width and
|
|
|
|
|
+ * height must be greater than 0. The data is contained in a byte buffer, and
|
|
|
|
|
+ * should be packed before creation of the image object.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @author Mark Powell
|
|
|
|
|
+ * @author Joshua Slack
|
|
|
|
|
+ * @version $Id: Image.java 4131 2009-03-19 20:15:28Z blaine.dev $
|
|
|
|
|
+ */
|
|
|
|
|
+public class Image extends NativeObject implements Savable /*, Cloneable*/ {
|
|
|
|
|
+
|
|
|
|
|
+ public enum Format {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 8-bit alpha
|
|
|
|
|
+ */
|
|
|
|
|
+ Alpha8(8),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 16-bit alpha
|
|
|
|
|
+ */
|
|
|
|
|
+ Alpha16(16),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 8-bit grayscale/luminance.
|
|
|
|
|
+ */
|
|
|
|
|
+ Luminance8(8),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 16-bit grayscale/luminance.
|
|
|
|
|
+ */
|
|
|
|
|
+ Luminance16(16),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * half-precision floating-point grayscale/luminance.
|
|
|
|
|
+ */
|
|
|
|
|
+ Luminance16F(16,true),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * single-precision floating-point grayscale/luminance.
|
|
|
|
|
+ */
|
|
|
|
|
+ Luminance32F(32,true),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 8-bit luminance/grayscale and 8-bit alpha.
|
|
|
|
|
+ */
|
|
|
|
|
+ Luminance8Alpha8(16),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 16-bit luminance/grayscale and 16-bit alpha.
|
|
|
|
|
+ */
|
|
|
|
|
+ Luminance16Alpha16(32),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * half-precision floating-point grayscale/luminance and alpha.
|
|
|
|
|
+ */
|
|
|
|
|
+ Luminance16FAlpha16F(32,true),
|
|
|
|
|
+
|
|
|
|
|
+ @Deprecated
|
|
|
|
|
+ Intensity8(8),
|
|
|
|
|
+
|
|
|
|
|
+ @Deprecated
|
|
|
|
|
+ Intensity16(16),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 8-bit blue, green, and red.
|
|
|
|
|
+ */
|
|
|
|
|
+ BGR8(24), // BGR and ABGR formats are often used on windows systems
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 8-bit red, green, and blue.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGB8(24),
|
|
|
|
|
+
|
|
|
|
|
+ @Deprecated
|
|
|
|
|
+ RGB10(30),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 16-bit red, green, and blue.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGB16(48),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 5-bit red, 6-bit green, and 5-bit blue.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGB565(16),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 4-bit alpha, red, green, and blue. Used on Android only.
|
|
|
|
|
+ */
|
|
|
|
|
+ ARGB4444(16),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 5-bit red, green, and blue with 1-bit alpha.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGB5A1(16),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 8-bit red, green, blue, and alpha.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGBA8(32),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 8-bit alpha, blue, green, and red.
|
|
|
|
|
+ */
|
|
|
|
|
+ ABGR8(32),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 16-bit red, green, blue and alpha
|
|
|
|
|
+ */
|
|
|
|
|
+ RGBA16(64),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * S3TC compression DXT1.
|
|
|
|
|
+ * Called BC1 in DirectX10.
|
|
|
|
|
+ */
|
|
|
|
|
+ DXT1(4,false,true, false),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * S3TC compression DXT1 with 1-bit alpha.
|
|
|
|
|
+ */
|
|
|
|
|
+ DXT1A(4,false,true, false),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * S3TC compression DXT3 with 4-bit alpha.
|
|
|
|
|
+ * Called BC2 in DirectX10.
|
|
|
|
|
+ */
|
|
|
|
|
+ DXT3(8,false,true, false),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * S3TC compression DXT5 with interpolated 8-bit alpha.
|
|
|
|
|
+ * Called BC3 in DirectX10.
|
|
|
|
|
+ */
|
|
|
|
|
+ DXT5(8,false,true, false),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Luminance-Alpha Texture Compression.
|
|
|
|
|
+ * Called BC5 in DirectX10.
|
|
|
|
|
+ */
|
|
|
|
|
+ LATC(8, false, true, false),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Arbitrary depth format. The precision is chosen by the video
|
|
|
|
|
+ * hardware.
|
|
|
|
|
+ */
|
|
|
|
|
+ Depth(0,true,false,false),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 16-bit depth.
|
|
|
|
|
+ */
|
|
|
|
|
+ Depth16(16,true,false,false),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 24-bit depth.
|
|
|
|
|
+ */
|
|
|
|
|
+ Depth24(24,true,false,false),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 32-bit depth.
|
|
|
|
|
+ */
|
|
|
|
|
+ Depth32(32,true,false,false),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * single-precision floating point depth.
|
|
|
|
|
+ */
|
|
|
|
|
+ Depth32F(32,true,false,true),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Texture data is stored as {@link Format#RGB16F} in system memory,
|
|
|
|
|
+ * but will be converted to {@link Format#RGB111110F} when sent
|
|
|
|
|
+ * to the video hardware.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGB16F_to_RGB111110F(48,true),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * unsigned floating-point red, green and blue that uses 32 bits.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGB111110F(32,true),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Texture data is stored as {@link Format#RGB16F} in system memory,
|
|
|
|
|
+ * but will be converted to {@link Format#RGB9E5} when sent
|
|
|
|
|
+ * to the video hardware.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGB16F_to_RGB9E5(48,true),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 9-bit red, green and blue with 5-bit exponent.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGB9E5(32,true),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * half-precision floating point red, green, and blue.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGB16F(48,true),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * half-precision floating point red, green, blue, and alpha.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGBA16F(64,true),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * single-precision floating point red, green, and blue.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGB32F(96,true),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * single-precision floating point red, green, blue and alpha.
|
|
|
|
|
+ */
|
|
|
|
|
+ RGBA32F(128,true),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Luminance/grayscale texture compression.
|
|
|
|
|
+ * Called BC4 in DirectX10.
|
|
|
|
|
+ */
|
|
|
|
|
+ LTC(4, false, true, false),
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 24-bit depth with 8-bit stencil.
|
|
|
|
|
+ * Check the cap {@link Caps#PackedDepthStencilBuffer}.
|
|
|
|
|
+ */
|
|
|
|
|
+ Depth24Stencil8(32, true, false, false);
|
|
|
|
|
+
|
|
|
|
|
+ private int bpp;
|
|
|
|
|
+ private boolean isDepth;
|
|
|
|
|
+ private boolean isCompressed;
|
|
|
|
|
+ private boolean isFloatingPoint;
|
|
|
|
|
+
|
|
|
|
|
+ private Format(int bpp){
|
|
|
|
|
+ this.bpp = bpp;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Format(int bpp, boolean isFP){
|
|
|
|
|
+ this(bpp);
|
|
|
|
|
+ this.isFloatingPoint = isFP;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Format(int bpp, boolean isDepth, boolean isCompressed, boolean isFP){
|
|
|
|
|
+ this(bpp, isFP);
|
|
|
|
|
+ this.isDepth = isDepth;
|
|
|
|
|
+ this.isCompressed = isCompressed;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @return bits per pixel.
|
|
|
|
|
+ */
|
|
|
|
|
+ public int getBitsPerPixel(){
|
|
|
|
|
+ return bpp;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @return True if this format is a depth format, false otherwise.
|
|
|
|
|
+ */
|
|
|
|
|
+ public boolean isDepthFormat(){
|
|
|
|
|
+ return isDepth;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @return True if this is a compressed image format, false if
|
|
|
|
|
+ * uncompressed.
|
|
|
|
|
+ */
|
|
|
|
|
+ public boolean isCompressed() {
|
|
|
|
|
+ return isCompressed;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @return True if this image format is in floating point,
|
|
|
|
|
+ * false if it is an integer format.
|
|
|
|
|
+ */
|
|
|
|
|
+ public boolean isFloatingPont(){
|
|
|
|
|
+ return isFloatingPoint;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // image attributes
|
|
|
|
|
+ protected Format format;
|
|
|
|
|
+ protected int width, height, depth;
|
|
|
|
|
+ protected int[] mipMapSizes;
|
|
|
|
|
+ protected ArrayList<ByteBuffer> data;
|
|
|
|
|
+ protected transient Object efficientData;
|
|
|
|
|
+ protected int multiSamples = 1;
|
|
|
|
|
+// protected int mipOffset = 0;
|
|
|
|
|
+
|
|
|
|
|
+ // attributes relating to GL object
|
|
|
|
|
+ protected boolean mipsWereGenerated = false;
|
|
|
|
|
+ protected boolean needGeneratedMips = false;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Internal use only.
|
|
|
|
|
+ * The renderer marks which images have generated mipmaps in VRAM
|
|
|
|
|
+ * and which do not, so it can generate them as needed.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param generated If mipmaps were generated or not.
|
|
|
|
|
+ */
|
|
|
|
|
+ public void setMipmapsGenerated(boolean generated) {
|
|
|
|
|
+ this.mipsWereGenerated = generated;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Internal use only.
|
|
|
|
|
+ * Check if the renderer has generated mipmaps for this image in VRAM
|
|
|
|
|
+ * or not.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return If mipmaps were generated already.
|
|
|
|
|
+ */
|
|
|
|
|
+ public boolean isMipmapsGenerated() {
|
|
|
|
|
+ return mipsWereGenerated;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * (Package private) Called by {@link Texture} when
|
|
|
|
|
+ * {@link #isMipmapsGenerated() } is false in order to generate
|
|
|
|
|
+ * mipmaps for this image.
|
|
|
|
|
+ */
|
|
|
|
|
+ void setNeedGeneratedMipmaps() {
|
|
|
|
|
+ needGeneratedMips = true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @return True if the image needs to have mipmaps generated
|
|
|
|
|
+ * for it (as requested by the texture).
|
|
|
|
|
+ */
|
|
|
|
|
+ public boolean isGeneratedMipmapsRequired() {
|
|
|
|
|
+ return needGeneratedMips;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void resetObject() {
|
|
|
|
|
+ this.id = -1;
|
|
|
|
|
+ this.mipsWereGenerated = false;
|
|
|
|
|
+ setUpdateNeeded();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void deleteObject(Object rendererObject) {
|
|
|
|
|
+ ((Renderer)rendererObject).deleteImage(this);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public NativeObject createDestructableClone() {
|
|
|
|
|
+ return new Image(id);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @return A shallow clone of this image. The data is not cloned.
|
|
|
|
|
+ */
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public Image clone(){
|
|
|
|
|
+ Image clone = (Image) super.clone();
|
|
|
|
|
+ clone.mipMapSizes = mipMapSizes != null ? mipMapSizes.clone() : null;
|
|
|
|
|
+ clone.data = data != null ? new ArrayList<ByteBuffer>(data) : null;
|
|
|
|
|
+ clone.setUpdateNeeded();
|
|
|
|
|
+ return clone;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Constructor instantiates a new <code>Image</code> object. All values
|
|
|
|
|
+ * are undefined.
|
|
|
|
|
+ */
|
|
|
|
|
+ public Image() {
|
|
|
|
|
+ super(Image.class);
|
|
|
|
|
+ data = new ArrayList<ByteBuffer>(1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ protected Image(int id){
|
|
|
|
|
+ super(Image.class, id);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Constructor instantiates a new <code>Image</code> object. The
|
|
|
|
|
+ * attributes of the image are defined during construction.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param format
|
|
|
|
|
+ * the data format of the image.
|
|
|
|
|
+ * @param width
|
|
|
|
|
+ * the width of the image.
|
|
|
|
|
+ * @param height
|
|
|
|
|
+ * the height of the image.
|
|
|
|
|
+ * @param data
|
|
|
|
|
+ * the image data.
|
|
|
|
|
+ * @param mipMapSizes
|
|
|
|
|
+ * the array of mipmap sizes, or null for no mipmaps.
|
|
|
|
|
+ */
|
|
|
|
|
+ public Image(Format format, int width, int height, int depth, ArrayList<ByteBuffer> data,
|
|
|
|
|
+ int[] mipMapSizes) {
|
|
|
|
|
+
|
|
|
|
|
+ this();
|
|
|
|
|
+
|
|
|
|
|
+ if (mipMapSizes != null && mipMapSizes.length <= 1) {
|
|
|
|
|
+ mipMapSizes = null;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ needGeneratedMips = false;
|
|
|
|
|
+ mipsWereGenerated = true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setFormat(format);
|
|
|
|
|
+ this.width = width;
|
|
|
|
|
+ this.height = height;
|
|
|
|
|
+ this.data = data;
|
|
|
|
|
+ this.depth = depth;
|
|
|
|
|
+ this.mipMapSizes = mipMapSizes;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Constructor instantiates a new <code>Image</code> object. The
|
|
|
|
|
+ * attributes of the image are defined during construction.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param format
|
|
|
|
|
+ * the data format of the image.
|
|
|
|
|
+ * @param width
|
|
|
|
|
+ * the width of the image.
|
|
|
|
|
+ * @param height
|
|
|
|
|
+ * the height of the image.
|
|
|
|
|
+ * @param data
|
|
|
|
|
+ * the image data.
|
|
|
|
|
+ * @param mipMapSizes
|
|
|
|
|
+ * the array of mipmap sizes, or null for no mipmaps.
|
|
|
|
|
+ */
|
|
|
|
|
+ public Image(Format format, int width, int height, ByteBuffer data,
|
|
|
|
|
+ int[] mipMapSizes) {
|
|
|
|
|
+
|
|
|
|
|
+ this();
|
|
|
|
|
+
|
|
|
|
|
+ if (mipMapSizes != null && mipMapSizes.length <= 1) {
|
|
|
|
|
+ mipMapSizes = null;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ needGeneratedMips = false;
|
|
|
|
|
+ mipsWereGenerated = true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setFormat(format);
|
|
|
|
|
+ this.width = width;
|
|
|
|
|
+ this.height = height;
|
|
|
|
|
+ if (data != null){
|
|
|
|
|
+ this.data = new ArrayList<ByteBuffer>(1);
|
|
|
|
|
+ this.data.add(data);
|
|
|
|
|
+ }
|
|
|
|
|
+ this.mipMapSizes = mipMapSizes;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Constructor instantiates a new <code>Image</code> object. The
|
|
|
|
|
+ * attributes of the image are defined during construction.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param format
|
|
|
|
|
+ * the data format of the image.
|
|
|
|
|
+ * @param width
|
|
|
|
|
+ * the width of the image.
|
|
|
|
|
+ * @param height
|
|
|
|
|
+ * the height of the image.
|
|
|
|
|
+ * @param data
|
|
|
|
|
+ * the image data.
|
|
|
|
|
+ */
|
|
|
|
|
+ public Image(Format format, int width, int height, int depth, ArrayList<ByteBuffer> data) {
|
|
|
|
|
+ this(format, width, height, depth, data, null);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Constructor instantiates a new <code>Image</code> object. The
|
|
|
|
|
+ * attributes of the image are defined during construction.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param format
|
|
|
|
|
+ * the data format of the image.
|
|
|
|
|
+ * @param width
|
|
|
|
|
+ * the width of the image.
|
|
|
|
|
+ * @param height
|
|
|
|
|
+ * the height of the image.
|
|
|
|
|
+ * @param data
|
|
|
|
|
+ * the image data.
|
|
|
|
|
+ */
|
|
|
|
|
+ public Image(Format format, int width, int height, ByteBuffer data) {
|
|
|
|
|
+ this(format, width, height, data, null);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @return The number of samples (for multisampled textures).
|
|
|
|
|
+ * @see Image#setMultiSamples(int)
|
|
|
|
|
+ */
|
|
|
|
|
+ public int getMultiSamples() {
|
|
|
|
|
+ return multiSamples;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param multiSamples Set the number of samples to use for this image,
|
|
|
|
|
+ * setting this to a value higher than 1 turns this image/texture
|
|
|
|
|
+ * into a multisample texture (on OpenGL3.1 and higher).
|
|
|
|
|
+ */
|
|
|
|
|
+ public void setMultiSamples(int multiSamples) {
|
|
|
|
|
+ if (multiSamples <= 0)
|
|
|
|
|
+ throw new IllegalArgumentException("multiSamples must be > 0");
|
|
|
|
|
+
|
|
|
|
|
+ if (getData(0) != null)
|
|
|
|
|
+ throw new IllegalArgumentException("Cannot upload data as multisample texture");
|
|
|
|
|
+
|
|
|
|
|
+ if (hasMipmaps())
|
|
|
|
|
+ throw new IllegalArgumentException("Multisample textures do not support mipmaps");
|
|
|
|
|
+
|
|
|
|
|
+ this.multiSamples = multiSamples;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <code>setData</code> sets the data that makes up the image. This data
|
|
|
|
|
+ * is packed into an array of <code>ByteBuffer</code> objects.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param data
|
|
|
|
|
+ * the data that contains the image information.
|
|
|
|
|
+ */
|
|
|
|
|
+ public void setData(ArrayList<ByteBuffer> data) {
|
|
|
|
|
+ this.data = data;
|
|
|
|
|
+ setUpdateNeeded();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <code>setData</code> sets the data that makes up the image. This data
|
|
|
|
|
+ * is packed into a single <code>ByteBuffer</code>.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param data
|
|
|
|
|
+ * the data that contains the image information.
|
|
|
|
|
+ */
|
|
|
|
|
+ public void setData(ByteBuffer data) {
|
|
|
|
|
+ this.data = new ArrayList<ByteBuffer>(1);
|
|
|
|
|
+ this.data.add(data);
|
|
|
|
|
+ setUpdateNeeded();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void addData(ByteBuffer data) {
|
|
|
|
|
+ if (this.data == null)
|
|
|
|
|
+ this.data = new ArrayList<ByteBuffer>(1);
|
|
|
|
|
+ this.data.add(data);
|
|
|
|
|
+ setUpdateNeeded();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void setData(int index, ByteBuffer data) {
|
|
|
|
|
+ if (index >= 0) {
|
|
|
|
|
+ while (this.data.size() <= index) {
|
|
|
|
|
+ this.data.add(null);
|
|
|
|
|
+ }
|
|
|
|
|
+ this.data.set(index, data);
|
|
|
|
|
+ setUpdateNeeded();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ throw new IllegalArgumentException("index must be greater than or equal to 0.");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Set the efficient data representation of this image.
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * Some system implementations are more efficient at operating
|
|
|
|
|
+ * on data other than ByteBuffers, in that case, this method can be used.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param efficientData
|
|
|
|
|
+ */
|
|
|
|
|
+ public void setEfficentData(Object efficientData){
|
|
|
|
|
+ this.efficientData = efficientData;
|
|
|
|
|
+ setUpdateNeeded();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @return The efficient data representation of this image.
|
|
|
|
|
+ * @see Image#setEfficentData(java.lang.Object)
|
|
|
|
|
+ */
|
|
|
|
|
+ public Object getEfficentData(){
|
|
|
|
|
+ return efficientData;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Sets the mipmap sizes stored in this image's data buffer. Mipmaps are
|
|
|
|
|
+ * stored sequentially, and the first mipmap is the main image data. To
|
|
|
|
|
+ * specify no mipmaps, pass null and this will automatically be expanded
|
|
|
|
|
+ * into a single mipmap of the full
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param mipMapSizes
|
|
|
|
|
+ * the mipmap sizes array, or null for a single image map.
|
|
|
|
|
+ */
|
|
|
|
|
+ public void setMipMapSizes(int[] mipMapSizes) {
|
|
|
|
|
+ if (mipMapSizes != null && mipMapSizes.length <= 1)
|
|
|
|
|
+ mipMapSizes = null;
|
|
|
|
|
+
|
|
|
|
|
+ this.mipMapSizes = mipMapSizes;
|
|
|
|
|
+
|
|
|
|
|
+ if (mipMapSizes != null) {
|
|
|
|
|
+ needGeneratedMips = false;
|
|
|
|
|
+ mipsWereGenerated = false;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ needGeneratedMips = false;
|
|
|
|
|
+ mipsWereGenerated = true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setUpdateNeeded();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <code>setHeight</code> sets the height value of the image. It is
|
|
|
|
|
+ * typically a good idea to try to keep this as a multiple of 2.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param height
|
|
|
|
|
+ * the height of the image.
|
|
|
|
|
+ */
|
|
|
|
|
+ public void setHeight(int height) {
|
|
|
|
|
+ this.height = height;
|
|
|
|
|
+ setUpdateNeeded();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <code>setDepth</code> sets the depth value of the image. It is
|
|
|
|
|
+ * typically a good idea to try to keep this as a multiple of 2. This is
|
|
|
|
|
+ * used for 3d images.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param depth
|
|
|
|
|
+ * the depth of the image.
|
|
|
|
|
+ */
|
|
|
|
|
+ public void setDepth(int depth) {
|
|
|
|
|
+ this.depth = depth;
|
|
|
|
|
+ setUpdateNeeded();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <code>setWidth</code> sets the width value of the image. It is
|
|
|
|
|
+ * typically a good idea to try to keep this as a multiple of 2.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param width
|
|
|
|
|
+ * the width of the image.
|
|
|
|
|
+ */
|
|
|
|
|
+ public void setWidth(int width) {
|
|
|
|
|
+ this.width = width;
|
|
|
|
|
+ setUpdateNeeded();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <code>setFormat</code> sets the image format for this image.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param format
|
|
|
|
|
+ * the image format.
|
|
|
|
|
+ * @throws NullPointerException
|
|
|
|
|
+ * if format is null
|
|
|
|
|
+ * @see Format
|
|
|
|
|
+ */
|
|
|
|
|
+ public void setFormat(Format format) {
|
|
|
|
|
+ if (format == null) {
|
|
|
|
|
+ throw new NullPointerException("format may not be null.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.format = format;
|
|
|
|
|
+ setUpdateNeeded();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <code>getFormat</code> returns the image format for this image.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return the image format.
|
|
|
|
|
+ * @see Format
|
|
|
|
|
+ */
|
|
|
|
|
+ public Format getFormat() {
|
|
|
|
|
+ return format;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <code>getWidth</code> returns the width of this image.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return the width of this image.
|
|
|
|
|
+ */
|
|
|
|
|
+ public int getWidth() {
|
|
|
|
|
+ return width;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <code>getHeight</code> returns the height of this image.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return the height of this image.
|
|
|
|
|
+ */
|
|
|
|
|
+ public int getHeight() {
|
|
|
|
|
+ return height;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <code>getDepth</code> returns the depth of this image (for 3d images).
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return the depth of this image.
|
|
|
|
|
+ */
|
|
|
|
|
+ public int getDepth() {
|
|
|
|
|
+ return depth;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <code>getData</code> returns the data for this image. If the data is
|
|
|
|
|
+ * undefined, null will be returned.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return the data for this image.
|
|
|
|
|
+ */
|
|
|
|
|
+ public List<ByteBuffer> getData() {
|
|
|
|
|
+ return data;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <code>getData</code> returns the data for this image. If the data is
|
|
|
|
|
+ * undefined, null will be returned.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return the data for this image.
|
|
|
|
|
+ */
|
|
|
|
|
+ public ByteBuffer getData(int index) {
|
|
|
|
|
+ if (data.size() > index)
|
|
|
|
|
+ return data.get(index);
|
|
|
|
|
+ else
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Returns whether the image data contains mipmaps.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return true if the image data contains mipmaps, false if not.
|
|
|
|
|
+ */
|
|
|
|
|
+ public boolean hasMipmaps() {
|
|
|
|
|
+ return mipMapSizes != null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Returns the mipmap sizes for this image.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return the mipmap sizes for this image.
|
|
|
|
|
+ */
|
|
|
|
|
+ public int[] getMipMapSizes() {
|
|
|
|
|
+ return mipMapSizes;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public String toString(){
|
|
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
|
|
+ sb.append(getClass().getSimpleName());
|
|
|
|
|
+ sb.append("[size=").append(width).append("x").append(height);
|
|
|
|
|
+
|
|
|
|
|
+ if (depth > 1)
|
|
|
|
|
+ sb.append("x").append(depth);
|
|
|
|
|
+
|
|
|
|
|
+ sb.append(", format=").append(format.name());
|
|
|
|
|
+
|
|
|
|
|
+ if (hasMipmaps())
|
|
|
|
|
+ sb.append(", mips");
|
|
|
|
|
+
|
|
|
|
|
+ if (getId() >= 0)
|
|
|
|
|
+ sb.append(", id=").append(id);
|
|
|
|
|
+
|
|
|
|
|
+ sb.append("]");
|
|
|
|
|
+
|
|
|
|
|
+ return sb.toString();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean equals(Object other) {
|
|
|
|
|
+ if (other == this) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!(other instanceof Image)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ Image that = (Image) other;
|
|
|
|
|
+ if (this.getFormat() != that.getFormat())
|
|
|
|
|
+ return false;
|
|
|
|
|
+ if (this.getWidth() != that.getWidth())
|
|
|
|
|
+ return false;
|
|
|
|
|
+ if (this.getHeight() != that.getHeight())
|
|
|
|
|
+ return false;
|
|
|
|
|
+ if (this.getData() != null && !this.getData().equals(that.getData()))
|
|
|
|
|
+ return false;
|
|
|
|
|
+ if (this.getData() == null && that.getData() != null)
|
|
|
|
|
+ return false;
|
|
|
|
|
+ if (this.getMipMapSizes() != null
|
|
|
|
|
+ && !Arrays.equals(this.getMipMapSizes(), that.getMipMapSizes()))
|
|
|
|
|
+ return false;
|
|
|
|
|
+ if (this.getMipMapSizes() == null && that.getMipMapSizes() != null)
|
|
|
|
|
+ return false;
|
|
|
|
|
+ if (this.getMultiSamples() != that.getMultiSamples())
|
|
|
|
|
+ return false;
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int hashCode() {
|
|
|
|
|
+ int hash = 7;
|
|
|
|
|
+ hash = 97 * hash + (this.format != null ? this.format.hashCode() : 0);
|
|
|
|
|
+ hash = 97 * hash + this.width;
|
|
|
|
|
+ hash = 97 * hash + this.height;
|
|
|
|
|
+ hash = 97 * hash + this.depth;
|
|
|
|
|
+ hash = 97 * hash + Arrays.hashCode(this.mipMapSizes);
|
|
|
|
|
+ hash = 97 * hash + (this.data != null ? this.data.hashCode() : 0);
|
|
|
|
|
+ hash = 97 * hash + this.multiSamples;
|
|
|
|
|
+ return hash;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void write(JmeExporter e) throws IOException {
|
|
|
|
|
+ OutputCapsule capsule = e.getCapsule(this);
|
|
|
|
|
+ capsule.write(format, "format", Format.RGBA8);
|
|
|
|
|
+ capsule.write(width, "width", 0);
|
|
|
|
|
+ capsule.write(height, "height", 0);
|
|
|
|
|
+ capsule.write(depth, "depth", 0);
|
|
|
|
|
+ capsule.write(mipMapSizes, "mipMapSizes", null);
|
|
|
|
|
+ capsule.write(multiSamples, "multiSamples", 1);
|
|
|
|
|
+ capsule.writeByteBufferArrayList(data, "data", null);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void read(JmeImporter e) throws IOException {
|
|
|
|
|
+ InputCapsule capsule = e.getCapsule(this);
|
|
|
|
|
+ format = capsule.readEnum("format", Format.class, Format.RGBA8);
|
|
|
|
|
+ width = capsule.readInt("width", 0);
|
|
|
|
|
+ height = capsule.readInt("height", 0);
|
|
|
|
|
+ depth = capsule.readInt("depth", 0);
|
|
|
|
|
+ mipMapSizes = capsule.readIntArray("mipMapSizes", null);
|
|
|
|
|
+ multiSamples = capsule.readInt("multiSamples", 1);
|
|
|
|
|
+ data = (ArrayList<ByteBuffer>) capsule.readByteBufferArrayList("data", null);
|
|
|
|
|
+
|
|
|
|
|
+ if (mipMapSizes != null) {
|
|
|
|
|
+ needGeneratedMips = false;
|
|
|
|
|
+ mipsWereGenerated = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|