/// <summary> /// Reads the gif comments. /// </summary> private void ReadComments() { int length; var stringBuilder = new StringBuilder(); while ((length = this.stream.ReadByte()) != 0) { if (length > GifConstants.MaxCommentSubBlockLength) { GifThrowHelper.ThrowInvalidImageContentException($"Gif comment length '{length}' exceeds max '{GifConstants.MaxCommentSubBlockLength}' of a comment data block"); } if (this.IgnoreMetadata) { this.stream.Seek(length, SeekOrigin.Current); continue; } using (IManagedByteBuffer commentsBuffer = this.MemoryAllocator.AllocateManagedByteBuffer(length)) { this.stream.Read(commentsBuffer.Array, 0, length); string commentPart = GifConstants.Encoding.GetString(commentsBuffer.Array, 0, length); stringBuilder.Append(commentPart); } } if (stringBuilder.Length > 0) { this.gifMetadata.Comments.Add(stringBuilder.ToString()); } }
/// <summary> /// Reads the image descriptor. /// </summary> private void ReadImageDescriptor() { this.stream.Read(this.buffer, 0, 9); this.imageDescriptor = GifImageDescriptor.Parse(this.buffer); if (this.imageDescriptor.Height == 0 || this.imageDescriptor.Width == 0) { GifThrowHelper.ThrowInvalidImageContentException("Width or height should not be 0"); } }
/// <summary> /// Decodes and decompresses all pixel indices from the stream. /// </summary> /// <param name="minCodeSize">Minimum code size of the data.</param> /// <param name="pixels">The pixel array to decode to.</param> public void DecodePixels(int minCodeSize, Buffer2D <byte> pixels) { // Calculate the clear code. The value of the clear code is 2 ^ minCodeSize int clearCode = 1 << minCodeSize; // It is possible to specify a larger LZW minimum code size than the palette length in bits // which may leave a gap in the codes where no colors are assigned. // http://www.matthewflickinger.com/lab/whatsinagif/lzw_image_data.asp#lzw_compression if (minCodeSize < 2 || clearCode > MaxStackSize) { // Don't attempt to decode the frame indices. // Theoretically we could determine a min code size from the length of the provided // color palette but we won't bother since the image is most likely corrupted. GifThrowHelper.ThrowInvalidImageContentException("Gif Image does not contain a valid LZW minimum code."); } // The resulting index table length. int width = pixels.Width; int height = pixels.Height; int length = width * height; int codeSize = minCodeSize + 1; // Calculate the end code int endCode = clearCode + 1; // Calculate the available code. int availableCode = clearCode + 2; // Jillzhangs Code see: http://giflib.codeplex.com/ // Adapted from John Cristy's ImageMagick. int code; int oldCode = NullCode; int codeMask = (1 << codeSize) - 1; int bits = 0; int top = 0; int count = 0; int bi = 0; int xyz = 0; int data = 0; int first = 0; ref int prefixRef = ref MemoryMarshal.GetReference(this.prefix.GetSpan());
/// <inheritdoc/> public Image <TPixel> Decode <TPixel>(Configuration configuration, Stream stream) where TPixel : unmanaged, IPixel <TPixel> { var decoder = new GifDecoderCore(configuration, this); try { return(decoder.Decode <TPixel>(stream)); } catch (InvalidMemoryOperationException ex) { Size dims = decoder.Dimensions; GifThrowHelper.ThrowInvalidImageContentException($"Can not decode image. Failed to allocate buffers for possibly degenerate dimensions: {dims.Width}x{dims.Height}.", ex); // Not reachable, as the previous statement will throw a exception. return(null); } }