public override Resource LoadResource(string name) { if (!MatchExtension(name)) { return(null); } using (var stream = FileSystem.GetFile(name)) { if (stream == null) { return(null); } byte[] newData; Pfim.IImage image = Pfim.Pfim.FromStream(stream); if (image.Compressed) { image.Decompress(); } var tightStride = image.Width * image.BitsPerPixel / 8; if (image.Stride != tightStride) { newData = new byte[image.Height * tightStride]; for (int i = 0; i < image.Height; i++) { System.Buffer.BlockCopy(image.Data, i * image.Stride, newData, i * tightStride, tightStride); } } else { newData = image.Data; } MipmapLevel[] mipmaps = new MipmapLevel[image.MipMaps.Length + 1]; mipmaps[0] = new MipmapLevel((uint)image.DataLen, newData.AsSpan(0, image.DataLen).ToArray(), (uint)image.Width, (uint)image.Height, 1); for (int i = 1; i < mipmaps.Length; i++) { var mip = image.MipMaps[i - 1]; uint imageSize = (uint)mip.DataLen; mipmaps[i] = new MipmapLevel(imageSize, newData.AsSpan(mip.DataOffset, mip.DataLen).ToArray(), (uint)mip.Width, (uint)mip.Height, 1); } VkFormat fmt = VkFormat.R8G8B8A8UNorm; switch (image.Format) { case Pfim.ImageFormat.Rgb8: fmt = VkFormat.R4G4UNormPack8; break; case Pfim.ImageFormat.R5g5b5: //fmt = VkFormat.R5g5b5UnormPack16; break; case Pfim.ImageFormat.R5g6b5: fmt = VkFormat.R5G6B5UNormPack16; break; case Pfim.ImageFormat.R5g5b5a1: fmt = VkFormat.R5G5B5A1UNormPack16; break; case Pfim.ImageFormat.Rgba16: fmt = VkFormat.R4G4B4A4UNormPack16; break; case Pfim.ImageFormat.Rgb24: fmt = VkFormat.R8G8B8UNorm; break; case Pfim.ImageFormat.Rgba32: fmt = VkFormat.B8G8R8A8UNorm; break; } Texture tex = new Texture { extent = new VkExtent3D((uint)image.Width, (uint)image.Height, 1), mipLevels = (uint)mipmaps.Length, format = fmt, imageUsageFlags = VkImageUsageFlags.Sampled, imageLayout = VkImageLayout.ShaderReadOnlyOptimal, }; tex.SetImageData(mipmaps); return(tex); } }
public static KtxFile Load(File file, bool readKeyValuePairs) { KtxHeader header = ReadStruct <KtxHeader>(file); KtxKeyValuePair[] kvps = null; if (readKeyValuePairs) { int keyValuePairBytesRead = 0; List <KtxKeyValuePair> keyValuePairs = new List <KtxKeyValuePair>(); while (keyValuePairBytesRead < header.BytesOfKeyValueData) { int bytesRemaining = (int)(header.BytesOfKeyValueData - keyValuePairBytesRead); KtxKeyValuePair kvp = ReadNextKeyValuePair(file, out int read); keyValuePairBytesRead += read; keyValuePairs.Add(kvp); } kvps = keyValuePairs.ToArray(); } else { file.Skip((int)header.BytesOfKeyValueData); // Skip over header data. } uint numberOfMipmapLevels = Math.Max(1, header.NumberOfMipmapLevels); uint numberOfArrayElements = Math.Max(1, header.NumberOfArrayElements); uint numberOfFaces = Math.Max(1, header.NumberOfFaces); uint baseWidth = Math.Max(1, header.PixelWidth); uint baseHeight = Math.Max(1, header.PixelHeight); uint baseDepth = Math.Max(1, header.PixelDepth); List <uint> imageSizes = new List <uint>(); MipmapLevel[] images = new MipmapLevel[numberOfMipmapLevels]; long dataSize = file.Length - file.Position; uint totalSize = 0; for (int mip = 0; mip < numberOfMipmapLevels; mip++) { uint mipWidth = Math.Max(1, baseWidth / (uint)(Math.Pow(2, mip))); uint mipHeight = Math.Max(1, baseHeight / (uint)(Math.Pow(2, mip))); uint mipDepth = Math.Max(1, baseDepth / (uint)(Math.Pow(2, mip))); uint imageSize = file.Read <uint>(); if (mip == 11) { //bug? imageSize = Math.Min(imageSizes.Back() >> 2, imageSize); //imageSize = 1; } imageSizes.Add(imageSize); ArrayElement[] arrayElements = new ArrayElement[numberOfArrayElements]; bool isCubemap = header.NumberOfFaces == 6 && header.NumberOfArrayElements == 0; uint arrayElementSize = imageSize / numberOfArrayElements; for (int arr = 0; arr < numberOfArrayElements; arr++) { uint faceSize = arrayElementSize; ImageFace[] faces = new ImageFace[numberOfFaces]; for (int face = 0; face < numberOfFaces; face++) { faces[face] = new ImageFace(file.ReadBytes((int)faceSize)); uint cubePadding = 0u; if (isCubemap) { cubePadding = 3 - ((imageSize + 3) % 4); } file.Skip((int)cubePadding); totalSize += faceSize; } arrayElements[arr] = new ArrayElement(faces); } images[mip] = new MipmapLevel( mipWidth, mipHeight, mipDepth, imageSize, arrayElements, header.NumberOfArrayElements); uint mipPaddingBytes = 3 - ((imageSize + 3) % 4); //Debug.Assert(mipPaddingBytes == 0); file.Skip((int)mipPaddingBytes); } //Debug.Assert(dataSize == numberOfMipmapLevels * 4 + totalSize); return(new KtxFile(header, kvps, images)); }