public UVRT(Stream stream) { using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, true)) { string magic = reader.ReadFixedString(4); if (magic != UVRT_MAGIC) { throw new Exception("Incorrect UVRT magic \"" + magic + "\"."); } uint dataSize = reader.ReadUInt32(); this.Format = (PixelFormat)reader.ReadByte(); this.Type = (ImageType)reader.ReadByte(); reader.BaseStream.Seek(2, SeekOrigin.Current); // Padding; always 0. this.Width = reader.ReadUInt16(); this.Height = reader.ReadUInt16(); if (this.Type.IsIndexed()) { this.Palette = reader.ReadBytes(this.Format.GetSize() * (1 << this.Type.GetIndexBits())); } else { this.Palette = new byte[0]; } int pixelDataSize = (int)(dataSize - 8 - this.Palette.Length); int imgSize = pixelDataSize; this.MipLevels = 0; if (this.Type.HasMipmaps()) { // Save number of mipmaps but discard data. imgSize = this.Width * this.Height * this.Format.GetSize(); int pos = imgSize; while (pos < pixelDataSize) { int mipWidth = this.Width >> (this.MipLevels + 1); int mipHeight = this.Height >> (this.MipLevels + 1); int mipSize = mipWidth * mipHeight * this.Format.GetSize(); if (mipWidth == 0 || mipHeight == 0 || pixelDataSize < pos + mipSize) { break; } pos += mipSize; this.MipLevels++; } } this.Data = reader.ReadBytes(imgSize); } }
public UVRT(Bitmap bitmap, PixelFormat pixelFormat, ImageType imageType, int mipLevels, byte[] palette = null) { if (!IsPow2(bitmap.Width) || !IsPow2(bitmap.Height)) { throw new Exception("Width and height must be powers of two."); } if (imageType.IsIndexed()) { byte indexBits = imageType.GetIndexBits(); byte[] indices; Color[] colorPalette; if (palette != null) { indices = new byte[bitmap.Width * bitmap.Height]; colorPalette = BitmapUtil.PaletteToColors(palette, pixelFormat); for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { int index = BitmapUtil.GetClosestColorIndex(bitmap.GetPixel(x, y), colorPalette, pixelFormat != PixelFormat.RGB565); if (index == -1) { throw new Exception("Could not find a palette entry for pixel (" + x + ", " + y + ")."); } indices[y * bitmap.Width + x] = (byte)(index & 0xFF); } } } else { BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); byte[] argbData = new byte[data.Stride * bitmap.Height]; Marshal.Copy(data.Scan0, argbData, 0, argbData.Length); bitmap.UnlockBits(data); WuAlphaColorQuantizer quantizer = new WuAlphaColorQuantizer(); ColorQuantizerResult result = quantizer.Quantize(argbData, 1 << indexBits); indices = result.Bytes; colorPalette = new Color[1 << indexBits]; for (int i = 0; i < result.Palette.Length / 4; i++) { colorPalette[i] = Color.FromArgb(result.Palette[i * 4 + 3], result.Palette[i * 4 + 2], result.Palette[i * 4 + 1], result.Palette[i * 4 + 0]); } } byte[] converted = new byte[bitmap.Width * bitmap.Height * indexBits / 8]; for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { int dataIndex = y * bitmap.Width + x; int index = indices[dataIndex]; if (indexBits == 4) { int shift = (dataIndex & 1) * 4; converted[dataIndex / 2] = (byte)((converted[dataIndex / 2] & ~(0xF << shift)) | ((index & 0xF) << shift)); } else { converted[dataIndex] = (byte)(index & 0xFF); } } } this.Data = BitmapUtil.Swizzle(converted, (bitmap.Width * imageType.GetIndexBits()) / 8, bitmap.Height, (bitmap.Width * imageType.GetIndexBits()) / 8, bitmap.Height); this.Palette = BitmapUtil.ColorsToPalette(colorPalette, pixelFormat); } else { if (pixelFormat == PixelFormat.DXT1A || pixelFormat == PixelFormat.DXT1A_EXT) { this.Data = BitmapUtil.CompressDxt1(bitmap.Width, bitmap.Height, pixelFormat == PixelFormat.DXT1A_EXT, bitmap); } else { int pixelSize = pixelFormat.GetSize(); byte[] converted = new byte[bitmap.Width * bitmap.Height * pixelSize]; for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { int pixel = pixelFormat.FromColor(bitmap.GetPixel(x, y)); for (int j = 0; j < pixelSize; j++) { converted[(y * bitmap.Width + x) * pixelSize + j] = (byte)((pixel >> (j * 8)) & 0xFF); } } } this.Data = BitmapUtil.Swizzle(converted, bitmap.Width * pixelSize, bitmap.Height, bitmap.Width * pixelSize, bitmap.Height); } this.Palette = new byte[0]; } this.Format = pixelFormat; this.Type = imageType; this.Width = (ushort)bitmap.Width; this.Height = (ushort)bitmap.Height; this.MipLevels = mipLevels; }