Added support for multilayered images.
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9336 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
		
							parent
							
								
									96cfd22510
								
							
						
					
					
						commit
						b09e37c9d9
					
				| @ -236,17 +236,24 @@ public class TextureHelper extends AbstractBlenderHelper { | ||||
| 	 * @return the decompressed image | ||||
| 	 */ | ||||
| 	public Image decompress(Image image) { | ||||
| 		byte[] bytes = null; | ||||
| 		TexturePixel[] colors = null; | ||||
| 		ByteBuffer data = image.getData(0);// TODO: support decompression of all data 'layers' | ||||
| 		data.rewind(); | ||||
| 		Format format = image.getFormat(); | ||||
| 		int depth = image.getDepth(); | ||||
| 		if(depth == 0) { | ||||
| 			depth = 1; | ||||
| 		} | ||||
| 		ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth); | ||||
| 		TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() }; | ||||
| 		 | ||||
| 		DDSTexelData texelData = new DDSTexelData(data.remaining() / (format.getBitsPerPixel() * 2), image.getWidth(), image.getHeight(), format != Format.DXT1); | ||||
| 		switch (format) {// TODO: DXT1A | ||||
| 		for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) { | ||||
| 			ByteBuffer data = image.getData(dataLayerIndex); | ||||
| 			data.rewind(); | ||||
| 			 | ||||
| 			byte[] bytes = new byte[image.getWidth() * image.getHeight() << 2]; | ||||
| 			DDSTexelData texelData = new DDSTexelData(data.remaining() * 8/format.getBitsPerPixel()/16/*data.remaining() / (format.getBitsPerPixel() << 1)*/,  | ||||
| 					image.getWidth(), image.getHeight(), format != Format.DXT1); | ||||
| 			switch (format) { | ||||
| 				case DXT1:// BC1 | ||||
| 				bytes = new byte[image.getWidth() * image.getHeight() * 4]; | ||||
| 				colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() }; | ||||
| 				case DXT1A: | ||||
| 					while (data.hasRemaining()) { | ||||
| 						short c0 = data.getShort(); | ||||
| 						short c1 = data.getShort(); | ||||
| @ -280,8 +287,6 @@ public class TextureHelper extends AbstractBlenderHelper { | ||||
| 					} | ||||
| 					break; | ||||
| 				case DXT3:// BC2 | ||||
| 				bytes = new byte[image.getWidth() * image.getHeight() * 4]; | ||||
| 				colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() }; | ||||
| 					while (data.hasRemaining()) { | ||||
| 						long alpha = data.getLong(); | ||||
| 						float[] alphas = new float[16]; | ||||
| @ -316,8 +321,6 @@ public class TextureHelper extends AbstractBlenderHelper { | ||||
| 					} | ||||
| 					break; | ||||
| 				case DXT5:// BC3 | ||||
| 				bytes = new byte[image.getWidth() * image.getHeight() * 4]; | ||||
| 				colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() }; | ||||
| 					float[] alphas = new float[8]; | ||||
| 					while (data.hasRemaining()) { | ||||
| 						alphas[0] = data.get() * 255.0f; | ||||
| @ -363,10 +366,9 @@ public class TextureHelper extends AbstractBlenderHelper { | ||||
| 					} | ||||
| 					break; | ||||
| 				default: | ||||
| 				LOGGER.fine("Unsupported decompression format."); | ||||
| 					throw new IllegalStateException("Unknown compressed format: " + format); | ||||
| 			} | ||||
| 
 | ||||
| 		if (bytes != null) {// writing the data to the result table | ||||
| 			byte[] pixelBytes = new byte[4]; | ||||
| 			for (int i = 0; i < image.getWidth(); ++i) { | ||||
| 				for (int j = 0; j < image.getHeight(); ++j) { | ||||
| @ -377,11 +379,15 @@ public class TextureHelper extends AbstractBlenderHelper { | ||||
| 					bytes[(j * image.getWidth() + i) * 4 + 3] = pixelBytes[3]; | ||||
| 				} | ||||
| 			} | ||||
| 			// TODO: think of other image formats (ie. RGB if the texture has no | ||||
| 			// alpha values) | ||||
| 			return new Image(Format.RGBA8, image.getWidth(), image.getHeight(), BufferUtils.createByteBuffer(bytes)); | ||||
| 			dataArray.add(BufferUtils.createByteBuffer(bytes)); | ||||
| 		} | ||||
| 		return image; | ||||
| 		 | ||||
| 		Image result = depth > 1 ? new Image(Format.RGBA8, image.getWidth(), image.getHeight(), depth, dataArray) :  | ||||
| 								   new Image(Format.RGBA8, image.getWidth(), image.getHeight(), dataArray.get(0)); | ||||
| 		if(image.getMipMapSizes() != null) { | ||||
| 			result.setMipMapSizes(image.getMipMapSizes().clone()); | ||||
| 		} | ||||
| 		return result; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  | ||||
| @ -42,7 +42,6 @@ public class TextureBlenderAWT extends AbstractTextureBlender { | ||||
| 	public Image blend(Image image, Image baseImage, BlenderContext blenderContext) { | ||||
| 		float[] pixelColor = new float[] { color[0], color[1], color[2], 1.0f }; | ||||
| 		Format format = image.getFormat(); | ||||
| 		ByteBuffer data = image.getData(0); | ||||
| 		 | ||||
| 		PixelInputOutput basePixelIO = null, pixelReader = PixelIOFactory.getPixelIO(format); | ||||
| 		TexturePixel basePixel = null, pixel = new TexturePixel(); | ||||
| @ -59,9 +58,14 @@ public class TextureBlenderAWT extends AbstractTextureBlender { | ||||
| 		if (depth == 0) { | ||||
| 			depth = 1; | ||||
| 		} | ||||
| 		ByteBuffer newData = BufferUtils.createByteBuffer(width * height * depth * 4); | ||||
| 		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(); | ||||
| 			ByteBuffer newData = BufferUtils.createByteBuffer(width * height * 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 | ||||
| @ -90,13 +94,14 @@ public class TextureBlenderAWT extends AbstractTextureBlender { | ||||
| 					++y; | ||||
| 				} | ||||
| 			} | ||||
| 		if(depth > 1) { | ||||
| 			ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1); | ||||
| 			dataArray.add(newData); | ||||
| 			return new Image(Format.RGBA8, width, height, depth, dataArray); | ||||
| 		} else { | ||||
| 			return new Image(Format.RGBA8, width, height, newData); | ||||
| 		} | ||||
| 		 | ||||
| 		Image result = depth > 1 ? new Image(Format.RGBA8, width, height, depth, dataArray) : new Image(Format.RGBA8, width, height, dataArray.get(0)); | ||||
| 		if(image.getMipMapSizes() != null) { | ||||
| 			result.setMipMapSizes(image.getMipMapSizes().clone()); | ||||
| 		} | ||||
| 		return result; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  | ||||
| @ -2,8 +2,6 @@ package com.jme3.scene.plugins.blender.textures.blending; | ||||
| 
 | ||||
| import java.nio.ByteBuffer; | ||||
| import java.util.ArrayList; | ||||
| import java.util.logging.Level; | ||||
| import java.util.logging.Logger; | ||||
| 
 | ||||
| import jme3tools.converters.RGB565; | ||||
| 
 | ||||
| @ -18,15 +16,12 @@ import com.jme3.util.BufferUtils; | ||||
| /** | ||||
|  * The class that is responsible for blending the following texture types: | ||||
|  * <li> DXT1 | ||||
|  * <li> DXT1A | ||||
|  * <li> DXT3 | ||||
|  * <li> DXT5 | ||||
|  * Not yet supported (but will be): | ||||
|  * <li> DXT1A: | ||||
|  * @author Marcin Roguski (Kaelthas) | ||||
|  */ | ||||
| public class TextureBlenderDDS extends TextureBlenderAWT { | ||||
| 	private static final Logger	LOGGER	= Logger.getLogger(TextureBlenderDDS.class.getName()); | ||||
| 
 | ||||
| 	public TextureBlenderDDS(int flag, boolean negateTexture, int blendType, float[] materialColor, float[] color, float blendFactor) { | ||||
| 		super(flag, negateTexture, blendType, materialColor, color, blendFactor); | ||||
| 	} | ||||
| @ -34,16 +29,13 @@ public class TextureBlenderDDS extends TextureBlenderAWT { | ||||
| 	@Override | ||||
| 	public Image blend(Image image, Image baseImage, BlenderContext blenderContext) { | ||||
| 		Format format = image.getFormat(); | ||||
| 		ByteBuffer data = image.getData(0); | ||||
| 		data.rewind(); | ||||
| 
 | ||||
| 		int width = image.getWidth(); | ||||
| 		int height = image.getHeight(); | ||||
| 		int depth = image.getDepth(); | ||||
| 		if (depth == 0) { | ||||
| 			depth = 1; | ||||
| 		} | ||||
| 		ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining()); | ||||
| 		ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth); | ||||
| 		 | ||||
| 		PixelInputOutput basePixelIO = null; | ||||
| 		float[][] compressedMaterialColor = null; | ||||
| @ -57,13 +49,14 @@ public class TextureBlenderDDS extends TextureBlenderAWT { | ||||
| 		float[] resultPixel = new float[4]; | ||||
| 		float[] pixelColor = new float[4]; | ||||
| 		TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel() }; | ||||
| 		int dataIndex = 0, baseXTexelIndex = 0, baseYTexelIndex = 0; | ||||
| 		int baseXTexelIndex = 0, baseYTexelIndex = 0; | ||||
| 		float[] alphas = new float[] {1, 1}; | ||||
| 		for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) { | ||||
| 			ByteBuffer data = image.getData(dataLayerIndex); | ||||
| 			data.rewind(); | ||||
| 			ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining()); | ||||
| 			System.out.println(dataLayerIndex); | ||||
| 			while (data.hasRemaining()) { | ||||
| 			if(format == Format.DXT1A) { | ||||
| 				LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}", format); | ||||
| 				break; | ||||
| 			} | ||||
| 				if(format == Format.DXT3) { | ||||
| 					long alpha = data.getLong(); | ||||
| 					//get alpha for first and last pixel that is compressed in the texel | ||||
| @ -71,16 +64,17 @@ public class TextureBlenderDDS extends TextureBlenderAWT { | ||||
| 					byte alpha1 = (byte)(alpha >> 60 & 0xFF); | ||||
| 					alphas[0] = alpha0 >= 0 ? alpha0 / 255.0f : 1.0f - ~alpha0 / 255.0f; | ||||
| 					alphas[1] = alpha1 >= 0 ? alpha1 / 255.0f : 1.0f - ~alpha1 / 255.0f; | ||||
| 				dataIndex += 8; | ||||
| 					newData.putLong(alpha); | ||||
| 				} else if(format == Format.DXT5) { | ||||
| 					byte alpha0 = data.get(); | ||||
| 					byte alpha1 = data.get(); | ||||
| 					alphas[0] = alpha0 >= 0 ? alpha0 / 255.0f : 1.0f - ~alpha0 / 255.0f; | ||||
| 					alphas[1] = alpha1 >= 0 ? alpha0 / 255.0f : 1.0f - ~alpha0 / 255.0f; | ||||
| 					newData.put(alpha0); | ||||
| 					newData.put(alpha1); | ||||
| 					//only read the next 6 bytes (these are alpha indexes) | ||||
| 				data.getInt(); | ||||
| 				data.getShort(); | ||||
| 				dataIndex += 8; | ||||
| 					newData.putInt(data.getInt()); | ||||
| 					newData.putShort(data.getShort()); | ||||
| 				} | ||||
| 				int col0 = RGB565.RGB565_to_ARGB8(data.getShort()); | ||||
| 				int col1 = RGB565.RGB565_to_ARGB8(data.getShort()); | ||||
| @ -107,13 +101,11 @@ public class TextureBlenderDDS extends TextureBlenderAWT { | ||||
| 					colors[i].fromARGB8(1, resultPixel[0], resultPixel[1], resultPixel[2]); | ||||
| 					int argb8 = colors[i].toARGB8(); | ||||
| 					short rgb565 = RGB565.ARGB8_to_RGB565(argb8); | ||||
| 				newData.putShort(dataIndex, rgb565); | ||||
| 				dataIndex += 2; | ||||
| 					newData.putShort(rgb565); | ||||
| 				} | ||||
| 
 | ||||
| 				// just copy the remaining 4 bytes of the current texel | ||||
| 			newData.putInt(dataIndex, data.getInt()); | ||||
| 			dataIndex += 4; | ||||
| 				newData.putInt(data.getInt()); | ||||
| 				 | ||||
| 				++baseXTexelIndex; | ||||
| 				if(baseXTexelIndex > image.getWidth() >> 2) { | ||||
| @ -121,13 +113,13 @@ public class TextureBlenderDDS extends TextureBlenderAWT { | ||||
| 					++baseYTexelIndex; | ||||
| 				} | ||||
| 			} | ||||
| 		 | ||||
| 		if(depth > 1) { | ||||
| 			ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1); | ||||
| 			dataArray.add(newData); | ||||
| 			return new Image(format, width, height, depth, dataArray); | ||||
| 		} else { | ||||
| 			return new Image(format, width, height, newData); | ||||
| 		} | ||||
| 		 | ||||
| 		Image result = dataArray.size() > 1 ? new Image(format, width, height, depth, dataArray) : new Image(format, width, height, dataArray.get(0)); | ||||
| 		if(image.getMipMapSizes() != null) { | ||||
| 			result.setMipMapSizes(image.getMipMapSizes().clone()); | ||||
| 		} | ||||
| 		return result; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -35,8 +35,6 @@ public class TextureBlenderLuminance extends AbstractTextureBlender { | ||||
| 	 | ||||
| 	public Image blend(Image image, Image baseImage, BlenderContext blenderContext) { | ||||
| 		Format format = image.getFormat(); | ||||
| 		ByteBuffer data = image.getData(0); | ||||
| 		data.rewind(); | ||||
| 
 | ||||
| 		PixelInputOutput basePixelIO = null; | ||||
| 		TexturePixel basePixel = null; | ||||
| @ -53,10 +51,15 @@ public class TextureBlenderLuminance extends AbstractTextureBlender { | ||||
| 		if (depth == 0) { | ||||
| 			depth = 1; | ||||
| 		} | ||||
| 		ByteBuffer newData = BufferUtils.createByteBuffer(width * height * depth * 4); | ||||
| 		ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth); | ||||
| 
 | ||||
| 		float[] resultPixel = new float[4]; | ||||
| 		float[] tinAndAlpha = new float[2]; | ||||
| 		for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) { | ||||
| 			ByteBuffer data = image.getData(dataLayerIndex); | ||||
| 			data.rewind(); | ||||
| 			ByteBuffer newData = BufferUtils.createByteBuffer(width * height * 4); | ||||
| 			 | ||||
| 			int dataIndex = 0, x = 0, y = 0; | ||||
| 			while (data.hasRemaining()) { | ||||
| 				//getting the proper material color if the base texture is applied | ||||
| @ -78,14 +81,14 @@ public class TextureBlenderLuminance extends AbstractTextureBlender { | ||||
| 					++y; | ||||
| 				} | ||||
| 			} | ||||
| 		 | ||||
| 		if(depth > 1) { | ||||
| 			ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1); | ||||
| 			dataArray.add(newData); | ||||
| 			return new Image(Format.RGBA8, width, height, depth, dataArray); | ||||
| 		} else { | ||||
| 			return new Image(Format.RGBA8, width, height, newData); | ||||
| 		} | ||||
| 		 | ||||
| 		Image result = depth > 1 ? new Image(Format.RGBA8, width, height, depth, dataArray) : new Image(Format.RGBA8, width, height, dataArray.get(0)); | ||||
| 		if(image.getMipMapSizes() != null) { | ||||
| 			result.setMipMapSizes(image.getMipMapSizes().clone()); | ||||
| 		} | ||||
| 		return result; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  | ||||
| @ -34,7 +34,8 @@ import com.jme3.texture.Image; | ||||
| 		ByteBuffer data = image.getData().get(0); | ||||
| 		 | ||||
| 		switch (image.getFormat()) { | ||||
| 			case DXT1: {// BC1 | ||||
| 			case DXT1: // BC1 | ||||
| 			case DXT1A:{ | ||||
| 				data.position(texelIndex * 8); | ||||
| 				short c0 = data.getShort(); | ||||
| 				short c1 = data.getShort(); | ||||
| @ -142,8 +143,6 @@ import com.jme3.texture.Image; | ||||
| 				indexes = data.getInt();// 4-byte table with color indexes in decompressed table | ||||
| 				break; | ||||
| 			} | ||||
| 			case DXT1A://TODO: implement | ||||
| 				break; | ||||
| 			default: | ||||
| 				throw new IllegalStateException("Unsupported decompression format."); | ||||
| 		} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user