/*
* Copyright 2016 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.terasology.rendering.assets.texture;
import org.terasology.assets.module.annotations.RegisterAssetFileFormat;
import org.terasology.assets.module.ModuleAssetDataProducer;
import org.terasology.assets.ResourceUrn;
import org.terasology.assets.format.AbstractAssetFileFormat;
import org.terasology.assets.format.AssetDataFile;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.awt.image.ColorModel;
import java.io.InputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.file.PathMatcher;
import java.util.List;
import javax.imageio.ImageIO;
/**
*/
@RegisterAssetFileFormat
public class AWTTextureFormat extends AbstractAssetFileFormat<TextureData> {
private Texture.FilterMode defaultFilterMode;
private PathMatcher pathMatcher;
public AWTTextureFormat() {
this(Texture.FilterMode.NEAREST, path -> {
if (path.getName(1).toString().equals(ModuleAssetDataProducer.OVERRIDE_FOLDER)) {
return path.getName(3).toString().equals("textures");
} else {
return path.getName(2).toString().equals("textures");
}
});
}
public AWTTextureFormat(Texture.FilterMode defaultFilterMode, PathMatcher pathMatcher) {
super("jpeg", "jpg", "bmp", "gif", "png");
this.defaultFilterMode = defaultFilterMode;
this.pathMatcher = pathMatcher;
}
@Override
public TextureData load(ResourceUrn urn, List<AssetDataFile> inputs) throws IOException {
try (InputStream inStream = inputs.get(0).openStream()) {
final BufferedImage img = ImageIO.read(inStream);
final WritableRaster raster = img.getRaster();
final DataBufferByte dbf = (DataBufferByte) raster.getDataBuffer();
byte[] data = dbf.getData();
final int stride = data.length / (img.getWidth() * img.getHeight());
// Sanity check
if (stride > 4) {
throw new IOException("Image data makes no sense (got "
+ data.length + ", expected "
+ img.getWidth() * img.getHeight() * stride
+ ")");
}
final ByteBuffer buf = ByteBuffer.allocateDirect(4 * img.getWidth() * img.getHeight());
// Convert AWT image to proper internal format
if (img.getType() == BufferedImage.TYPE_3BYTE_BGR) {
for (int i = 0; i < data.length; i += stride) {
buf.put(data, i + 2, 1); // R
buf.put(data, i + 1, 1); // G
buf.put(data, i + 0, 1); // B
buf.put((byte) 255); // A
}
} else if (img.getType() == BufferedImage.TYPE_4BYTE_ABGR) {
for (int i = 0; i < data.length; i += stride) {
buf.put(data, i + 3, 1); // R
buf.put(data, i + 2, 1); // G
buf.put(data, i + 1, 1); // B
buf.put(data, i + 0, 1); // A
}
} else if (img.getType() == BufferedImage.TYPE_INT_ARGB) {
for (int i = 0; i < data.length; i += stride) {
buf.put(data, i + 1, 1); // R
buf.put(data, i + 2, 1); // G
buf.put(data, i + 3, 1); // B
buf.put(data, i + 0, 1); // A
}
} else if (img.getType() == BufferedImage.TYPE_BYTE_INDEXED) {
final ColorModel cm = img.getColorModel();
for (int i = 0; i < data.length; i += stride) {
buf.put((byte) cm.getRed(data[i])); // R
buf.put((byte) cm.getGreen(data[i])); // G
buf.put((byte) cm.getBlue(data[i])); // B
buf.put((byte) cm.getAlpha(data[i])); // A
}
} else {
throw new IOException("Unsuported AWT format: " + img.getType());
}
buf.flip();
Texture.FilterMode filterMode = defaultFilterMode;
Texture.WrapMode wrapMode = Texture.WrapMode.CLAMP;
return new TextureData(img.getWidth(), img.getHeight(), new ByteBuffer[]{buf}, wrapMode, filterMode);
} catch (UnsupportedOperationException e) {
throw new IOException(e);
}
}
@Override
public PathMatcher getFileMatcher() {
return path -> super.getFileMatcher().matches(path) && pathMatcher.matches(path);
}
}