protected internal override Texture2D Read( ContentReader reader, Texture2D existingInstance ) { Texture2D texture = null; SurfaceFormat surfaceFormat; if (reader.version < 5) { SurfaceFormat_Legacy legacyFormat = (SurfaceFormat_Legacy)reader.ReadInt32(); switch (legacyFormat) { case SurfaceFormat_Legacy.Dxt1: surfaceFormat = SurfaceFormat.Dxt1; break; case SurfaceFormat_Legacy.Dxt3: surfaceFormat = SurfaceFormat.Dxt3; break; case SurfaceFormat_Legacy.Dxt5: surfaceFormat = SurfaceFormat.Dxt5; break; case SurfaceFormat_Legacy.Color: surfaceFormat = SurfaceFormat.Color; break; default: throw new NotSupportedException( "Unsupported legacy surface format." ); } } else { surfaceFormat = (SurfaceFormat)reader.ReadInt32(); } int width = reader.ReadInt32(); int height = reader.ReadInt32(); int levelCount = reader.ReadInt32(); int levelCountOutput = levelCount; SurfaceFormat convertedFormat = surfaceFormat; switch (surfaceFormat) { case SurfaceFormat.Dxt1: if (!OpenGLDevice.Instance.SupportsDxt1) { convertedFormat = SurfaceFormat.Color; } break; case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: if (!OpenGLDevice.Instance.SupportsS3tc) { convertedFormat = SurfaceFormat.Color; } break; case SurfaceFormat.NormalizedByte4: convertedFormat = SurfaceFormat.Color; break; } if (existingInstance == null) { texture = new Texture2D( reader.GraphicsDevice, width, height, levelCountOutput > 1, convertedFormat ); } else { texture = existingInstance; } for (int level = 0; level < levelCount; level += 1) { int levelDataSizeInBytes = (reader.ReadInt32()); byte[] levelData = null; // Don't assign this quite yet... int levelWidth = width >> level; int levelHeight = height >> level; if (level >= levelCountOutput) { continue; } // Convert the image data if required switch (surfaceFormat) { case SurfaceFormat.Dxt1: if (!OpenGLDevice.Instance.SupportsDxt1) { levelData = reader.ReadBytes(levelDataSizeInBytes); levelData = DxtUtil.DecompressDxt1( levelData, levelWidth, levelHeight ); } break; case SurfaceFormat.Dxt3: if (!OpenGLDevice.Instance.SupportsS3tc) { levelData = reader.ReadBytes(levelDataSizeInBytes); levelData = DxtUtil.DecompressDxt3( levelData, levelWidth, levelHeight ); } break; case SurfaceFormat.Dxt5: if (!OpenGLDevice.Instance.SupportsS3tc) { levelData = reader.ReadBytes(levelDataSizeInBytes); levelData = DxtUtil.DecompressDxt5( levelData, levelWidth, levelHeight ); } break; case SurfaceFormat.Bgr565: { levelData = reader.ReadBytes(levelDataSizeInBytes); } break; case SurfaceFormat.Bgra5551: { levelData = reader.ReadBytes(levelDataSizeInBytes); // Shift the channels to suit OPENGL int offset = 0; for (int y = 0; y < levelHeight; y += 1) { for (int x = 0; x < levelWidth; x += 1) { ushort pixel = BitConverter.ToUInt16( levelData, offset ); pixel = (ushort)( ((pixel & 0x7FFF) << 1) | ((pixel & 0x8000) >> 15) ); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } } break; case SurfaceFormat.Bgra4444: { levelData = reader.ReadBytes(levelDataSizeInBytes); // Shift the channels to suit OPENGL int offset = 0; for (int y = 0; y < levelHeight; y += 1) { for (int x = 0; x < levelWidth; x += 1) { ushort pixel = BitConverter.ToUInt16( levelData, offset ); pixel = (ushort)( ((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12) ); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } } break; case SurfaceFormat.NormalizedByte4: { levelData = reader.ReadBytes(levelDataSizeInBytes); int bytesPerPixel = 4; // According to Texture.GetFormatSize() int pitch = levelWidth * bytesPerPixel; for (int y = 0; y < levelHeight; y += 1) { for (int x = 0; x < levelWidth; x += 1) { int color = BitConverter.ToInt32( levelData, y * pitch + x * bytesPerPixel ); // R:=W levelData[y * pitch + x * 4] = (byte)(((color >> 16) & 0xff)); // G:=V levelData[y * pitch + x * 4 + 1] = (byte)(((color >> 8) & 0xff)); // B:=U levelData[y * pitch + x * 4 + 2] = (byte)(((color) & 0xff)); // A:=Q levelData[y * pitch + x * 4 + 3] = (byte)(((color >> 24) & 0xff)); } } } break; } if (levelData == null && reader.BaseStream.GetType() != typeof(System.IO.MemoryStream)) { /* If the ContentReader is not backed by a * MemoryStream, we have to read the data in. */ levelData = reader.ReadBytes(levelDataSizeInBytes); } if (levelData != null) { /* If we had to convert the data, or get the data from a * non-MemoryStream, we set the data with our levelData * reference. */ texture.SetData(level, null, levelData, 0, levelData.Length); } else { /* Ideally, we didn't have to perform any conversion or * unnecessary reading. Just throw the buffer directly * into SetData, skipping a redundant byte[] copy. */ texture.SetData <byte>( level, null, (((System.IO.MemoryStream)(reader.BaseStream)).GetBuffer()), (int)reader.BaseStream.Position, levelDataSizeInBytes ); reader.BaseStream.Seek( levelDataSizeInBytes, System.IO.SeekOrigin.Current ); } } return(texture); }
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { Texture2D texture = null; SurfaceFormat surfaceFormat; if (reader.version < 5) { SurfaceFormat_Legacy legacyFormat = (SurfaceFormat_Legacy)reader.ReadInt32(); switch (legacyFormat) { case SurfaceFormat_Legacy.Dxt1: surfaceFormat = SurfaceFormat.Dxt1; break; case SurfaceFormat_Legacy.Dxt3: surfaceFormat = SurfaceFormat.Dxt3; break; case SurfaceFormat_Legacy.Dxt5: surfaceFormat = SurfaceFormat.Dxt5; break; case SurfaceFormat_Legacy.Color: surfaceFormat = SurfaceFormat.Color; break; default: throw new NotSupportedException("Unsupported legacy surface format."); } } else { surfaceFormat = (SurfaceFormat)reader.ReadInt32(); } int width = (reader.ReadInt32()); int height = (reader.ReadInt32()); int levelCount = (reader.ReadInt32()); int levelCountOutput = levelCount; // If the system does not fully support Power of Two textures, // skip any mip maps supplied with any non PoT textures. if (levelCount > 1 && !GraphicsCapabilities.SupportsNonPowerOfTwo && (!MathHelper.IsPowerOfTwo(width) || !MathHelper.IsPowerOfTwo(height))) { levelCountOutput = 1; System.Diagnostics.Debug.WriteLine( "Device does not support non Power of Two textures. Skipping mipmaps."); } SurfaceFormat convertedFormat = surfaceFormat; switch (surfaceFormat) { #if IOS // At the moment. If a DXT Texture comes in on iOS, it's really a PVR compressed // texture. We need to use this hack until the content pipeline is implemented. // For now DXT5 means we're using 4bpp PVRCompression and DXT3 means 2bpp. Look at // PvrtcBitmapContent.cs for more information.: case SurfaceFormat.Dxt3: convertedFormat = SurfaceFormat.RgbaPvrtc2Bpp; break; case SurfaceFormat.Dxt5: convertedFormat = SurfaceFormat.RgbaPvrtc4Bpp; break; #else case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: if (!GraphicsCapabilities.SupportsDxt1) { convertedFormat = SurfaceFormat.Color; } break; case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: if (!GraphicsCapabilities.SupportsS3tc) { convertedFormat = SurfaceFormat.Color; } break; #endif case SurfaceFormat.NormalizedByte4: convertedFormat = SurfaceFormat.Color; break; } if (existingInstance == null) { texture = new Texture2D(reader.GraphicsDevice, width, height, levelCountOutput > 1, convertedFormat); } else { texture = existingInstance; } for (int level = 0; level < levelCount; level++) { int levelDataSizeInBytes = (reader.ReadInt32()); byte[] levelData = reader.ReadBytes(levelDataSizeInBytes); int levelWidth = width >> level; int levelHeight = height >> level; if (level >= levelCountOutput) { continue; } //Convert the image data if required switch (surfaceFormat) { #if !IOS case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: if (!GraphicsCapabilities.SupportsDxt1) { levelData = DxtUtil.DecompressDxt1(levelData, levelWidth, levelHeight); } break; case SurfaceFormat.Dxt3: if (!GraphicsCapabilities.SupportsS3tc) { levelData = DxtUtil.DecompressDxt3(levelData, levelWidth, levelHeight); } break; case SurfaceFormat.Dxt5: if (!GraphicsCapabilities.SupportsS3tc) { levelData = DxtUtil.DecompressDxt5(levelData, levelWidth, levelHeight); } break; #endif case SurfaceFormat.Bgr565: { /* * // BGR -> BGR * int offset = 0; * for (int y = 0; y < levelHeight; y++) * { * for (int x = 0; x < levelWidth; x++) * { * ushort pixel = BitConverter.ToUInt16(levelData, offset); * pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12)); * levelData[offset] = (byte)(pixel); * levelData[offset + 1] = (byte)(pixel >> 8); * offset += 2; * } * } */ } break; case SurfaceFormat.Bgra5551: { #if OPENGL // Shift the channels to suit OPENGL int offset = 0; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { ushort pixel = BitConverter.ToUInt16(levelData, offset); pixel = (ushort)(((pixel & 0x7FFF) << 1) | ((pixel & 0x8000) >> 15)); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } #endif } break; case SurfaceFormat.Bgra4444: { #if OPENGL // Shift the channels to suit OPENGL int offset = 0; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { ushort pixel = BitConverter.ToUInt16(levelData, offset); pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12)); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } #endif } break; case SurfaceFormat.NormalizedByte4: { int bytesPerPixel = surfaceFormat.GetSize(); int pitch = levelWidth * bytesPerPixel; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { int color = BitConverter.ToInt32(levelData, y * pitch + x * bytesPerPixel); levelData[y * pitch + x * 4] = (byte)(((color >> 16) & 0xff)); //R:=W levelData[y * pitch + x * 4 + 1] = (byte)(((color >> 8) & 0xff)); //G:=V levelData[y * pitch + x * 4 + 2] = (byte)(((color) & 0xff)); //B:=U levelData[y * pitch + x * 4 + 3] = (byte)(((color >> 24) & 0xff)); //A:=Q } } } break; } texture.SetData(level, null, levelData, 0, levelData.Length); } return(texture); }
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { Texture2D texture = null; SurfaceFormat surfaceFormat; if (reader.version < 5) { SurfaceFormat_Legacy legacyFormat = (SurfaceFormat_Legacy)reader.ReadInt32(); switch (legacyFormat) { case SurfaceFormat_Legacy.Dxt1: surfaceFormat = SurfaceFormat.Dxt1; break; case SurfaceFormat_Legacy.Dxt3: surfaceFormat = SurfaceFormat.Dxt3; break; case SurfaceFormat_Legacy.Dxt5: surfaceFormat = SurfaceFormat.Dxt5; break; case SurfaceFormat_Legacy.Color: surfaceFormat = SurfaceFormat.Color; break; default: throw new NotImplementedException(); } } else { surfaceFormat = (SurfaceFormat)reader.ReadInt32(); } int width = (reader.ReadInt32()); int height = (reader.ReadInt32()); int levelCount = (reader.ReadInt32()); SurfaceFormat convertedFormat = surfaceFormat; switch (surfaceFormat) { #if IPHONE // At the moment. If a DXT Texture comes in on iOS, it's really a PVR compressed // texture. We need to use this hack until the content pipeline is implemented. // For now DXT5 means we're using 4bpp PVRCompression and DXT3 means 2bpp. Look at // PvrtcBitmapContent.cs for more information.: case SurfaceFormat.Dxt3: convertedFormat = SurfaceFormat.RgbaPvrtc2Bpp; break; case SurfaceFormat.Dxt5: convertedFormat = SurfaceFormat.RgbaPvrtc4Bpp; break; #elif ANDROID || PSS case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: convertedFormat = SurfaceFormat.Color; break; #endif case SurfaceFormat.NormalizedByte4: convertedFormat = SurfaceFormat.Color; break; } if (existingInstance == null) { texture = new Texture2D(reader.GraphicsDevice, width, height, levelCount > 1, convertedFormat); } else { texture = existingInstance; } for (int level = 0; level < levelCount; level++) { int levelDataSizeInBytes = (reader.ReadInt32()); byte[] levelData = reader.ReadBytes(levelDataSizeInBytes); int levelWidth = width >> level; int levelHeight = height >> level; //Convert the image data if required switch (surfaceFormat) { #if ANDROID || PSS //no Dxt in OpenGL ES case SurfaceFormat.Dxt1: levelData = DxtUtil.DecompressDxt1(levelData, levelWidth, levelHeight); break; case SurfaceFormat.Dxt3: levelData = DxtUtil.DecompressDxt3(levelData, levelWidth, levelHeight); break; case SurfaceFormat.Dxt5: levelData = DxtUtil.DecompressDxt5(levelData, levelWidth, levelHeight); break; #endif case SurfaceFormat.Bgr565: { /* * // BGR -> BGR * int offset = 0; * for (int y = 0; y < levelHeight; y++) * { * for (int x = 0; x < levelWidth; x++) * { * ushort pixel = BitConverter.ToUInt16(levelData, offset); * pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12)); * levelData[offset] = (byte)(pixel); * levelData[offset + 1] = (byte)(pixel >> 8); * offset += 2; * } * } */ } break; case SurfaceFormat.Bgra4444: { // Shift the channels to suit GLES int offset = 0; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { ushort pixel = BitConverter.ToUInt16(levelData, offset); pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12)); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } } break; case SurfaceFormat.NormalizedByte4: { int bytesPerPixel = surfaceFormat.Size(); int pitch = levelWidth * bytesPerPixel; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { int color = BitConverter.ToInt32(levelData, y * pitch + x * bytesPerPixel); levelData[y * pitch + x * 4] = (byte)(((color >> 16) & 0xff)); //R:=W levelData[y * pitch + x * 4 + 1] = (byte)(((color >> 8) & 0xff)); //G:=V levelData[y * pitch + x * 4 + 2] = (byte)(((color) & 0xff)); //B:=U levelData[y * pitch + x * 4 + 3] = (byte)(((color >> 24) & 0xff)); //A:=Q } } } break; } texture.SetData(level, null, levelData, 0, levelData.Length); } return(texture); }