/// <summary> /// Creates a list of Chunks containing the PNG keywords /// </summary> /// <returns> /// A <see cref="ByteVector"/> with the list of chunks, or /// or <see langword="null" /> if no PNG Keywords are contained. /// </returns> private ByteVector RenderKeywordChunks() { // Check, if PngTag is contained PngTag png_tag = GetTag(TagTypes.Png, true) as PngTag; if (png_tag == null) { return(null); } ByteVector chunks = new ByteVector(); foreach (KeyValuePair <string, string> keyword in png_tag) { ByteVector data = new ByteVector(); data.Add(keyword.Key); data.Add("\0"); data.Add(keyword.Value); chunks.Add(ByteVector.FromUInt((uint)data.Count)); chunks.Add(tEXt_CHUNK_TYPE); chunks.Add(data); chunks.Add(ComputeCRC(tEXt_CHUNK_TYPE, data)); } return(chunks); }
/// <summary> /// Reads an tEXt Chunk from file. The current position must be set /// to the start of the Chunk Data. Such a Chunk contains plain /// keywords. /// </summary> /// <param name="data_length"> /// A <see cref="System.Int32"/> with the length of the Chunk Data. /// </param> private void ReadtEXtChunk(int data_length) { long position = Tell; // tEXt Chunk // // N Bytes Keyword // 1 Byte Null Separator // N Bytes Txt // // Followed by 4 Bytes CRC data ByteVector data = ReadChunkData(data_length); CheckCRC(tEXt_CHUNK_TYPE, data, ReadCRC()); int keyword_terminator; string keyword = ReadKeyword(data, 0, out keyword_terminator); string value = data.Mid(keyword_terminator + 1).ToString(); PngTag png_tag = GetTag(TagTypes.Png, true) as PngTag; if (png_tag.GetKeyword(keyword) == null) { png_tag.SetKeyword(keyword, value); } AddMetadataBlock(position - 8, data_length + 8 + 4); }
/// <summary> /// Reads an zTXt Chunk from file. The current position must be set /// to the start of the Chunk Data. Such a Chunk contains compressed /// keywords. /// </summary> /// <param name="data_length"> /// A <see cref="System.Int32"/> with the length of the Chunk Data. /// </param> /// <remarks> /// The Chunk may also contain compressed Exif data which is written /// by other tools. But, since the PNG specification does not support /// Exif data, we ignore it here. /// </remarks> private void ReadzTXtChunk(int data_length) { long position = Tell; // zTXt Chunk // // N Bytes Keyword // 1 Byte Null Separator // 1 Byte Compression Method // N Bytes Txt // // Followed by 4 Bytes CRC data ByteVector data = ReadChunkData(data_length); CheckCRC(zTXt_CHUNK_TYPE, data, ReadCRC()); int terminator_index; string keyword = ReadKeyword(data, 0, out terminator_index); if (terminator_index + 1 >= data_length) { throw new CorruptFileException("Compression Method byte expected"); } byte compression_method = data[terminator_index + 1]; ByteVector plain_data = Decompress(compression_method, data.Mid(terminator_index + 2)); // ignore unknown compression methods if (plain_data == null) { return; } string value = plain_data.ToString(); PngTag png_tag = GetTag(TagTypes.Png, true) as PngTag; if (png_tag.GetKeyword(keyword) == null) { png_tag.SetKeyword(keyword, value); } AddMetadataBlock(position - 8, data_length + 8 + 4); }
/// <summary> /// Reads an iTXt Chunk from file. The current position must be set /// to the start of the Chunk Data. Such a Chunk may contain XMP data /// or translated keywords. /// </summary> /// <param name="data_length"> /// A <see cref="System.Int32"/> with the length of the Chunk Data. /// </param> private void ReadiTXtChunk(int data_length) { long position = Tell; // iTXt Chunk // // N Bytes Keyword // 1 Byte Null Separator // 1 Byte Compression Flag (0 for uncompressed data) // 1 Byte Compression Method // N Bytes Language Tag // 1 Byte Null Separator // N Bytes Translated Keyword // 1 Byte Null Terminator // N Bytes Txt // // Followed by 4 Bytes CRC data ByteVector data = ReadChunkData(data_length); CheckCRC(iTXt_CHUNK_TYPE, data, ReadCRC()); // handle XMP, which has a fixed header if (data.StartsWith(XMP_CHUNK_HEADER)) { ImageTag.AddTag(new XmpTag(data.Mid(XMP_CHUNK_HEADER.Length).ToString(StringType.UTF8), this)); AddMetadataBlock(position - 8, data_length + 8 + 4); return; } int terminator_index; string keyword = ReadKeyword(data, 0, out terminator_index); if (terminator_index + 2 >= data_length) { throw new CorruptFileException("Compression Flag and Compression Method byte expected"); } byte compression_flag = data[terminator_index + 1]; byte compression_method = data[terminator_index + 2]; //string language = ReadTerminatedString (data, terminator_index + 3, out terminator_index); //string translated_keyword = ReadTerminatedString (data, terminator_index + 1, out terminator_index); ByteVector txt_data = data.Mid(terminator_index + 1); if (compression_flag != 0x00) { txt_data = Decompress(compression_method, txt_data); // ignore unknown compression methods if (txt_data == null) { return; } } string value = txt_data.ToString(); PngTag png_tag = GetTag(TagTypes.Png, true) as PngTag; if (png_tag.GetKeyword(keyword) == null) { png_tag.SetKeyword(keyword, value); } AddMetadataBlock(position - 8, data_length + 8 + 4); }