Example #1
0
        protected override void _Read(BinaryReader reader)
        {
            long baseOffset = reader.BaseStream.Position;

            byte[] buffer = reader.ReadBytes((int)reader.BaseStream.Length);

            MemoryStream memoryStream = new MemoryStream(buffer, 0, buffer.Length, true, true);
            DDS_Header   header       = new DDS_Header(memoryStream);

            FormatDetails = new DDSFormatDetails(header.Format, header.DX10_DXGI_AdditionalHeader.dxgiFormat);
            MipMaps       = DDSGeneral.LoadDDS(memoryStream, header, 0, FormatDetails);
            Width         = header.Width;
            Height        = header.Height;
            memoryStream.Close();
        }
Example #2
0
        internal static List <MipMap> LoadImage(byte[] rawDDSData, ImageEngineFormat surfaceFormat, int width, int height, out DDSGeneral.DDS_HEADER header)
        {
            header = DDSGeneral.Build_DDS_Header(1, height, width, surfaceFormat);
            List <MipMap> MipMaps = null;

            // Create new fully formatted DDS i.e. one with a header.
            MemoryStream stream = new MemoryStream();
            BinaryWriter bw     = new BinaryWriter(stream);

            DDSGeneral.Write_DDS_Header(header, bw);
            bw.Write(rawDDSData);

            switch (surfaceFormat)
            {
            case ImageEngineFormat.DDS_DXT1:
            case ImageEngineFormat.DDS_DXT2:
            case ImageEngineFormat.DDS_DXT3:
            case ImageEngineFormat.DDS_DXT4:
            case ImageEngineFormat.DDS_DXT5:
                if (WindowsWICCodecsAvailable)
                {
                    MipMaps = WIC_Codecs.LoadWithCodecs(stream, 0, 0, true);
                }
                else
                {
                    MipMaps = DDSGeneral.LoadDDS(stream, header, new Format(surfaceFormat), 0);
                }
                break;

            case ImageEngineFormat.DDS_ARGB:
            case ImageEngineFormat.DDS_A8L8:
            case ImageEngineFormat.DDS_RGB:
            case ImageEngineFormat.DDS_ATI1:
            case ImageEngineFormat.DDS_ATI2_3Dc:
            case ImageEngineFormat.DDS_G8_L8:
            case ImageEngineFormat.DDS_V8U8:
                MipMaps = DDSGeneral.LoadDDS(stream, header, new Format(surfaceFormat), 0);
                break;

            default:
                throw new InvalidDataException("Image format is unknown.");
            }
            bw.Dispose(); // Also disposes MemoryStream
            return(MipMaps);
        }
Example #3
0
        /// <summary>
        /// Loads image from stream.
        /// </summary>
        /// <param name="stream">Full image stream.</param>
        /// <param name="Format">Detected Format.</param>
        /// <param name="extension">File Extension. Used to determine format more easily.</param>
        /// <param name="maxWidth">Maximum width to allow when loading. Resized if enforceResize = true.</param>
        /// <param name="maxHeight">Maximum height to allow when loading. Resized if enforceResize = true.</param>
        /// <param name="enforceResize">True = Resizes image to match either maxWidth or maxHeight.</param>
        /// <param name="header">DDS header of image.</param>
        /// <param name="mergeAlpha">ONLY valid when enforceResize is true. True = Flattens alpha down, directly affecting RGB.</param>
        /// <returns>List of Mipmaps.</returns>
        internal static List <MipMap> LoadImage(Stream stream, out Format Format, string extension, int maxWidth, int maxHeight, bool enforceResize, out DDSGeneral.DDS_HEADER header, bool mergeAlpha)
        {
            // KFreon: See if image is built-in codec agnostic.
            header = null;
            Format = ImageFormats.ParseFormat(stream, extension, ref header);
            List <MipMap> MipMaps = null;

            switch (Format.SurfaceFormat)
            {
            case ImageEngineFormat.BMP:
            case ImageEngineFormat.JPG:
            case ImageEngineFormat.PNG:
                MipMaps = WIC_Codecs.LoadWithCodecs(stream, maxWidth, maxHeight, false);
                break;

            case ImageEngineFormat.DDS_DXT1:
            case ImageEngineFormat.DDS_DXT2:
            case ImageEngineFormat.DDS_DXT3:
            case ImageEngineFormat.DDS_DXT4:
            case ImageEngineFormat.DDS_DXT5:
                if (WindowsWICCodecsAvailable)
                {
                    MipMaps = WIC_Codecs.LoadWithCodecs(stream, maxWidth, maxHeight, true);
                }
                else
                {
                    MipMaps = DDSGeneral.LoadDDS(stream, header, Format, maxHeight > maxWidth ? maxHeight : maxWidth);
                }
                break;

            case ImageEngineFormat.DDS_ARGB:
            case ImageEngineFormat.DDS_A8L8:
            case ImageEngineFormat.DDS_RGB:
            case ImageEngineFormat.DDS_ATI1:
            case ImageEngineFormat.DDS_ATI2_3Dc:
            case ImageEngineFormat.DDS_G8_L8:
            case ImageEngineFormat.DDS_V8U8:
                MipMaps = DDSGeneral.LoadDDS(stream, header, Format, maxHeight > maxWidth ? maxHeight : maxWidth);
                break;

            case ImageEngineFormat.TGA:
                var             img    = new TargaImage(stream);
                byte[]          pixels = UsefulThings.WinForms.Imaging.GetPixelDataFromBitmap(img.Image);
                WriteableBitmap wbmp   = UsefulThings.WPF.Images.CreateWriteableBitmap(pixels, img.Image.Width, img.Image.Height);
                var             mip1   = new MipMap(wbmp);
                MipMaps = new List <MipMap>()
                {
                    mip1
                };
                img.Dispose();
                break;

            default:
                throw new InvalidDataException("Image format is unknown.");
            }

            if (MipMaps == null || MipMaps.Count == 0)
            {
                throw new InvalidDataException("No mipmaps loaded.");
            }


            // KFreon: No resizing requested
            if (maxHeight == 0 && maxWidth == 0)
            {
                return(MipMaps);
            }

            // KFreon: Test if we need to resize
            var top = MipMaps.First();

            if (top.Width == maxWidth || top.Height == maxHeight)
            {
                return(MipMaps);
            }

            int max = maxWidth > maxHeight ? maxWidth : maxHeight;

            // KFreon: Attempt to resize
            var sizedMips = MipMaps.Where(m => m.Width > m.Height ? m.Width <= max : m.Height <= max);

            if (sizedMips != null && sizedMips.Any())  // KFreon: If there's already a mip, return that.
            {
                MipMaps = sizedMips.ToList();
            }
            else if (enforceResize)
            {
                // Get top mip and clear others.
                var mip = MipMaps[0];
                MipMaps.Clear();
                MipMap output = null;

                int divisor = mip.Width > mip.Height ? mip.Width / max : mip.Height / max;

                output = Resize(mip, 1f / divisor, mergeAlpha);

                MipMaps.Add(output);
            }
            return(MipMaps);
        }
        internal static List <MipMap> LoadImage(Stream imageStream, AbstractHeader header, int maxDimension, double scale, ImageFormats.ImageEngineFormatDetails formatDetails)
        {
            imageStream.Seek(0, SeekOrigin.Begin);
            List <MipMap> MipMaps = null;

            int decodeWidth  = header.Width > header.Height ? maxDimension : 0;
            int decodeHeight = header.Width < header.Height ? maxDimension : 0;

            switch (header.Format)
            {
            case ImageEngineFormat.DDS_DXT1:
            case ImageEngineFormat.DDS_DXT2:
            case ImageEngineFormat.DDS_DXT3:
            case ImageEngineFormat.DDS_DXT4:
            case ImageEngineFormat.DDS_DXT5:
                MipMaps = WIC_Codecs.LoadWithCodecs(imageStream, decodeWidth, decodeHeight, scale, true, formatDetails);
                if (MipMaps == null)
                {
                    // Windows codecs unavailable/failed. Load with mine.
                    MipMaps = DDSGeneral.LoadDDS((MemoryStream)imageStream, (DDS_Header)header, maxDimension, formatDetails);
                }
                break;

            case ImageEngineFormat.DDS_G8_L8:
            case ImageEngineFormat.DDS_ARGB_4:
            case ImageEngineFormat.DDS_RGB_8:
            case ImageEngineFormat.DDS_V8U8:
            case ImageEngineFormat.DDS_A8L8:
            case ImageEngineFormat.DDS_ARGB_8:
            case ImageEngineFormat.DDS_ARGB_32F:
            case ImageEngineFormat.DDS_ABGR_8:
            case ImageEngineFormat.DDS_G16_R16:
            case ImageEngineFormat.DDS_R5G6B5:
            case ImageEngineFormat.DDS_ATI1:
            case ImageEngineFormat.DDS_ATI2_3Dc:
            case ImageEngineFormat.DDS_CUSTOM:
            case ImageEngineFormat.DDS_DX10:
                MipMaps = DDSGeneral.LoadDDS((MemoryStream)imageStream, (DDS_Header)header, maxDimension, formatDetails);
                break;

            case ImageEngineFormat.GIF:
            case ImageEngineFormat.JPG:
            case ImageEngineFormat.PNG:
            case ImageEngineFormat.BMP:
            case ImageEngineFormat.TIF:
                MipMaps = WIC_Codecs.LoadWithCodecs(imageStream, decodeWidth, decodeHeight, scale, false, formatDetails);
                break;

            case ImageEngineFormat.TGA:
                using (var tga = new TargaImage(imageStream, ((TGA_Header)header).header))
                    MipMaps = new List <MipMap>()
                    {
                        new MipMap(tga.ImageData, tga.Header.Width, tga.Header.Height, formatDetails)
                    };
                break;

            default:
                throw new FormatException($"Format unknown: {header.Format}.");
            }

            return(MipMaps);
        }
Example #5
0
        /// <summary>
        /// Internal read implementation of the sub classes.
        /// </summary>
        /// <param name="reader"></param>
        /// <exception cref="Exception">Expected DDS RGB24 or RGBA32 color format!</exception>
        /// <exception cref="NotImplementedException">TODO</exception>
        protected override void _Read(BinaryReader reader)
        {
            long baseOffset = reader.BaseStream.Position;

            int gbixOffset = 0;
            int pvrtOffset = 0;

            uint identifier = reader.ReadUInt32();

            if (identifier == m_gbix) //"GBIX"
            {
                HasGlobalIndex  = true;
                GlobalIndexSize = reader.ReadUInt32();
                GlobalIndex     = reader.ReadBytes((int)GlobalIndexSize);

                reader.BaseStream.Seek(4, SeekOrigin.Current); //Skip "PVRT"
                gbixOffset = 0x00;
                pvrtOffset = 0x08 + (int)GlobalIndexSize;
            }
            else
            {
                identifier = reader.ReadUInt32();
                if (identifier == m_gbix)
                {
                    HasGlobalIndex  = true;
                    GlobalIndexSize = reader.ReadUInt32();
                    GlobalIndex     = reader.ReadBytes((int)GlobalIndexSize);
                    gbixOffset      = 0x04;
                    pvrtOffset      = 0x0C + (int)GlobalIndexSize;
                }
                else if (identifier == m_pvrt)
                {
                    gbixOffset = -1;
                    pvrtOffset = 0x04;
                }
                else
                {
                    gbixOffset = -1;
                    pvrtOffset = 0x00;
                    reader.BaseStream.Seek(-4, SeekOrigin.Current);
                }
            }

            // Read information about the texture
            ContentSize = reader.ReadUInt32();
            PixelFormat = (PvrPixelFormat)reader.ReadByte();
            DataFormat  = (PvrDataFormat)reader.ReadByte();
            reader.BaseStream.Seek(2, SeekOrigin.Current);
            Width  = reader.ReadUInt16();
            Height = reader.ReadUInt16();

            if (DataFormat == PvrDataFormat.DDS || DataFormat == PvrDataFormat.DDS_2)
            {
                if (!(PixelFormat == PvrPixelFormat.DDS_DXT1_RGB24 || PixelFormat == PvrPixelFormat.DDS_DXT3_RGBA32))
                {
                    throw new Exception("Expected DDS RGB24 or RGBA32 color format!");
                }

                long             ddsOffset = reader.BaseStream.Position;
                DDS_Header       header    = new DDS_Header(reader.BaseStream);
                DDSFormatDetails format    = new DDSFormatDetails(header.Format, header.DX10_DXGI_AdditionalHeader.dxgiFormat);
                reader.BaseStream.Seek(ddsOffset, SeekOrigin.Begin);

                byte[] ddsBuffer = reader.ReadBytes(header.dwPitchOrLinearSize + header.dwSize + 128);

                MemoryStream memoryStream = new MemoryStream(ddsBuffer, 0, ddsBuffer.Length, true, true);
                MipMaps = DDSGeneral.LoadDDS(memoryStream, header, 0, format);
                memoryStream.Close();

                Width  = header.Width;
                Height = header.Height;
            }
            else
            {
                // Get the codecs and make sure we can decode using them
                PixelCodec = PvrPixelCodec.GetPixelCodec(PixelFormat);
                DataCodec  = PvrDataCodec.GetDataCodec(DataFormat);
                if (DataCodec != null && PixelCodec != null)
                {
                    DataCodec.PixelCodec = PixelCodec;
                }

                // Set the number of palette entries
                int paletteEntries = DataCodec.PaletteEntries;
                if (DataFormat == PvrDataFormat.VECTOR_QUANTIZATION_SMALL || DataFormat == PvrDataFormat.VECTOR_QUANTIZATION_SMALL_MIPMAP)
                {
                    if (Width <= 16)
                    {
                        paletteEntries = 64; // Actually 16
                    }
                    else if (Width <= 32)
                    {
                        paletteEntries = 256; // Actually 64
                    }
                    else if (Width <= 64)
                    {
                        paletteEntries = 512; // Actually 128
                    }
                    else
                    {
                        paletteEntries = 1024; // Actually 256
                    }
                }

                // Set the palette and data offsets
                int paletteOffset = 0;
                int dataOffset    = 0;
                if (paletteEntries == 0 || DataCodec.NeedsExternalPalette)
                {
                    paletteOffset = -1;
                    dataOffset    = pvrtOffset + 0x10;
                }
                else
                {
                    paletteOffset = pvrtOffset + 0x10;
                    dataOffset    = paletteOffset + (paletteEntries * (PixelCodec.Bpp >> 3));
                }

                // Get the compression format and determine if we need to decompress this texture
                reader.BaseStream.Seek(baseOffset, SeekOrigin.Begin);
                uint first = reader.ReadUInt32();
                reader.BaseStream.Seek(baseOffset + pvrtOffset + 4, SeekOrigin.Begin);
                uint second = reader.ReadUInt32();
                if (first == second - pvrtOffset + dataOffset + 8)
                {
                    CompressionFormat = PvrCompressionFormat.RLE;
                }
                else
                {
                    CompressionFormat = PvrCompressionFormat.NONE;
                }
                CompressionCodec = PvrCompressionCodec.GetCompressionCodec(CompressionFormat);

                if (CompressionFormat != PvrCompressionFormat.NONE && CompressionCodec != null)
                {
                    //TODO: Convert to stream compatible code
                    throw new NotImplementedException("TODO");
                    //m_encodedData = CompressionCodec.Decompress(m_encodedData, dataOffset, PixelCodec, DataCodec);

                    // Now place the offsets in the appropiate area
                    if (CompressionFormat == PvrCompressionFormat.RLE)
                    {
                        if (gbixOffset != -1)
                        {
                            gbixOffset -= 4;
                        }
                        pvrtOffset -= 4;
                        if (paletteOffset != -1)
                        {
                            paletteOffset -= 4;
                        }
                        dataOffset -= 4;
                    }
                }

                // If the texture contains mipmaps, gets the offsets of them
                int[] mipmapOffsets;
                if (DataCodec.HasMipmaps)
                {
                    int mipmapOffset = 0;
                    mipmapOffsets = new int[(int)Math.Log(Width, 2) + 1];

                    // Calculate the padding for the first mipmap offset
                    if (DataFormat == PvrDataFormat.SQUARE_TWIDDLED_MIPMAP)
                    {
                        mipmapOffset = (DataCodec.Bpp) >> 3; // A 1x1 mipmap takes up as much space as a 2x1 mipmap
                    }
                    else if (DataFormat == PvrDataFormat.SQUARE_TWIDDLED_MIPMAP_ALT)
                    {
                        mipmapOffset = (3 * DataCodec.Bpp) >> 3; // A 1x1 mipmap takes up as much space as a 2x2 mipmap
                    }
                    for (int i = mipmapOffsets.Length - 1, size = 1; i >= 0; i--, size <<= 1)
                    {
                        mipmapOffsets[i] = mipmapOffset;
                        mipmapOffset    += Math.Max((size * size * DataCodec.Bpp) >> 3, 1);
                    }
                }
                else
                {
                    mipmapOffsets = new int[1] {
                        0
                    };
                }

                //DecodeMipmaps()
                if (paletteOffset != -1) // The texture contains an embedded palette
                {
                    reader.BaseStream.Seek(baseOffset + paletteOffset, SeekOrigin.Begin);
                    DataCodec.SetPalette(reader, paletteEntries);
                }

                MipMaps = new List <MipMap>();
                if (DataCodec.HasMipmaps)
                {
                    for (int i = 0, size = Width; i < mipmapOffsets.Length; i++, size >>= 1)
                    {
                        reader.BaseStream.Seek(baseOffset + dataOffset + mipmapOffsets[i], SeekOrigin.Begin);
                        byte[] pixels = DataCodec.Decode(reader, size, size, PixelCodec);
                        MipMaps.Add(new MipMap(pixels, size, size));
                    }
                }
                else
                {
                    reader.BaseStream.Seek(baseOffset + dataOffset + mipmapOffsets[0], SeekOrigin.Begin);
                    byte[] pixels = DataCodec.Decode(reader, Width, Height, PixelCodec);
                    MipMaps.Add(new MipMap(pixels, Width, Height));
                }
            }
            if (HasGlobalIndex)
            {
                reader.BaseStream.Seek(baseOffset + ContentSize + 0xC, SeekOrigin.Begin);
            }
            else
            {
                reader.BaseStream.Seek(baseOffset + ContentSize, SeekOrigin.Begin);
            }
        }