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