private static uint ComputeImageBufferSize(uint width, uint height, uint depth, uint mipmaps, VTFImageFormat imageFormat) { uint uiImageSize = 0, tempWidth = width, tempHeight = height; if (tempWidth > 0 && tempHeight > 0 && depth > 0) { for (int i = 0; i < mipmaps; i++) { uiImageSize += ComputeImageBufferSize(tempWidth, tempHeight, depth, imageFormat); tempWidth >>= 1; tempHeight >>= 1; depth >>= 1; if (tempWidth < 1) { tempWidth = 1; } if (tempHeight < 1) { tempHeight = 1; } if (depth < 1) { depth = 1; } } } return(uiImageSize); }
private static uint ComputeMipmapSize(uint width, uint height, uint depth, uint mipmapLevel, VTFImageFormat ImageFormat) { // figure out the width/height of this MIP level uint uiMipmapWidth, uiMipmapHeight, uiMipmapDepth; ComputeMipmapDimensions(width, height, depth, mipmapLevel, out uiMipmapWidth, out uiMipmapHeight, out uiMipmapDepth); // return the memory requirements return(ComputeImageBufferSize(uiMipmapWidth, uiMipmapHeight, uiMipmapDepth, ImageFormat)); }
private static Color[] DecompressImage(Stream data, ushort width, ushort height, VTFImageFormat imageFormat) { Color[] vtfColors = new Color[width * height]; Texture2DHelpers.TextureFormat format; if (imageFormat == VTFImageFormat.IMAGE_FORMAT_DXT1 || imageFormat == VTFImageFormat.IMAGE_FORMAT_DXT1_ONEBITALPHA) { format = Texture2DHelpers.TextureFormat.DXT1; } else if (imageFormat == VTFImageFormat.IMAGE_FORMAT_DXT3) { format = Texture2DHelpers.TextureFormat.DXT3; } else if (imageFormat == VTFImageFormat.IMAGE_FORMAT_DXT5) { format = Texture2DHelpers.TextureFormat.DXT5; } else if (imageFormat == VTFImageFormat.IMAGE_FORMAT_BGR888) { format = Texture2DHelpers.TextureFormat.BGR888; } else if (imageFormat == VTFImageFormat.IMAGE_FORMAT_BGRA8888) { format = Texture2DHelpers.TextureFormat.BGRA8888; } else { format = Texture2DHelpers.TextureFormat.BGR888; Debug.LogError("SourceTexture: Unsupported format " + imageFormat + ", will read as " + format); } vtfColors = Texture2DHelpers.DecompressRawBytes(data, width, height, format); Texture2DHelpers.FlipVertical(vtfColors, width, height); return(vtfColors); }
private static uint ComputeImageBufferSize(uint width, uint height, uint depth, VTFImageFormat imageFormat) { uint tempWidth = width, tempHeight = height; if (imageFormat == VTFImageFormat.IMAGE_FORMAT_DXT1 || imageFormat == VTFImageFormat.IMAGE_FORMAT_DXT1_ONEBITALPHA) { if (tempWidth < 4 && tempWidth > 0) { tempWidth = 4; } if (tempHeight < 4 && tempHeight > 0) { tempHeight = 4; } return(((tempWidth + 3) / 4) * ((tempHeight + 3) / 4) * 8 * depth); } else if (imageFormat == VTFImageFormat.IMAGE_FORMAT_DXT3 || imageFormat == VTFImageFormat.IMAGE_FORMAT_DXT5) { if (tempWidth < 4 && tempWidth > 0) { tempWidth = 4; } if (tempHeight < 4 && tempHeight > 0) { tempHeight = 4; } return(((tempWidth + 3) / 4) * ((tempHeight + 3) / 4) * 16 * depth); } else { return((uint)(tempWidth * tempHeight * depth * VTFImageConvertInfo[(int)imageFormat, (int)VTFImageConvertInfoIndex.bytesPerPixel])); } }
public void UnSerialize(IOReader reader) { // Make sure we are reading big endian reader.ByteOrder = Endian.Big; this.Flags = (VTFFlags)reader.ReadInt(); this.Width = reader.ReadUShort(); this.Height = reader.ReadUShort(); this.Depth = reader.ReadUShort(); this.NumFrames = reader.ReadUShort(); this.PreloadSize = reader.ReadUShort(); this.MipSkipCount = reader.ReadByte(); this.NumResources = reader.ReadByte(); this.Reflectivity.UnSerialize(reader); this.BumpScale = reader.ReadFloat(); this.ImageFormat = (VTFImageFormat)reader.ReadInt(); this.LowResImgSmple = reader.ReadBytes(4); this.CompressedSize = reader.ReadUInt(); }
//http://wiki.xentax.com/index.php/Source_VTF /// <summary> /// Parser VTF format /// <br>Supported versions: 7.1 - 7.5 (maybe 7.0)</br> /// </summary> /// <param name="stream">Stream of input file</param> /// <param name="FileName">Name of input file (optional)</param> public VTFFile(Stream stream, String FileName = "") { using (uReader FileStream = new uReader(stream)) { String TempHeader = FileStream.ReadFixedLengthString(Encoding.ASCII, 4); if (TempHeader != VTFHeader) { throw new Exception("Invalid VTF header. Expected '" + VTFHeader + "', got '" + TempHeader + "'."); } Header = new VTFHeader(); UInt32 VersionMajor = FileStream.ReadUInt32(); UInt32 VersionMinor = FileStream.ReadUInt32(); Decimal Version = VersionMajor + (VersionMinor / 10m); // e.g. 7.3 Header.Version = Version; UInt32 headerSize = FileStream.ReadUInt32(); Width = FileStream.ReadUInt16(); Height = FileStream.ReadUInt16(); Header.Flags = (VTFImageFlag)FileStream.ReadUInt32(); UInt16 NumFrames = FileStream.ReadUInt16(); UInt16 FirstFrame = FileStream.ReadUInt16(); FileStream.ReadBytes(4); // padding Header.Reflectivity = FileStream.ReadVector3D(false); FileStream.ReadBytes(4); // padding Header.BumpmapScale = FileStream.ReadSingle(); VTFImageFormat HighResImageFormat = (VTFImageFormat)FileStream.ReadUInt32(); Byte MipmapCount = FileStream.ReadByte(); VTFImageFormat LowResImageFormat = (VTFImageFormat)FileStream.ReadUInt32(); Byte LowResWidth = FileStream.ReadByte(); Byte LowResHeight = FileStream.ReadByte(); UInt16 Depth = 1; UInt32 NumResources = 0; if (Version >= 7.2m) { Depth = FileStream.ReadUInt16(); } if (Version >= 7.3m) { FileStream.ReadBytes(3); NumResources = FileStream.ReadUInt32(); FileStream.ReadBytes(8); } Int32 NumFaces = 1; if (Header.Flags.HasFlag(VTFImageFlag.TEXTUREFLAGS_ENVMAP)) { NumFaces = Version < 7.5m && FirstFrame != 0xFFFF ? 7 : 6; } VTFImageFormatInfo HighResFormatInfo = VTFImageFormatInfo.FromFormat(HighResImageFormat); VTFImageFormatInfo LowResFormatInfo = VTFImageFormatInfo.FromFormat(LowResImageFormat); Int32 ThumbnailSize = LowResImageFormat == VTFImageFormat.IMAGE_FORMAT_NONE ? 0 : LowResFormatInfo.GetSize(LowResWidth, LowResHeight); UInt32 ThumbnailOffset = headerSize; Int64 DataOffset = headerSize + ThumbnailSize; Resources = new VTFResource[NumResources]; for (Int32 i = 0; i < NumResources; i++) { VTFResourceType type = (VTFResourceType)FileStream.ReadUInt32(); UInt32 DataSize = FileStream.ReadUInt32(); switch (type) { case VTFResourceType.LowResImage: // Low res image ThumbnailOffset = DataSize; break; case VTFResourceType.Image: // Regular image DataOffset = DataSize; break; case VTFResourceType.Sheet: case VTFResourceType.CRC: case VTFResourceType.TextureLodSettings: case VTFResourceType.TextureSettingsEx: case VTFResourceType.KeyValueData: // todo Resources[i] = new VTFResource { Type = type, Data = DataSize }; break; default: throw new ArgumentOutOfRangeException(nameof(type), (uint)type, "Unknown resource type"); } } if (LowResImageFormat != VTFImageFormat.IMAGE_FORMAT_NONE) { FileStream.BaseStream.Position = ThumbnailOffset; Int32 thumbSize = LowResFormatInfo.GetSize(LowResWidth, LowResHeight); LowResImage = new VTFImage { Format = LowResImageFormat, Width = LowResWidth, Height = LowResHeight, Data = FileStream.ReadBytes(thumbSize) }; } Boolean ConvertToBGRA32 = true; Boolean hasAlpha = true; switch (HighResImageFormat) { //Unity support this formats natively case VTFImageFormat.IMAGE_FORMAT_A8: case VTFImageFormat.IMAGE_FORMAT_ABGR8888: case VTFImageFormat.IMAGE_FORMAT_ARGB8888: case VTFImageFormat.IMAGE_FORMAT_BGRA4444: case VTFImageFormat.IMAGE_FORMAT_DXT1_ONEBITALPHA: case VTFImageFormat.IMAGE_FORMAT_DXT3: case VTFImageFormat.IMAGE_FORMAT_DXT5: case VTFImageFormat.IMAGE_FORMAT_RGBA8888: case VTFImageFormat.IMAGE_FORMAT_BGRA8888: case VTFImageFormat.IMAGE_FORMAT_BGRX8888: case VTFImageFormat.IMAGE_FORMAT_RGBA16161616F: case VTFImageFormat.IMAGE_FORMAT_RGBA16161616: ConvertToBGRA32 = false; break; case VTFImageFormat.IMAGE_FORMAT_BGR565: case VTFImageFormat.IMAGE_FORMAT_RGB565: case VTFImageFormat.IMAGE_FORMAT_DXT1: case VTFImageFormat.IMAGE_FORMAT_RGB888: hasAlpha = false; ConvertToBGRA32 = false; break; } FileStream.BaseStream.Position = DataOffset; Frames = new Texture2D[NumFrames, NumFaces]; List <Byte>[] FramesData = new List <Byte> [NumFrames]; for (Int32 MipLevel = MipmapCount - 1; MipLevel >= 0; MipLevel--) { for (Int32 FrameID = 0; FrameID < NumFrames; FrameID++) { if (FramesData[FrameID] == null) { FramesData[FrameID] = new List <Byte>(); } for (Int32 FaceID = 0; FaceID < NumFaces; FaceID++) { for (Int32 SliceID = 0; SliceID < Depth; SliceID++) { Int32 Wid = GetMipSize(Width, MipLevel); Int32 Hei = GetMipSize(Height, MipLevel); Int32 DataSize = HighResFormatInfo.GetSize(Wid, Hei); if (ConvertToBGRA32) { FramesData[FrameID].InsertRange(0, VTFImageFormatInfo.FromFormat(HighResImageFormat).ConvertToBgra32(FileStream.ReadBytes(DataSize), Wid, Hei)); } else { FramesData[FrameID].InsertRange(0, FileStream.ReadBytes(DataSize)); } } } } } TextureFormat InternalFormat = TextureFormat.BGRA32; Boolean needCompress = false; switch (HighResImageFormat) { case VTFImageFormat.IMAGE_FORMAT_A8: InternalFormat = TextureFormat.Alpha8; break; case VTFImageFormat.IMAGE_FORMAT_ABGR8888: case VTFImageFormat.IMAGE_FORMAT_ARGB8888: InternalFormat = TextureFormat.ARGB32; break; case VTFImageFormat.IMAGE_FORMAT_BGR565: case VTFImageFormat.IMAGE_FORMAT_RGB565: InternalFormat = TextureFormat.RGB565; break; case VTFImageFormat.IMAGE_FORMAT_BGRA4444: InternalFormat = TextureFormat.RGBA4444; break; case VTFImageFormat.IMAGE_FORMAT_DXT1: case VTFImageFormat.IMAGE_FORMAT_DXT1_ONEBITALPHA: InternalFormat = TextureFormat.DXT1; break; case VTFImageFormat.IMAGE_FORMAT_DXT3: case VTFImageFormat.IMAGE_FORMAT_DXT5: InternalFormat = TextureFormat.DXT5; break; case VTFImageFormat.IMAGE_FORMAT_RGB888: InternalFormat = TextureFormat.RGB24; break; case VTFImageFormat.IMAGE_FORMAT_RGBA8888: InternalFormat = TextureFormat.RGBA32; break; case VTFImageFormat.IMAGE_FORMAT_RGBA16161616F: case VTFImageFormat.IMAGE_FORMAT_RGBA16161616: InternalFormat = TextureFormat.RGBAHalf; break; default: //needCompress = true; break; } Boolean mipmaps = MipmapCount > 1; for (Int32 FrameID = 0; FrameID < NumFrames; FrameID++) { for (Int32 FaceID = 0; FaceID < NumFaces; FaceID++) { Frames[FrameID, FaceID] = new Texture2D(Width, Height, InternalFormat, mipmaps); Frames[FrameID, FaceID].name = FileName; Frames[FrameID, FaceID].alphaIsTransparency = hasAlpha; Frames[FrameID, FaceID].LoadRawTextureData(FramesData[FrameID].ToArray()); Frames[FrameID, FaceID].Apply(); if (needCompress) { Frames[FrameID, FaceID].Compress(false); Debug.LogWarning(FileName + " compressed!"); } } } } }
private void UnSerialize(Stream input) { m_vtfReader = new IOReader(input); int ident = this.m_vtfReader.ReadInt(); if (ident == "VTF\0".MakeID()) this.m_bIs360 = false; else if (ident == "VTFX".MakeID()) { this.m_bIs360 = true; this.m_vtfReader.ByteOrder = Endian.Big; } else throw new BadImageFormatException(); // rewind stream m_vtfReader.Seek(-4); VTFFileHeader vtfHDR = new VTFFileHeader(); vtfHDR.UnSerialize(this.m_vtfReader); this.m_dwVersionMajor = (int)vtfHDR.VersionMajor; this.m_dwVersionMinor = (int)vtfHDR.VersionMinor; VTFHeader_PC hdr = new VTFHeader_PC(); hdr.UnSerialize(this.m_vtfReader); this.m_dwResourceCount = (int)hdr.NumResources; this.m_dwHeight = hdr.Height; this.m_dwWidth = hdr.Width; this.m_Format = hdr.ImageFormat; this.m_dwFlags = hdr.Flags; this.m_dwFrameCount = hdr.NumFrames; this.m_dwDepth = hdr.Depth; // Envmaps only have 1 face, if its not then it must be a cubemap with 7 sides if (m_dwFlags.IsFlagSet<VTFFlags>(VTFFlags.TEXTUREFLAGS_ENVMAP)) this.m_dwFaceCount = 1; else this.m_dwFaceCount = 7; this.m_vecReflectivity = hdr.Reflectivity; this.m_flBumpScale = hdr.BumpScale; this.m_dwLowResImageWidth = hdr.LowResImgWidth; this.m_dwLowResImageHeight = hdr.LowResImgHeight; this.m_LowResImageFormat = hdr.LowResImgFmt; this.m_dwMipCount = ComputeMipCount(); }
public void UnSerialize(IOReader reader) { this.Width = reader.ReadUShort(); this.Height = reader.ReadUShort(); this.Flags = (VTFFlags)reader.ReadInt(); this.NumFrames = reader.ReadUShort(); this.StartFrame = reader.ReadUShort(); this.Reflectivity.UnSerialize(reader); this.BumpScale = reader.ReadFloat(); this.ImageFormat = (VTFImageFormat)reader.ReadInt(); this.NumMipLevels = reader.ReadByte(); this.LowResImgFmt = (VTFImageFormat)reader.ReadInt(); this.LowResImgWidth = reader.ReadByte(); this.LowResImgHeight = reader.ReadByte(); }
private int ComputeImageSize(int width, int height, int depth, int mipMaps, VTFImageFormat imgFmt) { int imgSize = 0; for (int i = 0; i < mipMaps; i++) { imgSize += ComputeImageSize(width, height, depth, mipMaps, imgFmt); width >>= 1; height >>= 1; depth >>= 1; if (width < 1) width = 1; if (height < 1) height = 1; if (depth < 1) depth = 1; } return imgSize; }
private VTFImageFormatInfo_t GetImageFormatInfo(VTFImageFormat fmt) { return VTFImageFormatInfo[(int)fmt]; }
/// <summary> /// Computes image size from a format /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <param name="depth"></param> /// <param name="fmt"></param> /// <returns>size in bytes</returns> private int ComputeFormatSize(int width, int height, int depth, VTFImageFormat fmt) { switch (fmt) { case(VTFImageFormat.IMAGE_FORMAT_DXT1): case(VTFImageFormat.IMAGE_FORMAT_DXT1_ONEBITALPHA): if (width < 4 && width > 0) width = 4; if (height < 4 && height > 0) height = 4; return ((width + 3) / 4) * ((height + 3) / 4) * 8 * depth; case(VTFImageFormat.IMAGE_FORMAT_DXT3): case (VTFImageFormat.IMAGE_FORMAT_DXT5): if (width < 4 && width > 0) width = 4; if (height < 4 && height > 0) height = 4; return ((width + 3) / 4) * ((height + 3) / 4) * 16 * depth; default: return width * height * depth * GetImageFormatInfo(fmt).bytesPerPixle; } }
static uint ComputeImageSize(int width, int height, int mipmaps, uint frames, VTFImageFormat imageFormat) { uint imageSize = 0; for (uint i = 0; i < mipmaps; i++) { imageSize += ComputeImageSize(width, height, imageFormat); width >>= 1; height >>= 1; if (width < 1) { width = 1; } if (height < 1) { height = 1; } } imageSize *= frames; return(imageSize); }
/*Texture2D CreateThumbnailTexture(string name, vtfheader header) * { * Texture2D temp; * if (header.lowResImageFormat == VTFImageFormat.IMAGE_FORMAT_DXT5) * { * temp=new Texture2D((int)header.lowResImageWidth, (int)header.lowResImageHeight, TextureFormat.DXT5,false); * temp.LoadRawTextureData(ThumbnailImageData); * temp.Apply(); * temp.filterMode=FilterMode.Point; * temp.name=name; * //Debug.Log("Texture loaded "+header.lowResImageWidth+"x"+header.lowResImageHeight); * return temp; * } * if (header.lowResImageFormat == VTFImageFormat.IMAGE_FORMAT_DXT1) * { * temp=new Texture2D((int)header.lowResImageWidth, (int)header.lowResImageHeight, TextureFormat.DXT1, false); * temp.LoadRawTextureData(ThumbnailImageData); * temp.Apply(); * temp.filterMode=FilterMode.Point; * temp.name=name; * //Debug.Log("Texture loaded "+header.lowResImageWidth+"x"+header.lowResImageHeight); * return temp; * } * return null; * }*/ static uint ComputeImageSize(int Width, int Height, VTFImageFormat imageFormat) { switch (imageFormat) { case VTFImageFormat.IMAGE_FORMAT_DXT1: case VTFImageFormat.IMAGE_FORMAT_DXT1_ONEBITALPHA: if (Width < 4 && Width > 0) { Width = 4; } if (Height < 4 && Height > 0) { Height = 4; } return((((uint)Width + 3) / 4) * (((uint)Height + 3) / 4) * 8); //return (uint)Width * (uint)Height * 1; case VTFImageFormat.IMAGE_FORMAT_DXT3: case VTFImageFormat.IMAGE_FORMAT_DXT5: if (Width < 4 && Width > 0) { Width = 4; } if (Height < 4 && Height > 0) { Height = 4; } return((((uint)Width + 3) / 4) * (((uint)Height + 3) / 4) * 16); case VTFImageFormat.IMAGE_FORMAT_ABGR8888: case VTFImageFormat.IMAGE_FORMAT_ARGB8888: case VTFImageFormat.IMAGE_FORMAT_RGBA8888: case VTFImageFormat.IMAGE_FORMAT_BGRA8888: case VTFImageFormat.IMAGE_FORMAT_BGRX8888: case VTFImageFormat.IMAGE_FORMAT_UVWQ8888: case VTFImageFormat.IMAGE_FORMAT_UVLX8888: case VTFImageFormat.IMAGE_FORMAT_R32F: case VTFImageFormat.IMAGE_FORMAT_NV_INTZ: case VTFImageFormat.IMAGE_FORMAT_NV_RAWZ: case VTFImageFormat.IMAGE_FORMAT_NV_NULL: return((uint)Width * (uint)Height * 4); case VTFImageFormat.IMAGE_FORMAT_RGB888: case VTFImageFormat.IMAGE_FORMAT_BGR888: case VTFImageFormat.IMAGE_FORMAT_RGB888_BLUESCREEN: case VTFImageFormat.IMAGE_FORMAT_BGR888_BLUESCREEN: case VTFImageFormat.IMAGE_FORMAT_NV_DST24: return((uint)Width * (uint)Height * 3); case VTFImageFormat.IMAGE_FORMAT_RGB565: case VTFImageFormat.IMAGE_FORMAT_IA88: case VTFImageFormat.IMAGE_FORMAT_BGR565: case VTFImageFormat.IMAGE_FORMAT_BGRX5551: case VTFImageFormat.IMAGE_FORMAT_BGRA4444: case VTFImageFormat.IMAGE_FORMAT_BGRA5551: case VTFImageFormat.IMAGE_FORMAT_UV88: case VTFImageFormat.IMAGE_FORMAT_NV_DST16: case VTFImageFormat.IMAGE_FORMAT_ATI_DST16: return((uint)Width * (uint)Height * 2); default: return((uint)Width * (uint)Height * 1); //GetImageFormatInfo(imageFormat).BytesPerPixel; } }
private VTFImageFormatInfo( VTFImageFormat format, Int32 bitsPerPixel, Int32 bytesPerPixel, Int32 redBitsPerPixel, Int32 greenBitsPerPixel, Int32 blueBitsPerPixel, Int32 alphaBitsPerPixel, Int32 redIndex, Int32 greenIndex, Int32 blueIndex, Int32 alphaIndex, Boolean isCompressed, Boolean isSupported, TransformPixel pixelTransform = null ) { Format = format; BitsPerPixel = bitsPerPixel; BytesPerPixel = bytesPerPixel; RedBitsPerPixel = redBitsPerPixel; GreenBitsPerPixel = greenBitsPerPixel; BlueBitsPerPixel = blueBitsPerPixel; AlphaBitsPerPixel = alphaBitsPerPixel; RedIndex = redIndex; GreenIndex = greenIndex; BlueIndex = blueIndex; AlphaIndex = alphaIndex; IsCompressed = isCompressed; IsSupported = isSupported; _pixelTransform = pixelTransform; _is8Aligned = (redBitsPerPixel == 0 || redBitsPerPixel == 8) && (greenBitsPerPixel == 0 || greenBitsPerPixel == 8) && (blueBitsPerPixel == 0 || blueBitsPerPixel == 8) && (alphaBitsPerPixel == 0 || alphaBitsPerPixel == 8); _is16Aligned = (redBitsPerPixel == 0 || redBitsPerPixel == 16) && (greenBitsPerPixel == 0 || greenBitsPerPixel == 16) && (blueBitsPerPixel == 0 || blueBitsPerPixel == 16) && (alphaBitsPerPixel == 0 || alphaBitsPerPixel == 16); _is32Aligned = (redBitsPerPixel == 0 || redBitsPerPixel == 32) && (greenBitsPerPixel == 0 || greenBitsPerPixel == 32) && (blueBitsPerPixel == 0 || blueBitsPerPixel == 32) && (alphaBitsPerPixel == 0 || alphaBitsPerPixel == 32); if (!_is8Aligned && !_is16Aligned && !_is32Aligned) { var masks = new[] { new Mask('r', redBitsPerPixel, redIndex), new Mask('g', greenBitsPerPixel, greenIndex), new Mask('b', blueBitsPerPixel, blueIndex), new Mask('a', alphaBitsPerPixel, alphaIndex), }.OrderBy(x => x.Index).ToList(); var offset = bitsPerPixel; foreach (var m in masks) { offset -= m.Size; m.Offset = offset; } var dict = masks.ToDictionary(x => x.Component, x => x); _masks = new[] { dict['b'], dict['g'], dict['r'], dict['a'] }; } }
public static VTFImageFormatInfo FromFormat(VTFImageFormat imageFormat) => ImageFormats[imageFormat];