Пример #1
0
        public async Task <byte[]> DecodeAsync(byte[] imageBytes, ISffPngImageHeader imageHeader)
        {
            var scanlineDecoder = NegumContainer.Resolve <ISffPngScanlineDecoder>();

            // -3 ==>> Scanline was interpreted as RGBA and we want it to be 1 byte not 4
            // 4 ==>> RGBA (1 byte per each subPixel)
            var bytesPerLine  = imageHeader.BytesInRow * 4 - 3;
            var bytesPerPixel = imageHeader.GetBytesPerPixel();

            var outputBytes = new byte[imageBytes.Length];

            for (var row = 0; row < imageHeader.Height; ++row)
            {
                var rowStartIndex = row * bytesPerLine;
                var rowEndIndex   = rowStartIndex + bytesPerLine;
                var scanline      = imageBytes[rowStartIndex..rowEndIndex];
Пример #2
0
        public async Task <byte[]> DecodeAsync(Stream stream, ISffPngImageHeader imageHeader)
        {
            var chunkHeaderReader       = NegumContainer.Resolve <ISffPngChunkHeaderReader>();
            var chunkProcessorContainer = NegumContainer.Resolve <ISffPngChunkProcessorContainer>();

            // State shared between all chunk processors.
            // Processors can use data read by other processors.
            var chunkProcessorState = new Dictionary <string, object>();

            while (true)
            {
                if (chunkProcessorContainer.IsProcessingFinished(chunkProcessorState))
                {
                    break;
                }

                var chunkHeader = await chunkHeaderReader.ReadAsync(stream);

                var chunkData = new byte[chunkHeader.Length];

                if (stream.Read(chunkData) != chunkHeader.Length)
                {
                    throw new ArgumentException($"Cannot read chunk data.");
                }

                chunkProcessorContainer.ProcessChunk(chunkHeader, chunkData, chunkProcessorState);

                var crcData = new byte[SffPngHelper.CrcDataLength];

                if (stream.Read(crcData) != SffPngHelper.CrcDataLength)
                {
                    throw new ArgumentException($"Cannot read CRC data for chunk: {chunkHeader.Name}");
                }

                // TODO: Do we need to validate CRC ??? (only critical)
            }

            chunkProcessorContainer.PerformPostProcessing(chunkProcessorState);

            var deflateImage = chunkProcessorContainer.GetOutputBytes(chunkProcessorState);

            return(deflateImage);
        }
        public async Task <byte[]> ApplyAsync(ISffPngImageHeader imageHeader, byte[] imageData, IPalette palette)
        {
            // (Scanline filter byte + imageHeader.Width * 4 RGBA bytes) * imageHeader.Height == imageData.Length
            if ((1 + imageHeader.Width * 4) * imageHeader.Height == imageData.Length)
            {
                // Already in RGBA format
                return(imageData);
            }

            if (palette == null)
            {
                throw new ArgumentNullException($"Palette is required to decode PNG image.");
            }

            var coloredImage = new List <byte>();

            for (var index = 0; index < imageData.Length; ++index)
            {
                var paletteIndex = imageData[index];

                // For scanline filter type we don't want to perform colorization
                if (index == 0 || index % imageHeader.BytesInRow == 0)
                {
                    coloredImage.Add(paletteIndex);
                    continue;
                }

                var color = palette.ElementAt(paletteIndex);

                coloredImage.Add(color.Red);
                coloredImage.Add(color.Green);
                coloredImage.Add(color.Blue);
                coloredImage.Add(color.Alpha);
            }

            return(coloredImage.ToArray());
        }
Пример #4
0
 public async Task <byte[]> DecodeAsync(byte[] imageBytes, ISffPngImageHeader imageHeader) =>
 imageHeader.InterlaceMethod switch
 {
     0 => await NegumContainer.Resolve <ISffPngNoInterlaceDecoder>().DecodeAsync(imageBytes, imageHeader),
 public async Task <byte[]> DecodeAsync(byte[] imageBytes, ISffPngImageHeader imageHeader)
 {
     throw new ArgumentException($"Adam7 interlace is not yet supported.");
 }