public override ImageMetaData ReadMetaData(Stream stream) { if (0x46464952 != FormatCatalog.ReadSignature (stream)) // 'RIFF' return null; var header = new byte[0x10]; if (8 != stream.Read (header, 0, 8)) return null; if (!Binary.AsciiEqual (header, 4, "WEBP")) return null; bool found_vp8x = false; var info = new WebPMetaData(); int chunk_size; for (;;) { if (8 != stream.Read (header, 0, 8)) return null; chunk_size = LittleEndian.ToInt32 (header, 4); int aligned_size = (chunk_size + 1) & ~1; if (!found_vp8x && Binary.AsciiEqual (header, 0, "VP8X")) { found_vp8x = true; if (chunk_size < 10) return null; if (chunk_size > header.Length) header = new byte[chunk_size]; if (chunk_size != stream.Read (header, 0, chunk_size)) return null; info.Flags = (WebPFeature)LittleEndian.ToUInt32 (header, 0); info.Width = 1 + GetUInt24 (header, 4); info.Height = 1 + GetUInt24 (header, 7); if ((long)info.Width * info.Height >= (1L << 32)) return null; continue; } if (Binary.AsciiEqual (header, 0, "VP8 ") || Binary.AsciiEqual (header, 0, "VP8L")) { info.IsLossless = header[3] == 'L'; info.DataOffset = stream.Position; info.DataSize = chunk_size; if (!found_vp8x) { if (chunk_size < 10 || 10 != stream.Read (header, 0, 10)) return null; if (header[3] != 0x9D || header[4] != 1 || header[5] != 0x2A) return null; if (0 != (header[0] & 1)) // not a keyframe return null; info.Width = LittleEndian.ToUInt16 (header, 6) & 0x3FFFu; info.Height = LittleEndian.ToUInt16 (header, 8) & 0x3FFFu; } break; } if (Binary.AsciiEqual (header, 0, "ALPH")) { info.AlphaOffset = stream.Position; info.AlphaSize = chunk_size; } stream.Seek (aligned_size, SeekOrigin.Current); } if (0 == info.Width || 0 == info.Height) return null; return info; }
public WebPDecoder(Stream input, WebPMetaData info) { m_input = new ArcView.Reader (input); m_info = info; m_stride = (int)info.Width * 4; m_output = new byte[m_stride * (int)info.Height]; m_io = new VP8Io(); if (0 != m_info.AlphaOffset) { m_input.BaseStream.Position = m_info.AlphaOffset; m_alpha_data = m_input.ReadBytes (m_info.AlphaSize); m_alpha_plane = new byte[info.Width * info.Height]; Format = PixelFormats.Bgra32; } else { Format = PixelFormats.Bgr32; } }
public override ImageMetaData ReadMetaData(IBinaryStream stream) { if (0x46464952 != stream.Signature) // 'RIFF' { return(null); } if (!stream.ReadHeader(12).AsciiEqual(8, "WEBP")) { return(null); } var header = new byte[0x10]; bool found_vp8x = false; var info = new WebPMetaData { BPP = 32 }; int chunk_size; for (;;) { if (8 != stream.Read(header, 0, 8)) { return(null); } chunk_size = LittleEndian.ToInt32(header, 4); int aligned_size = (chunk_size + 1) & ~1; if (!found_vp8x && Binary.AsciiEqual(header, 0, "VP8X")) { found_vp8x = true; if (chunk_size < 10) { return(null); } if (chunk_size > header.Length) { header = new byte[chunk_size]; } if (chunk_size != stream.Read(header, 0, chunk_size)) { return(null); } info.Flags = (WebPFeature)LittleEndian.ToUInt32(header, 0); info.Width = 1 + (uint)header.ToInt24(4); info.Height = 1 + (uint)header.ToInt24(7); if ((long)info.Width * info.Height >= (1L << 32)) { return(null); } continue; } if (Binary.AsciiEqual(header, 0, "VP8 ") || Binary.AsciiEqual(header, 0, "VP8L")) { info.IsLossless = header[3] == 'L'; info.DataOffset = stream.Position; info.DataSize = aligned_size; if (!found_vp8x) { if (chunk_size < 10 || 10 != stream.Read(header, 0, 10)) { return(null); } if (info.IsLossless) { if (header[0] != 0x2F || (header[4] >> 5) != 0) { return(null); } uint wh = LittleEndian.ToUInt32(header, 1); info.Width = (wh & 0x3FFFu) + 1; info.Height = ((wh >> 14) & 0x3FFFu) + 1; info.HasAlpha = 0 != (header[4] & 0x10); } else { if (header[3] != 0x9D || header[4] != 1 || header[5] != 0x2A) { return(null); } if (0 != (header[0] & 1)) // not a keyframe { return(null); } info.Width = LittleEndian.ToUInt16(header, 6) & 0x3FFFu; info.Height = LittleEndian.ToUInt16(header, 8) & 0x3FFFu; } } break; } if (Binary.AsciiEqual(header, 0, "ALPH")) { info.AlphaOffset = stream.Position; info.AlphaSize = chunk_size; } stream.Seek(aligned_size, SeekOrigin.Current); } if (0 == info.Width || 0 == info.Height) { return(null); } return(info); }