public virtual void TestGimpGreyscaleWithManyChunks() { TimeZoneInfo timeZone = System.TimeZoneInfo.Local; try { Com.Drew.Metadata.Metadata metadata = ProcessFile("Tests/Data/gimp-8x12-greyscale-alpha-time-background.png"); ICollection<PngDirectory> directories = metadata.GetDirectoriesOfType<PngDirectory>(); NUnit.Framework.Assert.IsNotNull(directories); Sharpen.Tests.AreEqual(6, directories.Count); PngDirectory[] dirs = new PngDirectory[directories.Count]; Sharpen.Collections.ToArray(directories, dirs); Sharpen.Tests.AreEqual(PngChunkType.Ihdr, dirs[0].GetPngChunkType()); Sharpen.Tests.AreEqual(8, dirs[0].GetInt(PngDirectory.TagImageWidth)); Sharpen.Tests.AreEqual(12, dirs[0].GetInt(PngDirectory.TagImageHeight)); Sharpen.Tests.AreEqual(8, dirs[0].GetInt(PngDirectory.TagBitsPerSample)); Sharpen.Tests.AreEqual(4, dirs[0].GetInt(PngDirectory.TagColorType)); Sharpen.Tests.AreEqual(0, dirs[0].GetInt(PngDirectory.TagCompressionType)); Sharpen.Tests.AreEqual(0, dirs[0].GetInt(PngDirectory.TagFilterMethod)); Sharpen.Tests.AreEqual(0, dirs[0].GetInt(PngDirectory.TagInterlaceMethod)); Sharpen.Tests.AreEqual(PngChunkType.gAMA, dirs[1].GetPngChunkType()); Sharpen.Tests.AreEqual(0.45455, dirs[1].GetDouble(PngDirectory.TagGamma), 0.00001); Sharpen.Tests.AreEqual(PngChunkType.bKGD, dirs[2].GetPngChunkType()); NUnit.Framework.CollectionAssert.AreEqual(new sbyte[] { 0, 52 }, dirs[2].GetByteArray(PngDirectory.TagBackgroundColor)); //noinspection ConstantConditions Sharpen.Tests.AreEqual(PngChunkType.pHYs, dirs[3].GetPngChunkType()); Sharpen.Tests.AreEqual(1, dirs[3].GetInt(PngDirectory.TagUnitSpecifier)); Sharpen.Tests.AreEqual(2835, dirs[3].GetInt(PngDirectory.TagPixelsPerUnitX)); Sharpen.Tests.AreEqual(2835, dirs[3].GetInt(PngDirectory.TagPixelsPerUnitY)); Sharpen.Tests.AreEqual(PngChunkType.tIME, dirs[4].GetPngChunkType()); //Sharpen.Tests.AreEqual("Tue Jan 01 04:08:30 GMT 2013", Sharpen.Extensions.ConvertToString(dirs[4].GetDate(PngDirectory.TagLastModificationTime))); var testString = CreateTestString(2013, 00, 01, 04, 08, 30); Sharpen.Tests.AreEqual(testString, Sharpen.Extensions.ConvertToString(dirs[4].GetDate(PngDirectory.TagLastModificationTime))); Sharpen.Tests.AreEqual(PngChunkType.iTXt, dirs[5].GetPngChunkType()); IList<KeyValuePair> pairs = (IList<KeyValuePair>)dirs[5].GetObject(PngDirectory.TagTextualData); NUnit.Framework.Assert.IsNotNull(pairs); Sharpen.Tests.AreEqual(1, pairs.Count); Sharpen.Tests.AreEqual("Comment", pairs[0].GetKey()); Sharpen.Tests.AreEqual("Created with GIMP", pairs[0].GetValue()); } finally { } }
/// <exception cref="Com.Drew.Imaging.Png.PngProcessingException"/> /// <exception cref="System.IO.IOException"/> private static void ProcessChunk([NotNull] Com.Drew.Metadata.Metadata metadata, [NotNull] PngChunk chunk) { PngChunkType chunkType = chunk.GetChunkType(); sbyte[] bytes = chunk.GetBytes(); if (chunkType.Equals(PngChunkType.Ihdr)) { PngHeader header = new PngHeader(bytes); PngDirectory directory = new PngDirectory(PngChunkType.Ihdr); directory.SetInt(PngDirectory.TagImageWidth, header.GetImageWidth()); directory.SetInt(PngDirectory.TagImageHeight, header.GetImageHeight()); directory.SetInt(PngDirectory.TagBitsPerSample, header.GetBitsPerSample()); directory.SetInt(PngDirectory.TagColorType, header.GetColorType().GetNumericValue()); directory.SetInt(PngDirectory.TagCompressionType, header.GetCompressionType()); directory.SetInt(PngDirectory.TagFilterMethod, header.GetFilterMethod()); directory.SetInt(PngDirectory.TagInterlaceMethod, header.GetInterlaceMethod()); metadata.AddDirectory(directory); } else { if (chunkType.Equals(PngChunkType.Plte)) { PngDirectory directory = new PngDirectory(PngChunkType.Plte); directory.SetInt(PngDirectory.TagPaletteSize, bytes.Length / 3); metadata.AddDirectory(directory); } else { if (chunkType.Equals(PngChunkType.tRNS)) { PngDirectory directory = new PngDirectory(PngChunkType.tRNS); directory.SetInt(PngDirectory.TagPaletteHasTransparency, 1); metadata.AddDirectory(directory); } else { if (chunkType.Equals(PngChunkType.sRGB)) { int srgbRenderingIntent = new SequentialByteArrayReader(bytes).GetInt8(); PngDirectory directory = new PngDirectory(PngChunkType.sRGB); directory.SetInt(PngDirectory.TagSrgbRenderingIntent, srgbRenderingIntent); metadata.AddDirectory(directory); } else { if (chunkType.Equals(PngChunkType.cHRM)) { PngChromaticities chromaticities = new PngChromaticities(bytes); PngChromaticitiesDirectory directory = new PngChromaticitiesDirectory(); directory.SetInt(PngChromaticitiesDirectory.TagWhitePointX, chromaticities.GetWhitePointX()); directory.SetInt(PngChromaticitiesDirectory.TagWhitePointX, chromaticities.GetWhitePointX()); directory.SetInt(PngChromaticitiesDirectory.TagRedX, chromaticities.GetRedX()); directory.SetInt(PngChromaticitiesDirectory.TagRedY, chromaticities.GetRedY()); directory.SetInt(PngChromaticitiesDirectory.TagGreenX, chromaticities.GetGreenX()); directory.SetInt(PngChromaticitiesDirectory.TagGreenY, chromaticities.GetGreenY()); directory.SetInt(PngChromaticitiesDirectory.TagBlueX, chromaticities.GetBlueX()); directory.SetInt(PngChromaticitiesDirectory.TagBlueY, chromaticities.GetBlueY()); metadata.AddDirectory(directory); } else { if (chunkType.Equals(PngChunkType.gAMA)) { int gammaInt = new SequentialByteArrayReader(bytes).GetInt32(); PngDirectory directory = new PngDirectory(PngChunkType.gAMA); directory.SetDouble(PngDirectory.TagGamma, gammaInt / 100000.0); metadata.AddDirectory(directory); } else { if (chunkType.Equals(PngChunkType.iCCP)) { SequentialReader reader = new SequentialByteArrayReader(bytes); string profileName = reader.GetNullTerminatedString(79); PngDirectory directory = new PngDirectory(PngChunkType.iCCP); directory.SetString(PngDirectory.TagIccProfileName, profileName); sbyte compressionMethod = reader.GetInt8(); if (compressionMethod == 0) { // Only compression method allowed by the spec is zero: deflate // This assumes 1-byte-per-char, which it is by spec. int bytesLeft = bytes.Length - profileName.Length - 2; sbyte[] compressedProfile = reader.GetBytes(bytesLeft); InflaterInputStream inflateStream = new InflaterInputStream(new ByteArrayInputStream(compressedProfile)); new IccReader().Extract(new RandomAccessStreamReader(inflateStream), metadata); inflateStream.Close(); } metadata.AddDirectory(directory); } else { if (chunkType.Equals(PngChunkType.bKGD)) { PngDirectory directory = new PngDirectory(PngChunkType.bKGD); directory.SetByteArray(PngDirectory.TagBackgroundColor, bytes); metadata.AddDirectory(directory); } else { if (chunkType.Equals(PngChunkType.tEXt)) { SequentialReader reader = new SequentialByteArrayReader(bytes); string keyword = reader.GetNullTerminatedString(79); int bytesLeft = bytes.Length - keyword.Length - 1; string value = reader.GetNullTerminatedString(bytesLeft); IList<KeyValuePair> textPairs = new AList<KeyValuePair>(); textPairs.Add(new KeyValuePair(keyword, value)); PngDirectory directory = new PngDirectory(PngChunkType.iTXt); directory.SetObject(PngDirectory.TagTextualData, textPairs); metadata.AddDirectory(directory); } else { if (chunkType.Equals(PngChunkType.iTXt)) { SequentialReader reader = new SequentialByteArrayReader(bytes); string keyword = reader.GetNullTerminatedString(79); sbyte compressionFlag = reader.GetInt8(); sbyte compressionMethod = reader.GetInt8(); string languageTag = reader.GetNullTerminatedString(bytes.Length); string translatedKeyword = reader.GetNullTerminatedString(bytes.Length); int bytesLeft = bytes.Length - keyword.Length - 1 - 1 - 1 - languageTag.Length - 1 - translatedKeyword.Length - 1; string text = null; if (compressionFlag == 0) { text = reader.GetNullTerminatedString(bytesLeft); } else { if (compressionFlag == 1) { if (compressionMethod == 0) { text = StringUtil.FromStream(new InflaterInputStream(new ByteArrayInputStream(bytes, bytes.Length - bytesLeft, bytesLeft))); } else { PngDirectory directory = new PngDirectory(PngChunkType.iTXt); directory.AddError("Invalid compression method value"); metadata.AddDirectory(directory); } } else { PngDirectory directory = new PngDirectory(PngChunkType.iTXt); directory.AddError("Invalid compression flag value"); metadata.AddDirectory(directory); } } if (text != null) { if (keyword.Equals("XML:com.adobe.xmp")) { // NOTE in testing images, the XMP has parsed successfully, but we are not extracting tags from it as necessary new XmpReader().Extract(text, metadata); } else { IList<KeyValuePair> textPairs = new AList<KeyValuePair>(); textPairs.Add(new KeyValuePair(keyword, text)); PngDirectory directory = new PngDirectory(PngChunkType.iTXt); directory.SetObject(PngDirectory.TagTextualData, textPairs); metadata.AddDirectory(directory); } } } else { if (chunkType.Equals(PngChunkType.tIME)) { SequentialByteArrayReader reader = new SequentialByteArrayReader(bytes); int year = reader.GetUInt16(); int month = reader.GetUInt8() - 1; int day = reader.GetUInt8(); int hour = reader.GetUInt8(); int minute = reader.GetUInt8(); int second = reader.GetUInt8(); Sharpen.Calendar calendar = Sharpen.Calendar.GetInstance(Sharpen.Extensions.GetTimeZone("UTC")); //noinspection MagicConstant calendar.Set(year, month, day, hour, minute, second); PngDirectory directory = new PngDirectory(PngChunkType.tIME); directory.SetDate(PngDirectory.TagLastModificationTime, calendar.GetTime()); metadata.AddDirectory(directory); } else { if (chunkType.Equals(PngChunkType.pHYs)) { SequentialByteArrayReader reader = new SequentialByteArrayReader(bytes); int pixelsPerUnitX = reader.GetInt32(); int pixelsPerUnitY = reader.GetInt32(); sbyte unitSpecifier = reader.GetInt8(); PngDirectory directory = new PngDirectory(PngChunkType.pHYs); directory.SetInt(PngDirectory.TagPixelsPerUnitX, pixelsPerUnitX); directory.SetInt(PngDirectory.TagPixelsPerUnitY, pixelsPerUnitY); directory.SetInt(PngDirectory.TagUnitSpecifier, unitSpecifier); metadata.AddDirectory(directory); } else { if (chunkType.Equals(PngChunkType.sBIT)) { PngDirectory directory = new PngDirectory(PngChunkType.sBIT); directory.SetByteArray(PngDirectory.TagSignificantBits, bytes); metadata.AddDirectory(directory); } } } } } } } } } } } } } }