Example #1
0
        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);
            }
        }
Example #2
0
        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;
        }