/// <summary>Reads the GIF Color Table as 256 integer values</summary> /// <param name="numberOfColors">The number of colors to read</param> /// <returns>The GIF color table</returns> protected int[] ReadColorTable(int numberOfColors) { int nbytes = 3 * numberOfColors; int[] tab = null; byte[] c = new byte[nbytes]; int n = 0; try { n = inStream.Read(c, 0, c.Length); } catch (IOException) { } if (n < nbytes) { status = DecoderStatus.FormatError; } else { tab = new int[256]; // max size to avoid bounds checks int i = 0; int j = 0; while (i < numberOfColors) { byte r = (byte)(c[j++] & 0xff); byte g = (byte)(c[j++] & 0xff); byte b = (byte)(c[j++] & 0xff); tab[i++] = BitConverter.ToInt32(new[] { r, g, b, byte.MaxValue }, 0); } } return(tab); }
/// <summary>Reads the next variable length input block</summary> /// <returns>The remaining input bytes stored in the buffer</returns> protected int ReadBlock() { blockSize = Read(); int n = 0; if (blockSize > 0) { try { while (n < blockSize) { int count = inStream.Read(block, n, blockSize - n); if (count == -1) { break; } n += count; } } catch (IOException) { } if (n < blockSize) { status = DecoderStatus.FormatError; } } return(n); }
public static void DecompressAlpha(AvifItemData alphaImage, DecodeInfo decodeInfo, Surface fullSurface) { if (alphaImage is null) { ExceptionUtil.ThrowArgumentNullException(nameof(alphaImage)); } if (decodeInfo is null) { ExceptionUtil.ThrowArgumentNullException(nameof(decodeInfo)); } if (fullSurface is null) { ExceptionUtil.ThrowArgumentNullException(nameof(fullSurface)); } DecoderStatus status = DecoderStatus.Ok; unsafe { alphaImage.UseBufferPointer((ptr, length) => { BitmapData bitmapData = new BitmapData { scan0 = fullSurface.Scan0.Pointer, width = (uint)fullSurface.Width, height = (uint)fullSurface.Height, stride = (uint)fullSurface.Stride }; UIntPtr alphaImageSize = new UIntPtr(length); if (IntPtr.Size == 8) { status = AvifNative_64.DecompressAlphaImage(ptr, alphaImageSize, decodeInfo, ref bitmapData); } else { status = AvifNative_86.DecompressAlphaImage(ptr, alphaImageSize, decodeInfo, ref bitmapData); } }); } if (status != DecoderStatus.Ok) { HandleError(status); } }
/// <summary>Initializes or reinitalizes the reader</summary> protected void Init() { status = DecoderStatus.OK; frameCount = 0; frames = new List <int[]>(); delays = new List <int>(); globalColorTable = null; localColorTable = null; }
/// <summary>Reads a GIF file from the specified source</summary> /// <param name="name">The source file / URL</param> /// <returns>The status code</returns> public DecoderStatus Read(string name) { status = DecoderStatus.OK; try { status = Read(new FileInfo(name).OpenRead()); } catch (IOException) { status = DecoderStatus.OpenError; } return(status); }
/// <summary>Reads a single byte from the input stream</summary> protected int Read() { int curByte = 0; try { curByte = inStream.ReadByte(); } catch (IOException) { status = DecoderStatus.FormatError; } return(curByte); }
private static void HandleError(DecoderStatus status) { switch (status) { case DecoderStatus.Ok: break; case DecoderStatus.NullParameter: throw new FormatException("A required decoder parameter was null."); case DecoderStatus.OutOfMemory: throw new OutOfMemoryException(); case DecoderStatus.CodecInitFailed: throw new FormatException("Unable to initialize AV1 decoder."); case DecoderStatus.DecodeFailed: throw new FormatException("The AV1 decode failed."); case DecoderStatus.AlphaSizeMismatch: throw new FormatException("The alpha image does not match the expected size."); case DecoderStatus.ColorSizeMismatch: throw new FormatException("The color image does not match the expected size."); case DecoderStatus.TileNclxProfileMismatch: throw new FormatException("The color image tiles must use an identical color profile."); case DecoderStatus.UnsupportedBitDepth: throw new FormatException("The image has an unsupported bit depth."); case DecoderStatus.UnknownYUVFormat: throw new FormatException("The YUV format is not supported by the decoder."); case DecoderStatus.TileFormatMismatch: throw new FormatException("The color image tiles must use the same YUV format and bit depth."); default: throw new FormatException("An unknown error occurred when decoding the image."); } }
/// <summary>Reads the GIF header</summary> protected void ReadHeader() { string id = ""; for (int i = 0; i < 6; i++) { id += (char)Read(); } if (!id.StartsWith("GIF")) { status = DecoderStatus.FormatError; return; } ReadLSD(); if (golbalColorTableFlag && !Error) { globalColorTable = ReadColorTable(golbalColorTableSize); bgColor = globalColorTable[bgIndex]; } }
/// <summary>Reads a GIF file from the specified stream</summary> /// <param name="inputStream">The source stream</param> /// <returns>The status code</returns> public DecoderStatus Read(Stream inputStream) { Init(); if (inputStream != null) { this.inStream = inputStream; ReadHeader(); if (!Error) { ReadContents(); if (frameCount < 0) { status = DecoderStatus.FormatError; } } inputStream.Close(); } else { status = DecoderStatus.OpenError; } return(status); }
/// <summary>Reads the next frame image</summary> protected void ReadNextFrame() { imagePosition = ReadVector2(); imageSize = ReadVector2(); int packed = Read(); lctFlag = (packed & 0x80) != 0; // 1 - local color table flag interlace = (packed & 0x40) != 0; // 2 - interlace flag // 3 - sort flag // 4-5 - reserved int localColorTableSize = 2 << (packed & 7); // 6-8 - local color table size if (lctFlag) { localColorTable = ReadColorTable(localColorTableSize); // read table } else { if (bgIndex == transIndex) { bgColor = 0; } } int save = 0; if (transparency) { save = activeColorTable[transIndex]; activeColorTable[transIndex] = 0; // set transparent color if specified } if (activeColorTable == null) { status = DecoderStatus.FormatError; // no color table defined } if (Error) { return; } DecodeImageData(); // decode pixel data Skip(); if (Error) { return; } frameCount++; // create new image to receive frame data bitmap = new int[width * height]; image = bitmap; SetPixels(); // transfer pixel data to image frames.Add(bitmap); // add image to frame list delays.Add(delay); if (transparency) { activeColorTable[transIndex] = save; } ResetFrame(); }
/// <summary>Reads the contents of the file</summary> protected void ReadContents() { // read GIF file content blocks bool done = false; while (!(done || Error)) { ControlCode code = ReadControlCode(); switch (code) { case ControlCode.ImageSeparator: ReadNextFrame(); break; case ControlCode.ExtensionBlock: code = ReadControlCode(); switch (code) { case ControlCode.GraphicsExtension: ReadGraphicControlExt(); break; case ControlCode.ApplicationExtension: ReadBlock(); string app = ""; for (int i = 0; i < 11; i++) { app += (char)block[i]; } if (app.Equals("NETSCAPE2.0") || app.Equals("ANIMEXTS1.0")) { ReadNetscapeExt(); } else { Skip(); // don't care } break; case ControlCode.TextOverlay: Skip(); break; default: Skip(); break; } break; case ControlCode.Terminator: done = true; break; case ControlCode.BadByte: break; default: status = DecoderStatus.FormatError; break; } } }
/// <summary> /// resets decoder /// </summary> public void ResetDecoder() { m_decoder_status = DecoderStatus.NoPacket; }
/// <summary> /// Decodes SLIP encoded block /// </summary> /// <param name="in_source_buffer"></param> /// <param name="in_source_pos"></param> /// <param name="in_source_length"></param> /// <param name="in_destination_buffer"></param> /// <param name="inout_destination_pos"></param> /// <returns></returns> public bool DecodeBlock(byte[] in_source_buffer, ref int in_source_pos, int in_source_length, byte[] in_destination_buffer, ref int inout_destination_pos) { byte data; int destination_length = in_destination_buffer.Length; while (in_source_pos < in_source_length && inout_destination_pos < destination_length) { // get data data = in_source_buffer[in_source_pos++]; switch (m_decoder_status) { case DecoderStatus.NoPacket: if (data == SLIP_END) { m_decoder_status = DecoderStatus.Packet; } break; case DecoderStatus.Packet: if (data == SLIP_ESC) { // escaped data m_decoder_status = DecoderStatus.Escaped; } else { if (data == SLIP_END) { // drop zero length packets if (inout_destination_pos != 0) { // packet end found m_decoder_status = DecoderStatus.NoPacket; return(true); } } else { // store if not escaped in_destination_buffer[inout_destination_pos++] = data; } } break; case DecoderStatus.Escaped: // process escaped data switch (data) { case SLIP_ESC_END: data = SLIP_END; m_decoder_status = DecoderStatus.Packet; break; case SLIP_ESC_ESC: data = SLIP_ESC; m_decoder_status = DecoderStatus.Packet; break; } // store data in_destination_buffer[inout_destination_pos++] = data; break; } } return(false); }
public static void DecompressColor(AvifItemData colorImage, CICPColorData?colorConversionInfo, DecodeInfo decodeInfo, Surface fullSurface) { if (colorImage is null) { ExceptionUtil.ThrowArgumentNullException(nameof(colorImage)); } if (decodeInfo is null) { ExceptionUtil.ThrowArgumentNullException(nameof(decodeInfo)); } if (fullSurface is null) { ExceptionUtil.ThrowArgumentNullException(nameof(fullSurface)); } DecoderStatus status = DecoderStatus.Ok; unsafe { colorImage.UseBufferPointer((ptr, length) => { BitmapData bitmapData = new BitmapData { scan0 = fullSurface.Scan0.Pointer, width = (uint)fullSurface.Width, height = (uint)fullSurface.Height, stride = (uint)fullSurface.Stride }; UIntPtr colorImageSize = new UIntPtr(length); if (colorConversionInfo.HasValue) { CICPColorData colorData = colorConversionInfo.Value; if (IntPtr.Size == 8) { status = AvifNative_64.DecompressColorImage(ptr, colorImageSize, ref colorData, decodeInfo, ref bitmapData); } else { status = AvifNative_86.DecompressColorImage(ptr, colorImageSize, ref colorData, decodeInfo, ref bitmapData); } } else { if (IntPtr.Size == 8) { status = AvifNative_64.DecompressColorImage(ptr, colorImageSize, IntPtr.Zero, decodeInfo, ref bitmapData); } else { status = AvifNative_86.DecompressColorImage(ptr, colorImageSize, IntPtr.Zero, decodeInfo, ref bitmapData); } } }); } if (status != DecoderStatus.Ok) { HandleError(status); } }
// This function is called when we want to flush the decoder state // (i.e. in case of invalid UTF-8 characters or interrupted sequences) internal unsafe static DecoderStatus InternalGetCharsFlush ( char* chars, int charCount, DecoderFallbackBuffer fallbackBuffer, DecoderStatus s, int bytesProcessed, ref int charsProcessed, ref uint leftBytes, ref uint leftBits, ref uint procBytes) { // if there is nothing to flush, then exit silently if(procBytes == 0) return DecoderStatus.Ok; // now we build a 'bytesUnknown' array with the // stored bytes in 'procBytes'. int extra = 0; for (uint t = procBytes; t != 0; extra++) t = t >> 8; byte [] bytesUnknown = new byte [extra]; for (int i = extra; i > 0; i--) bytesUnknown [i - 1] = (byte) ((procBytes >> (8 * (extra - i))) & 0xff); // partial reset: this condition avoids infinite loops if (s == DecoderStatus.InvalidSequence) leftBytes = 0; // call the fallback and cross fingers fallbackBuffer.Fallback (bytesUnknown, bytesProcessed - extra); if (chars != null) { while (fallbackBuffer.Remaining > 0) { if (charsProcessed >= charCount) return DecoderStatus.InsufficientSpace; chars [charsProcessed++] = fallbackBuffer.GetNextChar (); } } else charsProcessed += fallbackBuffer.Remaining; fallbackBuffer.Reset (); // recovery was succesful, flush decoder state leftBits = leftBytes = procBytes = 0; return DecoderStatus.Ok; }