예제 #1
0
파일: Targa.cs 프로젝트: Krakean/Pfim
 /// <summary>
 /// Constructs a targa image from a targa image and raw data
 /// </summary>
 private Targa(TargaHeader header, PfimConfig config, byte[] data, int dataLen)
 {
     _config = config;
     Header  = header;
     Data    = data;
     DataLen = dataLen;
 }
예제 #2
0
        protected override void Decode(Stream stream, PfimConfig config)
        {
            if (config.Decompress)
            {
                Data = DataDecode(stream, config);
            }
            else
            {
                var  heightBlockAligned = HeightBlocks;
                long totalSize          = WidthBlocks * CompressedBytesPerBlock * heightBlockAligned;

                for (int i = 1; i < Header.MipMapCount; i++)
                {
                    var width        = Math.Max((int)(Header.Width / Math.Pow(2, i)), 1);
                    var height       = Math.Max((int)(Header.Height / Math.Pow(2, i)), 1);
                    var widthBlocks  = CalcBlocks(width);
                    var heightBlocks = CalcBlocks(height);
                    totalSize += widthBlocks * heightBlocks * CompressedBytesPerBlock;
                }

                DataLen     = (int)totalSize;
                Data        = config.Allocator.Rent((int)totalSize);
                _compressed = true;
                Util.Fill(stream, Data, DataLen, config.BufferSize);
            }
        }
예제 #3
0
        protected override void Decode(Stream stream, PfimConfig config)
        {
            if (config.Decompress)
            {
                Data = DataDecode(stream, config);
            }
            else
            {
                var  heightBlockAligned = HeightBlocks;
                long totalSize          = WidthBlocks * CompressedBytesPerBlock * heightBlockAligned;

                var width  = (int)Header.Width;
                var height = (int)Header.Height;
                for (int i = 1; i < Header.MipMapCount; i++)
                {
                    width  = (int)Math.Pow(2, Math.Floor(Math.Log(width - 1, 2)));
                    height = (int)Math.Pow(2, Math.Floor(Math.Log(height - 1, 2)));
                    var widthBlocks  = Math.Max(DivSize, width) / DivSize;
                    var heightBlocks = Math.Max(DivSize, height) / DivSize;
                    totalSize += widthBlocks * heightBlocks * CompressedBytesPerBlock;
                }

                DataLen     = (int)totalSize;
                Data        = config.Allocator.Rent((int)totalSize);
                _compressed = true;
                Util.Fill(stream, Data, DataLen, config.BufferSize);
            }
        }
예제 #4
0
파일: Dds.cs 프로젝트: poeAddict/LibGGPK2
        private static Dds DecodeDds(Stream stream, PfimConfig config, DdsHeader header)
        {
            Dds dds;

            switch (header.PixelFormat.FourCC)
            {
            case CompressionAlgorithm.D3DFMT_DXT1:
                dds = new Dxt1Dds(header, config);
                break;

            case CompressionAlgorithm.D3DFMT_DXT2:
            case CompressionAlgorithm.D3DFMT_DXT4:
                throw new ArgumentException("Cannot support DXT2 or DXT4");

            case CompressionAlgorithm.D3DFMT_DXT3:
                dds = new Dxt3Dds(header, config);
                break;

            case CompressionAlgorithm.D3DFMT_DXT5:
                dds = new Dxt5Dds(header, config);
                break;

            case CompressionAlgorithm.None:
                dds = new UncompressedDds(header, config);
                break;

            case CompressionAlgorithm.DX10:
                var header10 = new DdsHeaderDxt10(stream);
                dds          = header10.NewDecoder(header, config);
                dds.Header10 = header10;
                break;

            case CompressionAlgorithm.ATI1:
            case CompressionAlgorithm.BC4U:
                dds = new Bc4Dds(header, config);
                break;

            case CompressionAlgorithm.BC4S:
                dds = new Bc4sDds(header, config);
                break;

            case CompressionAlgorithm.ATI2:
            case CompressionAlgorithm.BC5U:
                dds = new Bc5Dds(header, config);
                break;

            case CompressionAlgorithm.BC5S:
                dds = new Bc5sDds(header, config);
                break;

            default:
                throw new ArgumentException($"FourCC: {header.PixelFormat.FourCC} not supported.");
            }

            dds.Decode(stream, config);
            return(dds);
        }
예제 #5
0
        /// <summary>Fills data starting from the bottom left</summary>
        public byte[] BottomLeft(Stream str, TargaHeader header, PfimConfig config)
        {
            var stride     = Util.Stride(header.Width, header.PixelDepthBits);
            var len        = header.Height * stride;
            var data       = config.Allocator.Rent(len);
            var trueStride = header.PixelDepthBytes * header.Width;

            InnerBottomLeft(str, config, data, len, stride, trueStride);
            return(data);
        }
예제 #6
0
        /// <summary>
        /// Instantiate a targa header from a given stream. The stream will be parsed
        /// </summary>
        public TargaHeader(Stream str, PfimConfig config)
        {
            byte[] buf = new byte[MINIMUM_SIZE];
            if (str.Read(buf, 0, MINIMUM_SIZE) != MINIMUM_SIZE)
            {
                throw new ArgumentException("Stream doesn't have enough data for a .tga", nameof(str));
            }

            DecodeTargaHeader(str, buf, MINIMUM_SIZE, config);
        }
예제 #7
0
        private static void InnerBottomLeft(Stream str, PfimConfig config, byte[] data, int dataLen, int stride, int trueStride)
        {
            if (str is MemoryStream s && s.TryGetBuffer(out var arr))
            {
                int dataIndex = dataLen - stride;

                for (int i = 0; dataIndex > 0; i++, dataIndex -= stride)
                {
                    Buffer.BlockCopy(arr.Array, (int)(s.Position + i * trueStride), data, dataIndex, trueStride);
                }
            }
예제 #8
0
 private static void InnerBottomLeft(Stream str, PfimConfig config, byte[] data, int dataLen, int stride, int rowBits)
 {
     if (str is MemoryStream s && s.TryGetBuffer(out var arr))
     {
         int dataIndex = dataLen - stride;
         int rowBytes  = rowBits / 8;
         int totalRows = dataLen / rowBytes;
         for (int i = 0; i < totalRows; i++, dataIndex -= stride)
         {
             Buffer.BlockCopy(arr.Array, (int)(s.Position + i * rowBytes), data, dataIndex, rowBytes);
         }
     }
예제 #9
0
        /// <summary>Decode data into raw rgb format</summary>
        private byte[] DataDecode(Stream str, PfimConfig config)
        {
            var imageInfo = ImageInfo();

            _format = imageInfo.Format;

            var len = CalcSize(imageInfo);

            DataLen = len;
            byte[] data = config.Allocator.Rent(len);

            var stride = Util.Stride((int)Header.Width, BitsPerPixel);

            if (Header.Width * BytesPerPixel == stride)
            {
                Util.Fill(str, data, len, config.BufferSize);
            }
            else
            {
                Util.InnerFillUnaligned(str, data, len, (int)Header.Width * BytesPerPixel, stride, config.BufferSize);
            }

            // Swap the R and B channels
            if (imageInfo.Swap)
            {
                switch (imageInfo.Format)
                {
                case ImageFormat.Rgba32:
                    for (int i = 0; i < len; i += 4)
                    {
                        byte temp = data[i];
                        data[i]     = data[i + 2];
                        data[i + 2] = temp;
                    }
                    break;

                case ImageFormat.Rgba16:
                    for (int i = 0; i < len; i += 2)
                    {
                        byte temp = (byte)(data[i] & 0xF);
                        data[i]     = (byte)((data[i] & 0xF0) + (data[i + 1] & 0XF));
                        data[i + 1] = (byte)((data[i + 1] & 0xF0) + temp);
                    }
                    break;

                default:
                    throw new Exception($"Do not know how to swap {imageInfo.Format}");
                }
            }

            return(data);
        }
예제 #10
0
파일: Pfim.cs 프로젝트: poeAddict/LibGGPK2
        /// <summary>
        /// Create image from stream. Pfim will try to detect the format based on several leading bytes
        /// </summary>
        public static IImage FromStream(Stream stream, PfimConfig config)
        {
            byte[] magic = new byte[4];
            if (stream.Read(magic, 0, 4) != 4)
            {
                throw new ArgumentException("stream must contain magic header", nameof(stream));
            }

            if (magic[0] == 0x44 && magic[1] == 0x44 && magic[2] == 0x53 && magic[3] == 0x20)
            {
                return(Dds.CreateSkipMagic(stream, config));
            }

            throw new Exception("This is not a DDS image file");
        }
예제 #11
0
        /// <summary>
        /// Create image from stream. Pfim will try to detect the format based on several leading bytes
        /// </summary>
        public static IImage FromStream(Stream stream, PfimConfig config)
        {
            byte[] magic = new byte[4];
            if (stream.Read(magic, 0, 4) != 4)
            {
                throw new ArgumentException("stream must contain magic header", nameof(stream));
            }

            if (magic[0] == 0x44 && magic[1] == 0x44 && magic[2] == 0x53 && magic[3] == 0x20)
            {
                return(Dds.CreateSkipMagic(stream, config));
            }

            return(Targa.CreateWithPartialHeader(stream, config, magic));
        }
예제 #12
0
        /// <summary>Constructs an image from a given file</summary>
        public static IImage FromFile(string path, PfimConfig config)
        {
            if (String.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (!File.Exists(path))
            {
                throw new FileNotFoundException($"Image does not exist: {Path.GetFullPath(path)}", path);
            }

            using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, config.BufferSize))
            {
                return(FromStream(fs, config));
            }
        }
예제 #13
0
파일: Targa.cs 프로젝트: Krakean/Pfim
        private static Targa DecodeTarga(Stream str, PfimConfig config, TargaHeader header)
        {
            var targa = (header.IsCompressed)
                ? (IDecodeTarga)(new CompressedTarga())
                : new UncompressedTarga();

            byte[] data;
            switch (header.Orientation)
            {
            case TargaHeader.TargaOrientation.BottomLeft:
                data = targa.BottomLeft(str, header, config);
                break;

            case TargaHeader.TargaOrientation.BottomRight:
                data = targa.BottomRight(str, header, config);
                break;

            case TargaHeader.TargaOrientation.TopRight:
                data = targa.TopRight(str, header, config);
                break;

            case TargaHeader.TargaOrientation.TopLeft:
                data = targa.TopLeft(str, header, config);
                break;

            default:
                throw new Exception("Targa orientation not recognized");
            }

            var stride = Util.Stride(header.Width, header.PixelDepthBits);
            var len    = header.Height * stride;
            var result = new Targa(header, config, data, len);

            if (config.ApplyColorMap)
            {
                result.ApplyColorMap();
            }

            return(result);
        }
예제 #14
0
파일: Dds.cs 프로젝트: poeAddict/LibGGPK2
 /// <summary>
 /// Instantiates a direct draw surface image from a header, the data,
 /// and additional info.
 /// </summary>
 protected Dds(DdsHeader header, PfimConfig config)
 {
     Header  = header;
     _config = config;
 }
예제 #15
0
파일: Dds.cs 프로젝트: poeAddict/LibGGPK2
 protected abstract void Decode(Stream stream, PfimConfig config);
예제 #16
0
        internal Dds NewDecoder(DdsHeader header, PfimConfig config)
        {
            switch (DxgiFormat)
            {
            case DxgiFormat.BC1_TYPELESS:
            case DxgiFormat.BC1_UNORM_SRGB:
            case DxgiFormat.BC1_UNORM:
                return(new Dxt1Dds(header, config));

            case DxgiFormat.BC2_TYPELESS:
            case DxgiFormat.BC2_UNORM:
            case DxgiFormat.BC2_UNORM_SRGB:
                return(new Dxt3Dds(header, config));

            case DxgiFormat.BC3_TYPELESS:
            case DxgiFormat.BC3_UNORM:
            case DxgiFormat.BC3_UNORM_SRGB:
                return(new Dxt5Dds(header, config));

            case DxgiFormat.BC4_TYPELESS:
            case DxgiFormat.BC4_UNORM:
                return(new Bc4Dds(header, config));

            case DxgiFormat.BC4_SNORM:
                return(new Bc4sDds(header, config));

            case DxgiFormat.BC5_TYPELESS:
            case DxgiFormat.BC5_UNORM:
                return(new Bc5Dds(header, config));

            case DxgiFormat.BC5_SNORM:
                return(new Bc5sDds(header, config));

            case DxgiFormat.BC6H_TYPELESS:
            case DxgiFormat.BC6H_UF16:
            case DxgiFormat.BC6H_SF16:
                return(new Bc6hDds(header, config));

            case DxgiFormat.BC7_TYPELESS:
            case DxgiFormat.BC7_UNORM:
            case DxgiFormat.BC7_UNORM_SRGB:
                return(new Bc7Dds(header, config));

            case DxgiFormat.R8G8B8A8_TYPELESS:
            case DxgiFormat.R8G8B8A8_UNORM:
            case DxgiFormat.R8G8B8A8_UNORM_SRGB:
            case DxgiFormat.R8G8B8A8_UINT:
            case DxgiFormat.R8G8B8A8_SNORM:
            case DxgiFormat.R8G8B8A8_SINT:
                return(new UncompressedDds(header, config, 32, true));

            case DxgiFormat.B8G8R8A8_TYPELESS:
            case DxgiFormat.B8G8R8A8_UNORM:
            case DxgiFormat.B8G8R8A8_UNORM_SRGB:
                return(new UncompressedDds(header, config, 32, false));

            case DxgiFormat.UNKNOWN:
            case DxgiFormat.R32G32B32A32_TYPELESS:
            case DxgiFormat.R32G32B32A32_FLOAT:
            case DxgiFormat.R32G32B32A32_UINT:
            case DxgiFormat.R32G32B32A32_SINT:
            case DxgiFormat.R32G32B32_TYPELESS:
            case DxgiFormat.R32G32B32_FLOAT:
            case DxgiFormat.R32G32B32_UINT:
            case DxgiFormat.R32G32B32_SINT:
            case DxgiFormat.R16G16B16A16_TYPELESS:
            case DxgiFormat.R16G16B16A16_FLOAT:
            case DxgiFormat.R16G16B16A16_UNORM:
            case DxgiFormat.R16G16B16A16_UINT:
            case DxgiFormat.R16G16B16A16_SNORM:
            case DxgiFormat.R16G16B16A16_SINT:
            case DxgiFormat.R32G32_TYPELESS:
            case DxgiFormat.R32G32_FLOAT:
            case DxgiFormat.R32G32_UINT:
            case DxgiFormat.R32G32_SINT:
            case DxgiFormat.R32G8X24_TYPELESS:
            case DxgiFormat.D32_FLOAT_S8X24_UINT:
            case DxgiFormat.R32_FLOAT_X8X24_TYPELESS:
            case DxgiFormat.X32_TYPELESS_G8X24_UINT:
            case DxgiFormat.R10G10B10A2_TYPELESS:
            case DxgiFormat.R10G10B10A2_UNORM:
            case DxgiFormat.R10G10B10A2_UINT:
            case DxgiFormat.R11G11B10_FLOAT:
            case DxgiFormat.R16G16_TYPELESS:
            case DxgiFormat.R16G16_FLOAT:
            case DxgiFormat.R16G16_UNORM:
            case DxgiFormat.R16G16_UINT:
            case DxgiFormat.R16G16_SNORM:
            case DxgiFormat.R16G16_SINT:
            case DxgiFormat.R32_TYPELESS:
            case DxgiFormat.D32_FLOAT:
            case DxgiFormat.R32_FLOAT:
            case DxgiFormat.R32_UINT:
            case DxgiFormat.R32_SINT:
            case DxgiFormat.R24G8_TYPELESS:
            case DxgiFormat.D24_UNORM_S8_UINT:
            case DxgiFormat.R24_UNORM_X8_TYPELESS:
            case DxgiFormat.X24_TYPELESS_G8_UINT:
            case DxgiFormat.R8G8_TYPELESS:
            case DxgiFormat.R8G8_UNORM:
            case DxgiFormat.R8G8_UINT:
            case DxgiFormat.R8G8_SNORM:
            case DxgiFormat.R8G8_SINT:
            case DxgiFormat.R16_TYPELESS:
            case DxgiFormat.R16_FLOAT:
            case DxgiFormat.D16_UNORM:
            case DxgiFormat.R16_UNORM:
            case DxgiFormat.R16_UINT:
            case DxgiFormat.R16_SNORM:
            case DxgiFormat.R16_SINT:
            case DxgiFormat.R8_TYPELESS:
            case DxgiFormat.R8_UNORM:
            case DxgiFormat.R8_UINT:
            case DxgiFormat.R8_SNORM:
            case DxgiFormat.R8_SINT:
            case DxgiFormat.A8_UNORM:
            case DxgiFormat.R1_UNORM:
            case DxgiFormat.R9G9B9E5_SHAREDEXP:
            case DxgiFormat.R8G8_B8G8_UNORM:
            case DxgiFormat.G8R8_G8B8_UNORM:
            case DxgiFormat.B8G8R8X8_UNORM:
            case DxgiFormat.R10G10B10_XR_BIAS_A2_UNORM:
            case DxgiFormat.B8G8R8X8_TYPELESS:
            case DxgiFormat.B8G8R8X8_UNORM_SRGB:
            case DxgiFormat.NV12:
            case DxgiFormat.P010:
            case DxgiFormat.P016:
            case DxgiFormat.OPAQUE_420:
            case DxgiFormat.YUY2:
            case DxgiFormat.Y210:
            case DxgiFormat.Y216:
            case DxgiFormat.NV11:
            case DxgiFormat.AI44:
            case DxgiFormat.IA44:
            case DxgiFormat.P8:
            case DxgiFormat.A8P8:
            case DxgiFormat.B4G4R4A4_UNORM:
            case DxgiFormat.P208:
            case DxgiFormat.V208:
            case DxgiFormat.V408:
            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #17
0
        /// <summary>Decode data into raw rgb format</summary>
        public byte[] DataDecode(Stream stream, PfimConfig config)
        {
            // If we are decoding in memory data, decode stream from that instead of
            // an intermediate buffer
            if (stream is MemoryStream s && s.TryGetBuffer(out var arr))
            {
                return(InMemoryDecode(arr.Array, (int)s.Position));
            }

            DataLen = HeightBlocks * DivSize * DeflatedStrideBytes;
            var totalLen = AllocateMipMaps();

            byte[] data       = Config.Allocator.Rent(totalLen);
            var    pixelsLeft = totalLen;
            int    dataIndex  = 0;

            int imageIndex      = 0;
            int divSize         = DivSize;
            int stride          = DeflatedStrideBytes;
            int blocksPerStride = WidthBlocks;
            int indexPixelsLeft = HeightBlocks * DivSize * stride;
            var stridePixels    = StridePixels;
            int bytesPerStride  = BytesPerStride;

            int bufferSize;

            byte[] streamBuffer = config.Allocator.Rent(config.BufferSize);
            try
            {
                do
                {
                    int workingSize;
                    bufferSize = workingSize = stream.Read(streamBuffer, 0, config.BufferSize);
                    int bIndex = 0;
                    while (workingSize > 0 && indexPixelsLeft > 0)
                    {
                        // If there is not enough of the buffer to fill the next
                        // set of 16 square pixels Get the next buffer
                        if (workingSize < bytesPerStride)
                        {
                            bufferSize = workingSize = Util.Translate(stream, streamBuffer, config.BufferSize, bIndex);
                            bIndex     = 0;
                        }

                        var origDataIndex = dataIndex;

                        // Now that we have enough pixels to fill a stride (and
                        // this includes the normally 4 pixels below the stride)
                        for (uint i = 0; i < blocksPerStride; i++)
                        {
                            bIndex = Decode(streamBuffer, data, bIndex, (uint)dataIndex, (uint)stridePixels);

                            // Advance to the next block, which is (pixel depth *
                            // divSize) bytes away
                            dataIndex += divSize * PixelDepthBytes;
                        }

                        // Each decoded block is divSize by divSize so pixels left
                        // is Width * multiplied by block height
                        workingSize -= bytesPerStride;

                        var filled = stride * divSize;
                        pixelsLeft      -= filled;
                        indexPixelsLeft -= filled;

                        // Jump down to the block that is exactly (divSize - 1)
                        // below the current row we are on
                        dataIndex = origDataIndex + filled;

                        if (indexPixelsLeft <= 0 && imageIndex < MipMaps.Length)
                        {
                            var mip          = MipMaps[imageIndex];
                            var widthBlocks  = CalcBlocks(mip.Width);
                            var heightBlocks = CalcBlocks(mip.Height);
                            stridePixels    = widthBlocks * DivSize;
                            stride          = stridePixels * PixelDepthBytes;
                            blocksPerStride = widthBlocks;
                            indexPixelsLeft = heightBlocks * DivSize * stride;
                            bytesPerStride  = widthBlocks * CompressedBytesPerBlock;
                            imageIndex++;
                        }
                    }
                } while (bufferSize != 0 && pixelsLeft > 0);

                return(data);
            }
            finally
            {
                config.Allocator.Return(streamBuffer);
            }
        }
예제 #18
0
        /// <summary>Fills data starting from the bottom left</summary>
        public byte[] BottomLeft(Stream str, TargaHeader header, PfimConfig config)
        {
            var stride  = Util.Stride(header.Width, header.PixelDepthBits);
            var dataLen = header.Height * stride;
            var data    = config.Allocator.Rent(dataLen);

            if (str is MemoryStream s && s.TryGetBuffer(out var arr))
            {
                return(FastPass(data, arr, header, stride, s.Position));
            }

            int dataIndex       = dataLen - stride;
            int bytesPerPixel   = header.PixelDepthBytes;
            int fileBufferIndex = 0;

            // Calculate the maximum number of bytes potentially needed from the buffer.
            // If our buffer doesn't have enough to decode the maximum number of bytes,
            // fetch another batch of bytes from the stream.
            int maxRead = bytesPerPixel * 128 + 1;

            byte[] filebuffer = config.Allocator.Rent(config.BufferSize);
            try
            {
                int workingSize = str.Read(filebuffer, 0, config.BufferSize);
                while (dataIndex >= 0)
                {
                    int colIndex = 0;
                    do
                    {
                        if (config.BufferSize - fileBufferIndex < maxRead && workingSize == config.BufferSize)
                        {
                            workingSize     = Util.Translate(str, filebuffer, config.BufferSize, fileBufferIndex);
                            fileBufferIndex = 0;
                        }

                        bool isRunLength = (filebuffer[fileBufferIndex] & 128) != 0;
                        int  count       = isRunLength ? bytesPerPixel + 1 : filebuffer[fileBufferIndex] + 1;

                        // If the first bit is on, it means that the next packet is run length encoded
                        if (isRunLength)
                        {
                            RunLength(data, filebuffer, dataIndex, fileBufferIndex, bytesPerPixel);
                            dataIndex       += (filebuffer[fileBufferIndex] - 127) * bytesPerPixel;
                            colIndex        += filebuffer[fileBufferIndex] - 127;
                            fileBufferIndex += count;
                        }
                        else
                        {
                            int bytcount = count * bytesPerPixel;
                            fileBufferIndex++;

                            Buffer.BlockCopy(filebuffer, fileBufferIndex, data, dataIndex, bytcount);
                            fileBufferIndex += bytcount;
                            colIndex        += count;
                            dataIndex       += bytcount;
                        }
                    } while (colIndex < header.Width);
                    dataIndex -= bytesPerPixel * header.Width + stride;
                }

                return(data);
            }
            finally
            {
                config.Allocator.Return(filebuffer);
            }
        }
예제 #19
0
 internal UncompressedDds(DdsHeader header, PfimConfig config) : base(header, config)
 {
 }
예제 #20
0
파일: Dds.cs 프로젝트: poeAddict/LibGGPK2
        /// <summary>
        /// Same as a regular create except assumes that the magic number has already been consumed
        /// </summary>
        internal static IImage CreateSkipMagic(Stream stream, PfimConfig config)
        {
            DdsHeader header = new DdsHeader(stream, true);

            return(DecodeDds(stream, config, header));
        }
예제 #21
0
파일: Targa.cs 프로젝트: Krakean/Pfim
        internal static IImage CreateWithPartialHeader(Stream str, PfimConfig config, byte[] magic)
        {
            var header = new TargaHeader(str, magic, 4, config);

            return(DecodeTarga(str, config, header));
        }
예제 #22
0
        private void DecodeTargaHeader(Stream str, byte[] partial, int partialLen, PfimConfig config)
        {
            byte[] buf;

            if (partialLen == MINIMUM_SIZE)
            {
                buf = partial;
            }
            else if (partialLen > MINIMUM_SIZE)
            {
                throw new ArgumentException($"Partial header can't exceed {MINIMUM_SIZE} bytes");
            }
            else
            {
                buf = new byte[MINIMUM_SIZE];
                var left = MINIMUM_SIZE - partialLen;
                for (int i = 0; i < partialLen; i++)
                {
                    buf[i] = partial[i];
                }

                if (str.Read(buf, partialLen, left) != left)
                {
                    throw new ArgumentException("Stream doesn't have enough data for a .tga", nameof(str));
                }
            }

            IDLength    = buf[0];
            HasColorMap = buf[1] == 1;
            ImageType   = (TargaImageType)buf[2];
            if (!Enum.IsDefined(typeof(TargaImageType), ImageType))
            {
                throw new ArgumentException("Detected invalid targa image");
            }

            ColorMapOrigin    = BitConverter.ToInt16(buf, 3);
            ColorMapLength    = BitConverter.ToInt16(buf, 5);
            ColorMapDepthBits = buf[7];
            XOrigin           = BitConverter.ToInt16(buf, 8);
            YOrigin           = BitConverter.ToInt16(buf, 10);
            Width             = BitConverter.ToInt16(buf, 12);
            Height            = BitConverter.ToInt16(buf, 14);
            PixelDepthBits    = buf[16];

            // Extract the bits in place 4 and 5 for orientation
            Orientation = (TargaOrientation)((buf[17] >> 4) & 3);

            if (IDLength != 0)
            {
                var idBuf  = new byte[IDLength];
                var amount = str.Read(idBuf, 0, IDLength);
                ImageId = Encoding.Unicode.GetString(idBuf, 0, amount);
            }

            if (HasColorMap)
            {
                if (ColorMapOrigin > ColorMapLength)
                {
                    throw new ArgumentException("Color map origin was detected to exceed color map length");
                }

                var mapBytes = ColorMapDepthBytes;
                ColorMap = new byte[ColorMapLength * mapBytes];
                str.Read(ColorMap, ColorMapOrigin * mapBytes, (ColorMapLength - ColorMapOrigin) * mapBytes);
            }
        }
예제 #23
0
 internal TargaHeader(Stream str, byte[] partial, int partialLen, PfimConfig config)
 {
     DecodeTargaHeader(str, partial, partialLen, config);
 }
예제 #24
0
 public Dxt5Dds(DdsHeader header, PfimConfig config) : base(header, config)
 {
 }
예제 #25
0
 protected override void Decode(Stream stream, PfimConfig config)
 {
     Data = DataDecode(stream, config);
 }
예제 #26
0
파일: Dds.cs 프로젝트: poeAddict/LibGGPK2
 public static Dds Create(byte[] data, PfimConfig config)
 {
     return(Create(Util.CreateExposed(data), config));
 }
예제 #27
0
파일: Dds.cs 프로젝트: poeAddict/LibGGPK2
        /// <summary>Create a direct draw image from a stream</summary>
        public static Dds Create(Stream stream, PfimConfig config)
        {
            DdsHeader header = new DdsHeader(stream);

            return(DecodeDds(stream, config, header));
        }
예제 #28
0
 protected CompressedDds(DdsHeader header, PfimConfig config) : base(header, config)
 {
 }
예제 #29
0
파일: Targa.cs 프로젝트: Krakean/Pfim
        /// <summary>
        /// Creates a targa image from a given stream. The type of targa is determined from the
        /// targa header, which is assumed to be a part of the stream
        /// </summary>
        /// <param name="str">Stream to read the targa image from</param>
        /// <returns>A targa image</returns>
        public static Targa Create(Stream str, PfimConfig config)
        {
            var header = new TargaHeader(str, config);

            return(DecodeTarga(str, config, header));
        }
예제 #30
0
 internal UncompressedDds(DdsHeader header, PfimConfig config, uint bitsPerPixel, bool rgbSwapped) : base(header, config)
 {
     _bitsPerPixel = bitsPerPixel;
     _rgbSwapped   = rgbSwapped;
 }