public void ProcessChunk(string fourCc, byte[] payload) { switch (fourCc) { case "EXIF": { // We have seen WebP images with and without the preamble here. It's likely that some software incorrectly // copied an entire JPEG segment into the WebP image. Regardless, we can handle it here. var reader = ExifReader.StartsWithJpegExifPreamble(payload) ? new ByteArrayReader(payload, ExifReader.JpegSegmentPreambleLength) : new ByteArrayReader(payload); _directories.AddRange(new ExifReader().Extract(reader)); break; } case "ICCP": { _directories.Add(new IccReader().Extract(new ByteArrayReader(payload))); break; } case "XMP ": { _directories.Add(new XmpReader().Extract(payload)); break; } case "VP8X": { if (payload.Length != 10) { break; } string?error = null; var reader = new ByteArrayReader(payload, isMotorolaByteOrder: false); var isAnimation = false; var hasAlpha = false; var widthMinusOne = -1; var heightMinusOne = -1; try { // Flags // bit 0: has fragments // bit 1: is animation // bit 2: has XMP // bit 3: has Exif // bit 4: has alpha // big 5: has ICC isAnimation = reader.GetBit(1); hasAlpha = reader.GetBit(4); // Image size widthMinusOne = reader.GetInt24(4); heightMinusOne = reader.GetInt24(7); } catch (IOException e) { error = "Exception reading WebpRiff chunk 'VP8X' : " + e.Message; } var directory = new WebPDirectory(); if (error == null) { directory.Set(WebPDirectory.TagImageWidth, widthMinusOne + 1); directory.Set(WebPDirectory.TagImageHeight, heightMinusOne + 1); directory.Set(WebPDirectory.TagHasAlpha, hasAlpha); directory.Set(WebPDirectory.TagIsAnimation, isAnimation); } else { directory.AddError(error); } _directories.Add(directory); break; } case "VP8L": { if (payload.Length < 5) { break; } var reader = new ByteArrayReader(payload, isMotorolaByteOrder: false); string?error = null; var widthMinusOne = -1; var heightMinusOne = -1; try { // https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification#2_riff_header // Expect the signature byte if (reader.GetByte(0) != 0x2F) { break; } var b1 = reader.GetByte(1); var b2 = reader.GetByte(2); var b3 = reader.GetByte(3); var b4 = reader.GetByte(4); // 14 bits for width widthMinusOne = (b2 & 0x3F) << 8 | b1; // 14 bits for height heightMinusOne = (b4 & 0x0F) << 10 | b3 << 2 | (b2 & 0xC0) >> 6; } catch (IOException e) { error = "Exception reading WebpRiff chunk 'VP8L' : " + e.Message; } var directory = new WebPDirectory(); if (error == null) { directory.Set(WebPDirectory.TagImageWidth, widthMinusOne + 1); directory.Set(WebPDirectory.TagImageHeight, heightMinusOne + 1); } else { directory.AddError(error); } _directories.Add(directory); break; } case "VP8 ": { if (payload.Length < 10) { break; } var reader = new ByteArrayReader(payload, isMotorolaByteOrder: false); string?error = null; var width = 0; var height = 0; try { // https://tools.ietf.org/html/rfc6386#section-9.1 // https://github.com/webmproject/libwebp/blob/master/src/enc/syntax.c#L115 // Expect the signature bytes if (reader.GetByte(3) != 0x9D || reader.GetByte(4) != 0x01 || reader.GetByte(5) != 0x2A) { break; } width = reader.GetUInt16(6); height = reader.GetUInt16(8); } catch (IOException e) { error = "Exception reading WebpRiff chunk 'VP8' : " + e.Message; } var directory = new WebPDirectory(); if (error == null) { directory.Set(WebPDirectory.TagImageWidth, width); directory.Set(WebPDirectory.TagImageHeight, height); } else { directory.AddError(error); } _directories.Add(directory); break; } } }
public void ProcessChunk(string fourCc, byte[] payload) { switch (fourCc) { case "EXIF": { _directories.AddRange(new ExifReader().Extract(new ByteArrayReader(payload))); break; } case "ICCP": { _directories.Add(new IccReader().Extract(new ByteArrayReader(payload))); break; } case "XMP ": { _directories.Add(new XmpReader().Extract(payload)); break; } case "VP8X": { if (payload.Length != 10) { break; } string error = null; var reader = new ByteArrayReader(payload, isMotorolaByteOrder: false); var isAnimation = false; var hasAlpha = false; var widthMinusOne = -1; var heightMinusOne = -1; try { // Flags // var hasFragments = reader.GetBit(0); isAnimation = reader.GetBit(1); // var hasXmp = reader.GetBit(2); // var hasExif = reader.GetBit(3); hasAlpha = reader.GetBit(4); // var hasIcc = reader.GetBit(5); // Image size widthMinusOne = reader.GetInt24(4); heightMinusOne = reader.GetInt24(7); } catch (IOException e) { error = "Exception reading WebpRiff chunk 'VP8X' : " + e.Message; } var directory = new WebPDirectory(); if (error == null) { directory.Set(WebPDirectory.TagImageWidth, widthMinusOne + 1); directory.Set(WebPDirectory.TagImageHeight, heightMinusOne + 1); directory.Set(WebPDirectory.TagHasAlpha, hasAlpha); directory.Set(WebPDirectory.TagIsAnimation, isAnimation); } else { directory.AddError(error); } _directories.Add(directory); break; } case "VP8L": { if (payload.Length < 5) { break; } var reader = new ByteArrayReader(payload, isMotorolaByteOrder: false); string error = null; var widthMinusOne = -1; var heightMinusOne = -1; try { // https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification#2_riff_header // Expect the signature byte if (reader.GetByte(0) != 0x2F) { break; } var b1 = reader.GetByte(1); var b2 = reader.GetByte(2); var b3 = reader.GetByte(3); var b4 = reader.GetByte(4); // 14 bits for width widthMinusOne = (b2 & 0x3F) << 8 | b1; // 14 bits for height heightMinusOne = (b4 & 0x0F) << 10 | b3 << 2 | (b2 & 0xC0) >> 6; } catch (IOException e) { error = "Exception reading WebpRiff chunk 'VP8L' : " + e.Message; } var directory = new WebPDirectory(); if (error == null) { directory.Set(WebPDirectory.TagImageWidth, widthMinusOne + 1); directory.Set(WebPDirectory.TagImageHeight, heightMinusOne + 1); } else { directory.AddError(error); } _directories.Add(directory); break; } case "VP8 ": { if (payload.Length < 10) { break; } var reader = new ByteArrayReader(payload, isMotorolaByteOrder: false); string error = null; var width = 0; var height = 0; try { // https://tools.ietf.org/html/rfc6386#section-9.1 // https://github.com/webmproject/libwebp/blob/master/src/enc/syntax.c#L115 // Expect the signature bytes if (reader.GetByte(3) != 0x9D || reader.GetByte(4) != 0x01 || reader.GetByte(5) != 0x2A) { break; } width = reader.GetUInt16(6); height = reader.GetUInt16(8); } catch (IOException e) { error = "Exception reading WebpRiff chunk 'VP8' : " + e.Message; } var directory = new WebPDirectory(); if (error == null) { directory.Set(WebPDirectory.TagImageWidth, width); directory.Set(WebPDirectory.TagImageHeight, height); } else { directory.AddError(error); } _directories.Add(directory); break; } } }