Search in sources :

Example 31 with Format

use of com.jme3.texture.Image.Format in project jmonkeyengine by jMonkeyEngine.

the class ImageUtils method decompress.

/**
     * This method decompresses the given image. If the given image is already
     * decompressed nothing happens and it is simply returned.
     * 
     * @param image
     *            the image to decompress
     * @return the decompressed image
     */
public static Image decompress(Image image) {
    Format format = image.getFormat();
    int depth = image.getDepth();
    if (depth == 0) {
        depth = 1;
    }
    ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
    int[] sizes = image.getMipMapSizes() != null ? image.getMipMapSizes() : new int[1];
    int[] newMipmapSizes = image.getMipMapSizes() != null ? new int[image.getMipMapSizes().length] : null;
    for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
        ByteBuffer data = image.getData(dataLayerIndex);
        data.rewind();
        if (sizes.length == 1) {
            sizes[0] = data.remaining();
        }
        // this should always be constant for each mipmap
        float widthToHeightRatio = image.getWidth() / image.getHeight();
        List<DDSTexelData> texelDataList = new ArrayList<DDSTexelData>(sizes.length);
        int maxPosition = 0, resultSize = 0;
        for (int sizeIndex = 0; sizeIndex < sizes.length; ++sizeIndex) {
            maxPosition += sizes[sizeIndex];
            DDSTexelData texelData = new DDSTexelData(sizes[sizeIndex], widthToHeightRatio, format);
            texelDataList.add(texelData);
            switch(format) {
                // BC1
                case DXT1:
                case DXT1A:
                    while (data.position() < maxPosition) {
                        TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
                        short c0 = data.getShort();
                        short c1 = data.getShort();
                        int col0 = RGB565.RGB565_to_ARGB8(c0);
                        int col1 = RGB565.RGB565_to_ARGB8(c1);
                        colors[0].fromARGB8(col0);
                        colors[1].fromARGB8(col1);
                        if (col0 > col1) {
                            // creating color2 = 2/3color0 + 1/3color1
                            colors[2].fromPixel(colors[0]);
                            colors[2].mult(2);
                            colors[2].add(colors[1]);
                            colors[2].divide(3);
                            // creating color3 = 1/3color0 + 2/3color1;
                            colors[3].fromPixel(colors[1]);
                            colors[3].mult(2);
                            colors[3].add(colors[0]);
                            colors[3].divide(3);
                        } else {
                            // creating color2 = 1/2color0 + 1/2color1
                            colors[2].fromPixel(colors[0]);
                            colors[2].add(colors[1]);
                            colors[2].mult(0.5f);
                            colors[3].fromARGB8(0);
                        }
                        // 4-byte table with color indexes in decompressed table
                        int indexes = data.getInt();
                        texelData.add(colors, indexes);
                    }
                    break;
                case // BC2
                DXT3:
                    while (data.position() < maxPosition) {
                        TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
                        long alpha = data.getLong();
                        float[] alphas = new float[16];
                        long alphasIndex = 0;
                        for (int i = 0; i < 16; ++i) {
                            alphasIndex |= i << i * 4;
                            byte a = (byte) ((alpha >> i * 4 & 0x0F) << 4);
                            alphas[i] = a >= 0 ? a / 255.0f : 1.0f - ~a / 255.0f;
                        }
                        short c0 = data.getShort();
                        short c1 = data.getShort();
                        int col0 = RGB565.RGB565_to_ARGB8(c0);
                        int col1 = RGB565.RGB565_to_ARGB8(c1);
                        colors[0].fromARGB8(col0);
                        colors[1].fromARGB8(col1);
                        // creating color2 = 2/3color0 + 1/3color1
                        colors[2].fromPixel(colors[0]);
                        colors[2].mult(2);
                        colors[2].add(colors[1]);
                        colors[2].divide(3);
                        // creating color3 = 1/3color0 + 2/3color1;
                        colors[3].fromPixel(colors[1]);
                        colors[3].mult(2);
                        colors[3].add(colors[0]);
                        colors[3].divide(3);
                        // 4-byte table with color indexes in decompressed table
                        int indexes = data.getInt();
                        texelData.add(colors, indexes, alphas, alphasIndex);
                    }
                    break;
                case // BC3
                DXT5:
                    float[] alphas = new float[8];
                    while (data.position() < maxPosition) {
                        TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
                        alphas[0] = data.get() * 255.0f;
                        alphas[1] = data.get() * 255.0f;
                        //the casts to long must be done here because otherwise 32-bit integers would be shifetd by 32 and 40 bits which would result in improper values
                        long alphaIndices = data.get() | (long) data.get() << 8 | (long) data.get() << 16 | (long) data.get() << 24 | (long) data.get() << 32 | (long) data.get() << 40;
                        if (alphas[0] > alphas[1]) {
                            // 6 interpolated alpha values.
                            alphas[2] = (6 * alphas[0] + alphas[1]) / 7;
                            alphas[3] = (5 * alphas[0] + 2 * alphas[1]) / 7;
                            alphas[4] = (4 * alphas[0] + 3 * alphas[1]) / 7;
                            alphas[5] = (3 * alphas[0] + 4 * alphas[1]) / 7;
                            alphas[6] = (2 * alphas[0] + 5 * alphas[1]) / 7;
                            alphas[7] = (alphas[0] + 6 * alphas[1]) / 7;
                        } else {
                            alphas[2] = (4 * alphas[0] + alphas[1]) * 0.2f;
                            alphas[3] = (3 * alphas[0] + 2 * alphas[1]) * 0.2f;
                            alphas[4] = (2 * alphas[0] + 3 * alphas[1]) * 0.2f;
                            alphas[5] = (alphas[0] + 4 * alphas[1]) * 0.2f;
                            alphas[6] = 0;
                            alphas[7] = 1;
                        }
                        short c0 = data.getShort();
                        short c1 = data.getShort();
                        int col0 = RGB565.RGB565_to_ARGB8(c0);
                        int col1 = RGB565.RGB565_to_ARGB8(c1);
                        colors[0].fromARGB8(col0);
                        colors[1].fromARGB8(col1);
                        // creating color2 = 2/3color0 + 1/3color1
                        colors[2].fromPixel(colors[0]);
                        colors[2].mult(2);
                        colors[2].add(colors[1]);
                        colors[2].divide(3);
                        // creating color3 = 1/3color0 + 2/3color1;
                        colors[3].fromPixel(colors[1]);
                        colors[3].mult(2);
                        colors[3].add(colors[0]);
                        colors[3].divide(3);
                        // 4-byte table with color indexes in decompressed table
                        int indexes = data.getInt();
                        texelData.add(colors, indexes, alphas, alphaIndices);
                    }
                    break;
                default:
                    throw new IllegalStateException("Unknown compressed format: " + format);
            }
            newMipmapSizes[sizeIndex] = texelData.getSizeInBytes();
            resultSize += texelData.getSizeInBytes();
        }
        byte[] bytes = new byte[resultSize];
        int offset = 0;
        byte[] pixelBytes = new byte[4];
        for (DDSTexelData texelData : texelDataList) {
            for (int i = 0; i < texelData.getPixelWidth(); ++i) {
                for (int j = 0; j < texelData.getPixelHeight(); ++j) {
                    if (texelData.getRGBA8(i, j, pixelBytes)) {
                        bytes[offset + (j * texelData.getPixelWidth() + i) * 4] = pixelBytes[0];
                        bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 1] = pixelBytes[1];
                        bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 2] = pixelBytes[2];
                        bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 3] = pixelBytes[3];
                    } else {
                        break;
                    }
                }
            }
            offset += texelData.getSizeInBytes();
        }
        dataArray.add(BufferUtils.createByteBuffer(bytes));
    }
    Image result = depth > 1 ? new Image(Format.RGBA8, image.getWidth(), image.getHeight(), depth, dataArray, com.jme3.texture.image.ColorSpace.Linear) : new Image(Format.RGBA8, image.getWidth(), image.getHeight(), dataArray.get(0), com.jme3.texture.image.ColorSpace.Linear);
    if (newMipmapSizes != null) {
        result.setMipMapSizes(newMipmapSizes);
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) BufferedImage(java.awt.image.BufferedImage) Image(com.jme3.texture.Image) ByteBuffer(java.nio.ByteBuffer) Format(com.jme3.texture.Image.Format)

Example 32 with Format

use of com.jme3.texture.Image.Format in project jmonkeyengine by jMonkeyEngine.

the class ImageUtils method toJmeImage.

/**
     * Converts java awt image to jme image.
     * @param bufferedImage
     *            the java awt image
     * @param format
     *            the result image format
     * @return the jme image
     */
private static Image toJmeImage(BufferedImage bufferedImage, Format format) {
    ByteBuffer byteBuffer = BufferUtils.createByteBuffer(bufferedImage.getWidth() * bufferedImage.getHeight() * 3);
    ImageToAwt.convert(bufferedImage, format, byteBuffer);
    return new Image(format, bufferedImage.getWidth(), bufferedImage.getHeight(), byteBuffer, com.jme3.texture.image.ColorSpace.Linear);
}
Also used : BufferedImage(java.awt.image.BufferedImage) Image(com.jme3.texture.Image) ByteBuffer(java.nio.ByteBuffer)

Example 33 with Format

use of com.jme3.texture.Image.Format in project jmonkeyengine by jMonkeyEngine.

the class TextureBlenderAWT method blend.

@Override
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
    this.prepareImagesForBlending(image, baseImage);
    float[] pixelColor = new float[] { color[0], color[1], color[2], 1.0f };
    Format format = image.getFormat();
    PixelInputOutput basePixelIO = null, pixelReader = PixelIOFactory.getPixelIO(format);
    TexturePixel basePixel = null, pixel = new TexturePixel();
    float[] materialColor = this.materialColor;
    if (baseImage != null) {
        basePixelIO = PixelIOFactory.getPixelIO(baseImage.getFormat());
        materialColor = new float[this.materialColor.length];
        basePixel = new TexturePixel();
    }
    int width = image.getWidth();
    int height = image.getHeight();
    int depth = image.getDepth();
    if (depth == 0) {
        depth = 1;
    }
    int bytesPerPixel = image.getFormat().getBitsPerPixel() >> 3;
    ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
    float[] resultPixel = new float[4];
    for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
        ByteBuffer data = image.getData(dataLayerIndex);
        data.rewind();
        int imagePixelCount = data.limit() / bytesPerPixel;
        ByteBuffer newData = BufferUtils.createByteBuffer(imagePixelCount * 4);
        int dataIndex = 0, x = 0, y = 0, index = 0;
        while (index < data.limit()) {
            // getting the proper material color if the base texture is applied
            if (basePixelIO != null) {
                basePixelIO.read(baseImage, dataLayerIndex, basePixel, x, y);
                basePixel.toRGBA(materialColor);
                ++x;
                if (x >= width) {
                    x = 0;
                    ++y;
                }
            }
            // reading the current texture's pixel
            pixelReader.read(image, dataLayerIndex, pixel, index);
            index += bytesPerPixel;
            pixel.toRGBA(pixelColor);
            if (negateTexture) {
                pixel.negate();
            }
            this.blendPixel(resultPixel, materialColor, pixelColor, blenderContext);
            newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f));
            newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f));
            newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f));
            newData.put(dataIndex++, (byte) (pixelColor[3] * 255.0f));
        }
        dataArray.add(newData);
    }
    Image result = depth > 1 ? new Image(Format.RGBA8, width, height, depth, dataArray, ColorSpace.Linear) : new Image(Format.RGBA8, width, height, dataArray.get(0), ColorSpace.Linear);
    if (image.getMipMapSizes() != null) {
        result.setMipMapSizes(image.getMipMapSizes().clone());
    }
    return result;
}
Also used : Format(com.jme3.texture.Image.Format) PixelInputOutput(com.jme3.scene.plugins.blender.textures.io.PixelInputOutput) ArrayList(java.util.ArrayList) Image(com.jme3.texture.Image) TexturePixel(com.jme3.scene.plugins.blender.textures.TexturePixel) ByteBuffer(java.nio.ByteBuffer)

Example 34 with Format

use of com.jme3.texture.Image.Format in project jmonkeyengine by jMonkeyEngine.

the class DDSPixelInputOutput method read.

public void read(Image image, int layer, TexturePixel pixel, int x, int y) {
    int xTexetlIndex = x % image.getWidth() >> 2;
    int yTexelIndex = y % image.getHeight() >> 2;
    int xTexelCount = image.getWidth() >> 2;
    int texelIndex = yTexelIndex * xTexelCount + xTexetlIndex;
    TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
    int indexes = 0;
    long alphaIndexes = 0;
    float[] alphas = null;
    ByteBuffer data = image.getData().get(layer);
    switch(image.getFormat()) {
        // BC1
        case DXT1:
        case DXT1A:
            {
                data.position(texelIndex * 8);
                short c0 = data.getShort();
                short c1 = data.getShort();
                int col0 = RGB565.RGB565_to_ARGB8(c0);
                int col1 = RGB565.RGB565_to_ARGB8(c1);
                colors[0].fromARGB8(col0);
                colors[1].fromARGB8(col1);
                if (col0 > col1) {
                    // creating color2 = 2/3color0 + 1/3color1
                    colors[2].fromPixel(colors[0]);
                    colors[2].mult(2);
                    colors[2].add(colors[1]);
                    colors[2].divide(3);
                    // creating color3 = 1/3color0 + 2/3color1;
                    colors[3].fromPixel(colors[1]);
                    colors[3].mult(2);
                    colors[3].add(colors[0]);
                    colors[3].divide(3);
                } else {
                    // creating color2 = 1/2color0 + 1/2color1
                    colors[2].fromPixel(colors[0]);
                    colors[2].add(colors[1]);
                    colors[2].mult(0.5f);
                    colors[3].fromARGB8(0);
                }
                // 4-byte table with color indexes in decompressed table
                indexes = data.getInt();
                break;
            }
        case DXT3:
            {
                // BC2
                data.position(texelIndex * 16);
                long alpha = data.getLong();
                alphas = new float[16];
                for (int i = 0; i < 16; ++i) {
                    alphaIndexes |= i << i * 4;
                    byte a = (byte) ((alpha >> i * 4 & 0x0F) << 4);
                    alphas[i] = a >= 0 ? a / 255.0f : 1.0f - ~a / 255.0f;
                }
                short c0 = data.getShort();
                short c1 = data.getShort();
                int col0 = RGB565.RGB565_to_ARGB8(c0);
                int col1 = RGB565.RGB565_to_ARGB8(c1);
                colors[0].fromARGB8(col0);
                colors[1].fromARGB8(col1);
                // creating color2 = 2/3color0 + 1/3color1
                colors[2].fromPixel(colors[0]);
                colors[2].mult(2);
                colors[2].add(colors[1]);
                colors[2].divide(3);
                // creating color3 = 1/3color0 + 2/3color1;
                colors[3].fromPixel(colors[1]);
                colors[3].mult(2);
                colors[3].add(colors[0]);
                colors[3].divide(3);
                // 4-byte table with color indexes in decompressed table
                indexes = data.getInt();
                break;
            }
        case DXT5:
            {
                // BC3
                data.position(texelIndex * 16);
                alphas = new float[8];
                alphas[0] = data.get() * 255.0f;
                alphas[1] = data.get() * 255.0f;
                // the casts to long must be done here because otherwise 32-bit integers would be shifetd by 32 and 40 bits which would result in improper values
                alphaIndexes = (long) data.get() | (long) data.get() << 8 | (long) data.get() << 16 | (long) data.get() << 24 | (long) data.get() << 32 | (long) data.get() << 40;
                if (alphas[0] > alphas[1]) {
                    // 6 interpolated alpha values.
                    alphas[2] = (6 * alphas[0] + alphas[1]) / 7;
                    alphas[3] = (5 * alphas[0] + 2 * alphas[1]) / 7;
                    alphas[4] = (4 * alphas[0] + 3 * alphas[1]) / 7;
                    alphas[5] = (3 * alphas[0] + 4 * alphas[1]) / 7;
                    alphas[6] = (2 * alphas[0] + 5 * alphas[1]) / 7;
                    alphas[7] = (alphas[0] + 6 * alphas[1]) / 7;
                } else {
                    alphas[2] = (4 * alphas[0] + alphas[1]) * 0.2f;
                    alphas[3] = (3 * alphas[0] + 2 * alphas[1]) * 0.2f;
                    alphas[4] = (2 * alphas[0] + 3 * alphas[1]) * 0.2f;
                    alphas[5] = (alphas[0] + 4 * alphas[1]) * 0.2f;
                    alphas[6] = 0;
                    alphas[7] = 1;
                }
                short c0 = data.getShort();
                short c1 = data.getShort();
                int col0 = RGB565.RGB565_to_ARGB8(c0);
                int col1 = RGB565.RGB565_to_ARGB8(c1);
                colors[0].fromARGB8(col0);
                colors[1].fromARGB8(col1);
                // creating color2 = 2/3color0 + 1/3color1
                colors[2].fromPixel(colors[0]);
                colors[2].mult(2);
                colors[2].add(colors[1]);
                colors[2].divide(3);
                // creating color3 = 1/3color0 + 2/3color1;
                colors[3].fromPixel(colors[1]);
                colors[3].mult(2);
                colors[3].add(colors[0]);
                colors[3].divide(3);
                // 4-byte table with color indexes in decompressed table
                indexes = data.getInt();
                break;
            }
        default:
            throw new IllegalStateException("Unsupported decompression format.");
    }
    // coordinates of the pixel in the selected texel
    // pixels are arranged from left to right
    x = x - 4 * xTexetlIndex;
    // pixels are arranged from bottom to top (that is why '3 - ...' is at the start)
    y = 3 - y - 4 * yTexelIndex;
    int pixelIndexInTexel = (y * 4 + x) * (int) FastMath.log(colors.length, 2);
    int alphaIndexInTexel = alphas != null ? (y * 4 + x) * (int) FastMath.log(alphas.length, 2) : 0;
    // getting the pixel
    int indexMask = colors.length - 1;
    int colorIndex = indexes >> pixelIndexInTexel & indexMask;
    float alpha = alphas != null ? alphas[(int) (alphaIndexes >> alphaIndexInTexel & 0x07)] : colors[colorIndex].alpha;
    pixel.fromPixel(colors[colorIndex]);
    pixel.alpha = alpha;
}
Also used : TexturePixel(com.jme3.scene.plugins.blender.textures.TexturePixel) ByteBuffer(java.nio.ByteBuffer)

Example 35 with Format

use of com.jme3.texture.Image.Format in project jmonkeyengine by jMonkeyEngine.

the class EnvMapUtils method generatePrefilteredEnvMap.

/**
     * Generates the prefiltered env map (used for image based specular
     * lighting) With the GGX/Shlick brdf
     * {@link EnvMapUtils#getSphericalHarmonicsCoefficents(com.jme3.texture.TextureCubeMap)}
     * Note that the output cube map is in RGBA8 format.
     *
     * @param sourceEnvMap
     * @param targetMapSize the size of the irradiance map to generate
     * @param store
     * @param fixSeamsMethod the method to fix seams
     * @return The irradiance cube map for the given coefficients
     */
public static TextureCubeMap generatePrefilteredEnvMap(TextureCubeMap sourceEnvMap, int targetMapSize, FixSeamsMethod fixSeamsMethod, TextureCubeMap store) {
    TextureCubeMap pem = store;
    if (pem == null) {
        pem = new TextureCubeMap(targetMapSize, targetMapSize, Image.Format.RGB16F);
        pem.setMagFilter(Texture.MagFilter.Bilinear);
        pem.setMinFilter(Texture.MinFilter.Trilinear);
        pem.getImage().setColorSpace(ColorSpace.Linear);
    }
    int nbMipMap = (int) (Math.log(targetMapSize) / Math.log(2) - 1);
    CubeMapWrapper sourceWrapper = new CubeMapWrapper(sourceEnvMap);
    CubeMapWrapper targetWrapper = new CubeMapWrapper(pem);
    targetWrapper.initMipMaps(nbMipMap);
    Vector3f texelVect = new Vector3f();
    Vector3f color = new Vector3f();
    ColorRGBA outColor = new ColorRGBA();
    for (int mipLevel = 0; mipLevel < nbMipMap; mipLevel++) {
        System.err.println("mip level " + mipLevel);
        float roughness = getRoughnessFromMip(mipLevel, nbMipMap);
        int nbSamples = getSampleFromMip(mipLevel, nbMipMap);
        int targetMipMapSize = (int) pow(2, nbMipMap + 1 - mipLevel);
        for (int face = 0; face < 6; face++) {
            System.err.println("face " + face);
            for (int y = 0; y < targetMipMapSize; y++) {
                for (int x = 0; x < targetMipMapSize; x++) {
                    color.set(0, 0, 0);
                    getVectorFromCubemapFaceTexCoord(x, y, targetMipMapSize, face, texelVect, FixSeamsMethod.Wrap);
                    prefilterEnvMapTexel(sourceWrapper, roughness, texelVect, nbSamples, color);
                    outColor.set(color.x, color.y, color.z, 1.0f);
                    // System.err.println("coords " + x + "," + y);
                    targetWrapper.setPixel(x, y, face, mipLevel, outColor);
                }
            }
        }
    }
    return pem;
}
Also used : ColorRGBA(com.jme3.math.ColorRGBA) TextureCubeMap(com.jme3.texture.TextureCubeMap) Vector3f(com.jme3.math.Vector3f)

Aggregations

Image (com.jme3.texture.Image)20 ByteBuffer (java.nio.ByteBuffer)19 Format (com.jme3.texture.Image.Format)13 IOException (java.io.IOException)8 BufferedImage (java.awt.image.BufferedImage)7 ArrayList (java.util.ArrayList)7 TextureCubeMap (com.jme3.texture.TextureCubeMap)6 ColorRGBA (com.jme3.math.ColorRGBA)5 Texture2D (com.jme3.texture.Texture2D)5 TexturePixel (com.jme3.scene.plugins.blender.textures.TexturePixel)4 PixelInputOutput (com.jme3.scene.plugins.blender.textures.io.PixelInputOutput)4 DataInputStream (java.io.DataInputStream)4 AssetNotFoundException (com.jme3.asset.AssetNotFoundException)3 Vector3f (com.jme3.math.Vector3f)3 ShaderNodeVariable (com.jme3.shader.ShaderNodeVariable)3 VariableMapping (com.jme3.shader.VariableMapping)3 FrameBuffer (com.jme3.texture.FrameBuffer)3 LittleEndien (com.jme3.util.LittleEndien)3 InputStream (java.io.InputStream)3 TextureKey (com.jme3.asset.TextureKey)2