Beispiel #1
0
        private static byte[] ToScanlines(Image image)
        {
            byte[] data      = new byte[(image.Width * image.Height * 4) + image.Height];
            int    RowLength = (image.Width * 4) + 1;

            Parallel.For(0, image.Width, x =>
            {
                int dataOffset       = (x * 4) + 1;
                int PixelOffset      = x;
                data[dataOffset]     = image.Pixels[PixelOffset].Red;
                data[dataOffset + 1] = image.Pixels[PixelOffset].Green;
                data[dataOffset + 2] = image.Pixels[PixelOffset].Blue;
                data[dataOffset + 3] = image.Pixels[PixelOffset].Alpha;
                data[0] = 0;
                for (int y = 1; y < image.Height; ++y)
                {
                    dataOffset           = (y * RowLength) + (x * 4) + 1;
                    PixelOffset          = (image.Width * y) + x;
                    int AbovePixelOffset = (image.Width * (y - 1)) + x;
                    data[dataOffset]     = (byte)(image.Pixels[PixelOffset].Red - image.Pixels[AbovePixelOffset].Red);
                    data[dataOffset + 1] = (byte)(image.Pixels[PixelOffset].Green - image.Pixels[AbovePixelOffset].Green);
                    data[dataOffset + 2] = (byte)(image.Pixels[PixelOffset].Blue - image.Pixels[AbovePixelOffset].Blue);
                    data[dataOffset + 3] = (byte)(image.Pixels[PixelOffset].Alpha - image.Pixels[AbovePixelOffset].Alpha);
                    data[y * RowLength]  = 2;
                }
            });

            using (MemoryStream TempMemoryStream = new MemoryStream())
            {
                using (ZlibDeflateStream TempDeflateStream = new ZlibDeflateStream(TempMemoryStream, 6))
                {
                    TempDeflateStream.Write(data, 0, data.Length);
                }
                return(TempMemoryStream.ToArray());
            }
        }
Beispiel #2
0
        /// <summary>
        /// Writes the pixel information to the stream.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="pixels">The image.</param>
        /// <param name="stream">The stream.</param>
        private void WriteDataChunks <TPixel>(ImageFrame <TPixel> pixels, Stream stream)
            where TPixel : struct, IPixel <TPixel>
        {
            this.bytesPerScanline = this.width * this.bytesPerPixel;
            int resultLength = this.bytesPerScanline + 1;

            this.previousScanline = this.memoryManager.AllocateCleanManagedByteBuffer(this.bytesPerScanline);
            this.rawScanline      = this.memoryManager.AllocateCleanManagedByteBuffer(this.bytesPerScanline);
            this.result           = this.memoryManager.AllocateCleanManagedByteBuffer(resultLength);

            if (this.pngColorType != PngColorType.Palette)
            {
                this.sub     = this.memoryManager.AllocateCleanManagedByteBuffer(resultLength);
                this.up      = this.memoryManager.AllocateCleanManagedByteBuffer(resultLength);
                this.average = this.memoryManager.AllocateCleanManagedByteBuffer(resultLength);
                this.paeth   = this.memoryManager.AllocateCleanManagedByteBuffer(resultLength);
            }

            byte[]       buffer;
            int          bufferLength;
            MemoryStream memoryStream = null;

            try
            {
                memoryStream = new MemoryStream();
                using (var deflateStream = new ZlibDeflateStream(memoryStream, this.compressionLevel))
                {
                    for (int y = 0; y < this.height; y++)
                    {
                        IManagedByteBuffer r = this.EncodePixelRow(pixels.GetPixelRowSpan(y), y);
                        deflateStream.Write(r.Array, 0, resultLength);

                        IManagedByteBuffer temp = this.rawScanline;
                        this.rawScanline      = this.previousScanline;
                        this.previousScanline = temp;
                    }
                }

                buffer       = memoryStream.ToArray();
                bufferLength = buffer.Length;
            }
            finally
            {
                memoryStream?.Dispose();
            }

            // Store the chunks in repeated 64k blocks.
            // This reduces the memory load for decoding the image for many decoders.
            int numChunks = bufferLength / MaxBlockSize;

            if (bufferLength % MaxBlockSize != 0)
            {
                numChunks++;
            }

            for (int i = 0; i < numChunks; i++)
            {
                int length = bufferLength - (i * MaxBlockSize);

                if (length > MaxBlockSize)
                {
                    length = MaxBlockSize;
                }

                this.WriteChunk(stream, PngChunkTypes.Data, buffer, i * MaxBlockSize, length);
            }
        }
Beispiel #3
0
        private void WriteDataChunks(Stream stream, Image image)
        {
            byte[] pixels = image.Pixels;

            byte[] data = new byte[image.Width * image.Height * 4 + image.Height];

            int rowLength = image.Width * 4 + 1;

            for (int y = 0; y < image.Height; y++)
            {
                byte compression = 0;
                if (y > 0)
                {
                    compression = 2;
                }
                data[y * rowLength] = compression;

                for (int x = 0; x < image.Width; x++)
                {
                    // Calculate the offset for the new array.
                    int dataOffset = y * rowLength + x * 4 + 1;

                    // Calculate the offset for the original pixel array.
                    int pixelOffset = (y * image.Width + x) * 4;

                    data[dataOffset + 0] = pixels[pixelOffset + 2];
                    data[dataOffset + 1] = pixels[pixelOffset + 1];
                    data[dataOffset + 2] = pixels[pixelOffset + 0];
                    data[dataOffset + 3] = pixels[pixelOffset + 3];

                    if (y > 0)
                    {
                        int lastOffset = ((y - 1) * image.Width + x) * 4;

                        data[dataOffset + 0] -= pixels[lastOffset + 2];
                        data[dataOffset + 1] -= pixels[lastOffset + 1];
                        data[dataOffset + 2] -= pixels[lastOffset + 0];
                        data[dataOffset + 3] -= pixels[lastOffset + 3];
                    }
                }
            }

            byte[] buffer       = null;
            int    bufferLength = 0;

            MemoryStream memoryStream = null;

            try
            {
                memoryStream = new MemoryStream();

                using (var zStream = new ZlibDeflateStream(memoryStream, 6))
                {
                    zStream.Write(data, 0, data.Length);
                }

                bufferLength = (int)memoryStream.Length;
                buffer       = memoryStream.ToArray();
            }
            finally
            {
                if (memoryStream != null)
                {
                    memoryStream.Dispose();
                }
            }

            int numChunks = bufferLength / MaxBlockSize;

            if (bufferLength % MaxBlockSize != 0)
            {
                numChunks++;
            }

            for (int i = 0; i < numChunks; i++)
            {
                int length = bufferLength - i * MaxBlockSize;

                if (length > MaxBlockSize)
                {
                    length = MaxBlockSize;
                }

                WriteChunk(stream, PngChunkTypes.Data, buffer, i * MaxBlockSize, length);
            }
        }
        private void WriteDataChunks(Stream stream, IPixelAccessor pixels, QuantizedImage quantized)
        {
            byte[] data;
            int    imageWidth  = pixels.Width;
            int    imageHeight = pixels.Height;

            if (Quality <= 256)
            {
                int rowLength = imageWidth + 1;
                data = new byte[rowLength * imageHeight];
                Parallel.For(0, imageHeight, Bootstrapper.instance.ParallelOptions, y => {
                    int dataOffset   = (y * rowLength);
                    byte compression = 0;
                    if (y > 0)
                    {
                        compression = 2;
                    }
                    data[dataOffset++] = compression;
                    for (int x = 0; x < imageWidth; x++)
                    {
                        data[dataOffset++] = quantized.Pixels[(y * imageWidth) + x];
                        if (y > 0)
                        {
                            data[dataOffset - 1] -= quantized.Pixels[((y - 1) * imageWidth) + x];
                        }
                    }
                });
            }
            else
            {
                data = new byte[(imageWidth * imageHeight * 4) + pixels.Height];
                int rowLength = (imageWidth * 4) + 1;
                Parallel.For(0, imageHeight, Bootstrapper.instance.ParallelOptions, y => {
                    byte compression = 0;
                    if (y > 0)
                    {
                        compression = 2;
                    }
                    data[y * rowLength] = compression;
                    for (int x = 0; x < imageWidth; x++)
                    {
                        byte[] color         = pixels[x, y].ToBytes();
                        int dataOffset       = (y * rowLength) + (x * 4) + 1;
                        data[dataOffset]     = color[0];
                        data[dataOffset + 1] = color[1];
                        data[dataOffset + 2] = color[2];
                        data[dataOffset + 3] = color[3];
                        if (y > 0)
                        {
                            color                 = pixels[x, y - 1].ToBytes();
                            data[dataOffset]     -= color[0];
                            data[dataOffset + 1] -= color[1];
                            data[dataOffset + 2] -= color[2];
                            data[dataOffset + 3] -= color[3];
                        }
                    }
                });
            }
            byte[]       buffer;
            int          bufferLength;
            MemoryStream memoryStream = null;

            try{
                memoryStream = new MemoryStream();
                using (ZlibDeflateStream deflateStream = new ZlibDeflateStream(memoryStream, CompressionLevel)){
                    deflateStream.Write(data, 0, data.Length);
                }
                bufferLength = (int)memoryStream.Length;
                buffer       = memoryStream.ToArray();
            } finally{
                memoryStream?.Dispose();
            }
            int numChunks = bufferLength / maxBlockSize;

            if (bufferLength % maxBlockSize != 0)
            {
                numChunks++;
            }
            for (int i = 0; i < numChunks; i++)
            {
                int length = bufferLength - (i * maxBlockSize);
                if (length > maxBlockSize)
                {
                    length = maxBlockSize;
                }
                WriteChunk(stream, PngChunkTypes.Data, buffer, i * maxBlockSize, length);
            }
        }