mirror of https://github.com/SixLabors/ImageSharp
Browse Source
* Add support for writing tEXt chunks * Add support for reading zTXt chunks * Add check, if keyword is valid * Add support for reading iTXt chunks * Add support for writing iTXt chunks * Remove Test Decode_TextEncodingSetToUnicode_TextIsReadWithCorrectEncoding: Assertion is wrong, the correct keyword name is "Software" * Add support for writing zTXt chunk * Add an encoder Option to enable compression when the string is larger than a given threshold * Moved uncompressing text into separate method * Remove textEncoding option from png decoder options: the encoding is determined by the specification: https://www.w3.org/TR/PNG/#11zTXt * Removed invalid compressed zTXt chunk from test image * Revert accidentally committed changes to Sandbox Program.cs * Review adjustments * Using 1024 bytes as a limit when to compress text as recommended by the spec * Fix inconsistent line endings * Trim leading and trailing whitespace on png keywords * Move some metadata related tests into GifMetaDataTests.cs * Add test case for gif with large text * Gif text metadata is now a list of strings * Encoder writes each comment as a separate block * Adjustment of the Tests to the recent changes * Move comments to GifMetadata * Move Png TextData to format PngMetaDatapull/961/head
committed by
James Jackson-South
37 changed files with 1117 additions and 718 deletions
@ -0,0 +1,143 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Png |
|||
{ |
|||
/// <summary>
|
|||
/// Stores text data contained in the iTXt, tEXt, and zTXt chunks.
|
|||
/// Used for conveying textual information associated with the image, like the name of the author,
|
|||
/// the copyright information, the date, where the image was created, or some other information.
|
|||
/// </summary>
|
|||
public readonly struct PngTextData : IEquatable<PngTextData> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PngTextData"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="keyword">The keyword of the property.</param>
|
|||
/// <param name="value">The value of the property.</param>
|
|||
/// <param name="languageTag">An optional language tag.</param>
|
|||
/// <param name="translatedKeyword">A optional translated keyword.</param>
|
|||
public PngTextData(string keyword, string value, string languageTag, string translatedKeyword) |
|||
{ |
|||
Guard.NotNullOrWhiteSpace(keyword, nameof(keyword)); |
|||
|
|||
// No leading or trailing whitespace is allowed in keywords.
|
|||
this.Keyword = keyword.Trim(); |
|||
this.Value = value; |
|||
this.LanguageTag = languageTag; |
|||
this.TranslatedKeyword = translatedKeyword; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the keyword of this <see cref="PngTextData"/> which indicates
|
|||
/// the type of information represented by the text string as described in https://www.w3.org/TR/PNG/#11keywords.
|
|||
/// </summary>
|
|||
/// <example>
|
|||
/// Typical properties are the author, copyright information or other meta information.
|
|||
/// </example>
|
|||
public string Keyword { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of this <see cref="PngTextData"/>.
|
|||
/// </summary>
|
|||
public string Value { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets an optional language tag defined in https://www.w3.org/TR/PNG/#2-RFC-3066 indicates the human language used by the translated keyword and the text.
|
|||
/// If the first word is two or three letters long, it is an ISO language code https://www.w3.org/TR/PNG/#2-ISO-639.
|
|||
/// </summary>
|
|||
/// <example>
|
|||
/// Examples: cn, en-uk, no-bok, x-klingon, x-KlInGoN.
|
|||
/// </example>
|
|||
public string LanguageTag { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets an optional translated keyword, should contain a translation of the keyword into the language indicated by the language tag.
|
|||
/// </summary>
|
|||
public string TranslatedKeyword { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="PngTextData"/> objects. The result specifies whether the values
|
|||
/// of the properties of the two <see cref="PngTextData"/> objects are equal.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="PngTextData"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="PngTextData"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(PngTextData left, PngTextData right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="PngTextData"/> objects. The result specifies whether the values
|
|||
/// of the properties of the two <see cref="PngTextData"/> objects are unequal.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="PngTextData"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="PngTextData"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(PngTextData left, PngTextData right) |
|||
{ |
|||
return !(left == right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Indicates whether this instance and a specified object are equal.
|
|||
/// </summary>
|
|||
/// <param name="obj">
|
|||
/// The object to compare with the current instance.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// true if <paramref name="obj"/> and this instance are the same type and represent the
|
|||
/// same value; otherwise, false.
|
|||
/// </returns>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return obj is PngTextData other && this.Equals(other); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
public override int GetHashCode() => HashCode.Combine(this.Keyword, this.Value, this.LanguageTag, this.TranslatedKeyword); |
|||
|
|||
/// <summary>
|
|||
/// Returns the fully qualified type name of this instance.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A <see cref="T:System.String"/> containing a fully qualified type name.
|
|||
/// </returns>
|
|||
public override string ToString() => $"PngTextData [ Name={this.Keyword}, Value={this.Value} ]"; |
|||
|
|||
/// <summary>
|
|||
/// Indicates whether the current object is equal to another object of the same type.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// True if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
/// <param name="other">An object to compare with this object.</param>
|
|||
public bool Equals(PngTextData other) |
|||
{ |
|||
return this.Keyword.Equals(other.Keyword) |
|||
&& this.Value.Equals(other.Value) |
|||
&& this.LanguageTag.Equals(other.LanguageTag) |
|||
&& this.TranslatedKeyword.Equals(other.TranslatedKeyword); |
|||
} |
|||
} |
|||
} |
|||
@ -1,124 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
|
|||
namespace SixLabors.ImageSharp.Metadata |
|||
{ |
|||
/// <summary>
|
|||
/// Stores meta information about a image, like the name of the author,
|
|||
/// the copyright information, the date, where the image was created
|
|||
/// or some other information.
|
|||
/// </summary>
|
|||
public readonly struct ImageProperty : IEquatable<ImageProperty> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ImageProperty"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="name">The name of the property.</param>
|
|||
/// <param name="value">The value of the property.</param>
|
|||
public ImageProperty(string name, string value) |
|||
{ |
|||
Guard.NotNullOrWhiteSpace(name, nameof(name)); |
|||
|
|||
this.Name = name; |
|||
this.Value = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the name of this <see cref="ImageProperty"/> indicating which kind of
|
|||
/// information this property stores.
|
|||
/// </summary>
|
|||
/// <example>
|
|||
/// Typical properties are the author, copyright
|
|||
/// information or other meta information.
|
|||
/// </example>
|
|||
public string Name { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of this <see cref="ImageProperty"/>.
|
|||
/// </summary>
|
|||
public string Value { get; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="ImageProperty"/> objects. The result specifies whether the values
|
|||
/// of the <see cref="ImageProperty.Name"/> or <see cref="ImageProperty.Value"/> properties of the two
|
|||
/// <see cref="ImageProperty"/> objects are equal.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="ImageProperty"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="ImageProperty"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(ImageProperty left, ImageProperty right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="ImageProperty"/> objects. The result specifies whether the values
|
|||
/// of the <see cref="ImageProperty.Name"/> or <see cref="ImageProperty.Value"/> properties of the two
|
|||
/// <see cref="ImageProperty"/> objects are unequal.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="ImageProperty"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="ImageProperty"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(ImageProperty left, ImageProperty right) |
|||
{ |
|||
return !(left == right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Indicates whether this instance and a specified object are equal.
|
|||
/// </summary>
|
|||
/// <param name="obj">
|
|||
/// The object to compare with the current instance.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// true if <paramref name="obj"/> and this instance are the same type and represent the
|
|||
/// same value; otherwise, false.
|
|||
/// </returns>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return obj is ImageProperty other && this.Equals(other); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
public override int GetHashCode() => HashCode.Combine(this.Name, this.Value); |
|||
|
|||
/// <summary>
|
|||
/// Returns the fully qualified type name of this instance.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A <see cref="T:System.String"/> containing a fully qualified type name.
|
|||
/// </returns>
|
|||
public override string ToString() => $"ImageProperty [ Name={this.Name}, Value={this.Value} ]"; |
|||
|
|||
/// <summary>
|
|||
/// Indicates whether the current object is equal to another object of the same type.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// True if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
/// <param name="other">An object to compare with this object.</param>
|
|||
public bool Equals(ImageProperty other) |
|||
{ |
|||
return this.Name.Equals(other.Name) && Equals(this.Value, other.Value); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Formats.Png; |
|||
using Xunit; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Formats.Png |
|||
{ |
|||
/// <summary>
|
|||
/// Tests the <see cref="PngTextData"/> class.
|
|||
/// </summary>
|
|||
public class PngTextDataTests |
|||
{ |
|||
/// <summary>
|
|||
/// Tests the equality operators for inequality.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void AreEqual() |
|||
{ |
|||
var property1 = new PngTextData("Foo", "Bar", "foo", "bar"); |
|||
var property2 = new PngTextData("Foo", "Bar", "foo", "bar"); |
|||
|
|||
Assert.Equal(property1, property2); |
|||
Assert.True(property1 == property2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Tests the equality operators for equality.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void AreNotEqual() |
|||
{ |
|||
var property1 = new PngTextData("Foo", "Bar", "foo", "bar"); |
|||
var property2 = new PngTextData("Foo", "Foo", string.Empty, string.Empty); |
|||
var property3 = new PngTextData("Bar", "Bar", "unit", "test"); |
|||
var property4 = new PngTextData("Foo", null, "test", "case"); |
|||
|
|||
Assert.NotEqual(property1, property2); |
|||
Assert.True(property1 != property2); |
|||
|
|||
Assert.NotEqual(property1, property3); |
|||
Assert.NotEqual(property1, property4); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Tests whether the constructor throws an exception when the property keyword is null or empty.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void ConstructorThrowsWhenKeywordIsNullOrEmpty() |
|||
{ |
|||
Assert.Throws<ArgumentNullException>(() => new PngTextData(null, "Foo", "foo", "bar")); |
|||
|
|||
Assert.Throws<ArgumentException>(() => new PngTextData(string.Empty, "Foo", "foo", "bar")); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Tests whether the constructor correctly assigns properties.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void ConstructorAssignsProperties() |
|||
{ |
|||
var property = new PngTextData("Foo", null, "unit", "test"); |
|||
Assert.Equal("Foo", property.Keyword); |
|||
Assert.Null(property.Value); |
|||
Assert.Equal("unit", property.LanguageTag); |
|||
Assert.Equal("test", property.TranslatedKeyword); |
|||
|
|||
property = new PngTextData("Foo", string.Empty, string.Empty, null); |
|||
Assert.Equal("Foo", property.Keyword); |
|||
Assert.Equal(string.Empty, property.Value); |
|||
Assert.Equal(string.Empty, property.LanguageTag); |
|||
Assert.Null(property.TranslatedKeyword); |
|||
} |
|||
} |
|||
} |
|||
@ -1,73 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Metadata; |
|||
using Xunit; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests |
|||
{ |
|||
/// <summary>
|
|||
/// Tests the <see cref="ImageProperty"/> class.
|
|||
/// </summary>
|
|||
public class ImagePropertyTests |
|||
{ |
|||
/// <summary>
|
|||
/// Tests the equality operators for inequality.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void AreEqual() |
|||
{ |
|||
var property1 = new ImageProperty("Foo", "Bar"); |
|||
var property2 = new ImageProperty("Foo", "Bar"); |
|||
|
|||
Assert.Equal(property1, property2); |
|||
Assert.True(property1 == property2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Tests the equality operators for equality.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void AreNotEqual() |
|||
{ |
|||
var property1 = new ImageProperty("Foo", "Bar"); |
|||
var property2 = new ImageProperty("Foo", "Foo"); |
|||
var property3 = new ImageProperty("Bar", "Bar"); |
|||
var property4 = new ImageProperty("Foo", null); |
|||
|
|||
Assert.False(property1.Equals("Foo")); |
|||
|
|||
Assert.NotEqual(property1, property2); |
|||
Assert.True(property1 != property2); |
|||
|
|||
Assert.NotEqual(property1, property3); |
|||
Assert.NotEqual(property1, property4); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Tests whether the constructor throws an exception when the property name is null or empty.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void ConstructorThrowsWhenNameIsNullOrEmpty() |
|||
{ |
|||
Assert.Throws<ArgumentNullException>(() => new ImageProperty(null, "Foo")); |
|||
|
|||
Assert.Throws<ArgumentException>(() => new ImageProperty(string.Empty, "Foo")); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Tests whether the constructor correctly assigns properties.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void ConstructorAssignsProperties() |
|||
{ |
|||
var property = new ImageProperty("Foo", null); |
|||
Assert.Equal("Foo", property.Name); |
|||
Assert.Null(property.Value); |
|||
|
|||
property = new ImageProperty("Foo", string.Empty); |
|||
Assert.Equal(string.Empty, property.Value); |
|||
} |
|||
} |
|||
} |
|||
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 383 B |
|
After Width: | Height: | Size: 805 B |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Loading…
Reference in new issue