public virtual void TestToString() { Com.Drew.Metadata.Metadata metadata = new Com.Drew.Metadata.Metadata(); Sharpen.Tests.AreEqual("Metadata (0 directories)", Sharpen.Extensions.ConvertToString(metadata)); metadata.AddDirectory(new ExifIFD0Directory()); Sharpen.Tests.AreEqual("Metadata (1 directory)", Sharpen.Extensions.ConvertToString(metadata)); metadata.AddDirectory(new ExifSubIFDDirectory()); Sharpen.Tests.AreEqual("Metadata (2 directories)", Sharpen.Extensions.ConvertToString(metadata)); }
public virtual void Extract(sbyte[] segmentBytes, Com.Drew.Metadata.Metadata metadata, JpegSegmentType segmentType) { JpegDirectory directory = new JpegDirectory(); metadata.AddDirectory(directory); // The value of TAG_COMPRESSION_TYPE is determined by the segment type found directory.SetInt(JpegDirectory.TagCompressionType, segmentType.byteValue - JpegSegmentType.Sof0.byteValue); SequentialReader reader = new SequentialByteArrayReader(segmentBytes); try { directory.SetInt(JpegDirectory.TagDataPrecision, reader.GetUInt8()); directory.SetInt(JpegDirectory.TagImageHeight, reader.GetUInt16()); directory.SetInt(JpegDirectory.TagImageWidth, reader.GetUInt16()); short componentCount = reader.GetUInt8(); directory.SetInt(JpegDirectory.TagNumberOfComponents, componentCount); // for each component, there are three bytes of data: // 1 - Component ID: 1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q // 2 - Sampling factors: bit 0-3 vertical, 4-7 horizontal // 3 - Quantization table number for (int i = 0; i < (int)componentCount; i++) { int componentId = reader.GetUInt8(); int samplingFactorByte = reader.GetUInt8(); int quantizationTableNumber = reader.GetUInt8(); JpegComponent component = new JpegComponent(componentId, samplingFactorByte, quantizationTableNumber); directory.SetObject(JpegDirectory.TagComponentData1 + i, component); } } catch (IOException ex) { directory.AddError(ex.Message); } }
public virtual void TestHasErrors() { ExifSubIFDDirectory directory = new ExifSubIFDDirectory(); directory.AddError("Test Error 1"); Com.Drew.Metadata.Metadata metadata = new Com.Drew.Metadata.Metadata(); Sharpen.Tests.IsFalse(metadata.HasErrors()); metadata.AddDirectory(directory); Sharpen.Tests.IsTrue(metadata.HasErrors()); }
public virtual void ReadJpegSegments([NotNull] Iterable <sbyte[]> segments, [NotNull] Com.Drew.Metadata.Metadata metadata, [NotNull] JpegSegmentType segmentType) { foreach (sbyte[] segmentBytes in segments) { JpegCommentDirectory directory = new JpegCommentDirectory(); metadata.AddDirectory(directory); // The entire contents of the directory are the comment directory.SetString(JpegCommentDirectory.TagComment, Sharpen.Runtime.GetStringForBytes(segmentBytes)); } }
public virtual void ProcessChunk([NotNull] string fourCC, [NotNull] sbyte[] payload) { // System.out.println("Chunk " + fourCC + " " + payload.length + " bytes"); if (fourCC.Equals("EXIF")) { new ExifReader().Extract(new ByteArrayReader(payload), _metadata); } else { if (fourCC.Equals("ICCP")) { new IccReader().Extract(new ByteArrayReader(payload), _metadata); } else { if (fourCC.Equals("XMP ")) { new XmpReader().Extract(payload, _metadata); } else { if (fourCC.Equals("VP8X") && payload.Length == 10) { RandomAccessReader reader = new ByteArrayReader(payload); reader.SetMotorolaByteOrder(false); try { // Flags // boolean hasFragments = reader.getBit(0); bool isAnimation = reader.GetBit(1); // boolean hasXmp = reader.getBit(2); // boolean hasExif = reader.getBit(3); bool hasAlpha = reader.GetBit(4); // boolean hasIcc = reader.getBit(5); // Image size int widthMinusOne = reader.GetInt24(4); int heightMinusOne = reader.GetInt24(7); WebpDirectory directory = new WebpDirectory(); directory.SetInt(WebpDirectory.TagImageWidth, widthMinusOne + 1); directory.SetInt(WebpDirectory.TagImageHeight, heightMinusOne + 1); directory.SetBoolean(WebpDirectory.TagHasAlpha, hasAlpha); directory.SetBoolean(WebpDirectory.TagIsAnimation, isAnimation); _metadata.AddDirectory(directory); } catch (IOException e) { Sharpen.Runtime.PrintStackTrace(e, System.Console.Error); } } } } } }
public virtual void Extract([NotNull] SequentialReader reader, [NotNull] Com.Drew.Metadata.Metadata metadata) { reader.SetMotorolaByteOrder(false); PcxDirectory directory = new PcxDirectory(); metadata.AddDirectory(directory); try { sbyte identifier = reader.GetInt8(); if (identifier != unchecked ((int)(0x0A))) { throw new ImageProcessingException("Invalid PCX identifier byte"); } directory.SetInt(PcxDirectory.TagVersion, reader.GetInt8()); sbyte encoding = reader.GetInt8(); if (encoding != unchecked ((int)(0x01))) { throw new ImageProcessingException("Invalid PCX encoding byte"); } directory.SetInt(PcxDirectory.TagBitsPerPixel, reader.GetUInt8()); directory.SetInt(PcxDirectory.TagXmin, reader.GetUInt16()); directory.SetInt(PcxDirectory.TagYmin, reader.GetUInt16()); directory.SetInt(PcxDirectory.TagXmax, reader.GetUInt16()); directory.SetInt(PcxDirectory.TagYmax, reader.GetUInt16()); directory.SetInt(PcxDirectory.TagHorizontalDpi, reader.GetUInt16()); directory.SetInt(PcxDirectory.TagVerticalDpi, reader.GetUInt16()); directory.SetByteArray(PcxDirectory.TagPalette, reader.GetBytes(48)); reader.Skip(1); directory.SetInt(PcxDirectory.TagColorPlanes, reader.GetUInt8()); directory.SetInt(PcxDirectory.TagBytesPerLine, reader.GetUInt16()); int paletteType = reader.GetUInt16(); if (paletteType != 0) { directory.SetInt(PcxDirectory.TagPaletteType, paletteType); } int hScrSize = reader.GetUInt16(); if (hScrSize != 0) { directory.SetInt(PcxDirectory.TagHscrSize, hScrSize); } int vScrSize = reader.GetUInt16(); if (vScrSize != 0) { directory.SetInt(PcxDirectory.TagVscrSize, vScrSize); } } catch (Exception ex) { directory.AddError("Exception reading PCX file metadata: " + ex.Message); } }
protected internal DirectoryTiffHandler(Com.Drew.Metadata.Metadata metadata, Type initialDirectoryClass) { _metadata = metadata; try { _currentDirectory = (Directory)System.Activator.CreateInstance(initialDirectoryClass); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (MemberAccessException e) { throw new RuntimeException(e); } _metadata.AddDirectory(_currentDirectory); }
protected internal virtual void PushDirectory([NotNull] Type directoryClass) { _directoryStack.Push(_currentDirectory); try { _currentDirectory = (Directory)System.Activator.CreateInstance(directoryClass); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (MemberAccessException e) { throw new RuntimeException(e); } _metadata.AddDirectory(_currentDirectory); }
/// <summary> /// Performs the XMP data extraction, adding found values to the specified instance of /// <see cref="Com.Drew.Metadata.Metadata"/> /// . /// <p> /// The extraction is done with Adobe's XMPCore library. /// </summary> public virtual void Extract([NotNull] string xmpString, [NotNull] Com.Drew.Metadata.Metadata metadata) { XmpDirectory directory = new XmpDirectory(); try { XMPMeta xmpMeta = XMPMetaFactory.ParseFromString(xmpString); ProcessXmpTags(directory, xmpMeta); } catch (XMPException e) { directory.AddError("Error processing XMP data: " + e.Message); } if (!directory.IsEmpty()) { metadata.AddDirectory(directory); } }
/// <exception cref="System.IO.IOException"/> public virtual void Read([NotNull] FilePath file, [NotNull] Com.Drew.Metadata.Metadata metadata) { if (!file.IsFile()) { throw new IOException("File object must reference a file"); } if (!file.Exists()) { throw new IOException("File does not exist"); } if (!file.CanRead()) { throw new IOException("File is not readable"); } FileMetadataDirectory directory = new FileMetadataDirectory(); directory.SetString(FileMetadataDirectory.TagFileName, file.GetName()); directory.SetLong(FileMetadataDirectory.TagFileSize, file.Length()); directory.SetDate(FileMetadataDirectory.TagFileModifiedDate, Sharpen.Extensions.CreateDate(file.LastModified())); metadata.AddDirectory(directory); }
public virtual void Extract([NotNull] SequentialReader reader, [NotNull] Com.Drew.Metadata.Metadata metadata) { Com.Drew.Metadata.Directory directory = new AdobeJpegDirectory(); metadata.AddDirectory(directory); try { reader.SetMotorolaByteOrder(false); if (!reader.GetString(Preamble.Length).Equals(Preamble)) { directory.AddError("Invalid Adobe JPEG data header."); return; } directory.SetInt(AdobeJpegDirectory.TagDctEncodeVersion, reader.GetUInt16()); directory.SetInt(AdobeJpegDirectory.TagApp14Flags0, reader.GetUInt16()); directory.SetInt(AdobeJpegDirectory.TagApp14Flags1, reader.GetUInt16()); directory.SetInt(AdobeJpegDirectory.TagColorTransform, reader.GetInt8()); } catch (IOException ex) { directory.AddError("IO exception processing data: " + ex.Message); } }
public virtual void Extract([NotNull] SequentialReader reader, [NotNull] Com.Drew.Metadata.Metadata metadata) { PsdHeaderDirectory directory = new PsdHeaderDirectory(); metadata.AddDirectory(directory); // FILE HEADER SECTION try { int signature = reader.GetInt32(); if (signature != unchecked ((int)(0x38425053))) { // "8BPS" directory.AddError("Invalid PSD file signature"); return; } int version = reader.GetUInt16(); if (version != 1 && version != 2) { directory.AddError("Invalid PSD file version (must be 1 or 2)"); return; } // 6 reserved bytes are skipped here. They should be zero. reader.Skip(6); int channelCount = reader.GetUInt16(); directory.SetInt(PsdHeaderDirectory.TagChannelCount, channelCount); // even though this is probably an unsigned int, the max height in practice is 300,000 int imageHeight = reader.GetInt32(); directory.SetInt(PsdHeaderDirectory.TagImageHeight, imageHeight); // even though this is probably an unsigned int, the max width in practice is 300,000 int imageWidth = reader.GetInt32(); directory.SetInt(PsdHeaderDirectory.TagImageWidth, imageWidth); int bitsPerChannel = reader.GetUInt16(); directory.SetInt(PsdHeaderDirectory.TagBitsPerChannel, bitsPerChannel); int colorMode = reader.GetUInt16(); directory.SetInt(PsdHeaderDirectory.TagColorMode, colorMode); } catch (IOException) { directory.AddError("Unable to read PSD header"); return; } // COLOR MODE DATA SECTION try { long sectionLength = reader.GetUInt32(); /* * Only indexed color and duotone (see the mode field in the File header section) have color mode data. * For all other modes, this section is just the 4-byte length field, which is set to zero. * * Indexed color images: length is 768; color data contains the color table for the image, * in non-interleaved order. * Duotone images: color data contains the duotone specification (the format of which is not documented). * Other applications that read Photoshop files can treat a duotone image as a gray image, * and just preserve the contents of the duotone information when reading and writing the * file. */ reader.Skip(sectionLength); } catch (IOException) { return; } // IMAGE RESOURCES SECTION try { long sectionLength = reader.GetUInt32(); System.Diagnostics.Debug.Assert((sectionLength <= int.MaxValue)); new PhotoshopReader().Extract(reader, (int)sectionLength, metadata); } catch (IOException) { } }
/// <summary> /// Performs the IPTC data extraction, adding found values to the specified instance of /// <see cref="Com.Drew.Metadata.Metadata"/> /// . /// </summary> public virtual void Extract([NotNull] SequentialReader reader, [NotNull] Com.Drew.Metadata.Metadata metadata, long length) { IptcDirectory directory = new IptcDirectory(); metadata.AddDirectory(directory); int offset = 0; // for each tag while (offset < length) { // identifies start of a tag short startByte; try { startByte = reader.GetUInt8(); offset++; } catch (IOException) { directory.AddError("Unable to read starting byte of IPTC tag"); return; } if (startByte != unchecked ((int)(0x1c))) { // NOTE have seen images where there was one extra byte at the end, giving // offset==length at this point, which is not worth logging as an error. if (offset != length) { directory.AddError("Invalid IPTC tag marker at offset " + (offset - 1) + ". Expected '0x1c' but got '0x" + Sharpen.Extensions.ToHexString(startByte) + "'."); } return; } // we need at least five bytes left to read a tag if (offset + 5 >= length) { directory.AddError("Too few bytes remain for a valid IPTC tag"); return; } int directoryType; int tagType; int tagByteCount; try { directoryType = reader.GetUInt8(); tagType = reader.GetUInt8(); // TODO support Extended DataSet Tag (see 1.5(c), p14, IPTC-IIMV4.2.pdf) tagByteCount = reader.GetUInt16(); offset += 4; } catch (IOException) { directory.AddError("IPTC data segment ended mid-way through tag descriptor"); return; } if (offset + tagByteCount > length) { directory.AddError("Data for tag extends beyond end of IPTC segment"); return; } try { ProcessTag(reader, directory, directoryType, tagType, tagByteCount); } catch (IOException) { directory.AddError("Error processing IPTC tag"); return; } offset += tagByteCount; } }
public virtual void Extract([NotNull] SequentialReader reader, [NotNull] Com.Drew.Metadata.Metadata metadata) { BmpHeaderDirectory directory = new BmpHeaderDirectory(); metadata.AddDirectory(directory); // FILE HEADER // // 2 - magic number (0x42 0x4D = "BM") // 4 - size of BMP file in bytes // 2 - reserved // 2 - reserved // 4 - the offset of the pixel array // // BITMAP INFORMATION HEADER // // The first four bytes of the header give the size, which is a discriminator of the actual header format. // See this for more information http://en.wikipedia.org/wiki/BMP_file_format // // BITMAPINFOHEADER (size = 40) // // 4 - size of header // 4 - pixel width (signed) // 4 - pixel height (signed) // 2 - number of colour planes (must be set to 1) // 2 - number of bits per pixel // 4 - compression being used (needs decoding) // 4 - pixel data length (not total file size, just pixel array) // 4 - horizontal resolution, pixels/meter (signed) // 4 - vertical resolution, pixels/meter (signed) // 4 - number of colours in the palette (0 means no palette) // 4 - number of important colours (generally ignored) // // BITMAPCOREHEADER (size = 12) // // 4 - size of header // 2 - pixel width // 2 - pixel height // 2 - number of colour planes (must be set to 1) // 2 - number of bits per pixel // // COMPRESSION VALUES // // 0 = None // 1 = RLE 8-bit/pixel // 2 = RLE 4-bit/pixel // 3 = Bit field (or Huffman 1D if BITMAPCOREHEADER2 (size 64)) // 4 = JPEG (or RLE-24 if BITMAPCOREHEADER2 (size 64)) // 5 = PNG // 6 = Bit field reader.SetMotorolaByteOrder(false); try { int magicNumber = reader.GetUInt16(); if (magicNumber != unchecked ((int)(0x4D42))) { directory.AddError("Invalid BMP magic number"); return; } // skip past the rest of the file header reader.Skip(4 + 2 + 2 + 4); int headerSize = reader.GetInt32(); directory.SetInt(BmpHeaderDirectory.TagHeaderSize, headerSize); // We expect the header size to be either 40 (BITMAPINFOHEADER) or 12 (BITMAPCOREHEADER) if (headerSize == 40) { // BITMAPINFOHEADER directory.SetInt(BmpHeaderDirectory.TagImageWidth, reader.GetInt32()); directory.SetInt(BmpHeaderDirectory.TagImageHeight, reader.GetInt32()); directory.SetInt(BmpHeaderDirectory.TagColourPlanes, reader.GetInt16()); directory.SetInt(BmpHeaderDirectory.TagBitsPerPixel, reader.GetInt16()); directory.SetInt(BmpHeaderDirectory.TagCompression, reader.GetInt32()); // skip the pixel data length reader.Skip(4); directory.SetInt(BmpHeaderDirectory.TagXPixelsPerMeter, reader.GetInt32()); directory.SetInt(BmpHeaderDirectory.TagYPixelsPerMeter, reader.GetInt32()); directory.SetInt(BmpHeaderDirectory.TagPaletteColourCount, reader.GetInt32()); directory.SetInt(BmpHeaderDirectory.TagImportantColourCount, reader.GetInt32()); } else { if (headerSize == 12) { directory.SetInt(BmpHeaderDirectory.TagImageWidth, reader.GetInt16()); directory.SetInt(BmpHeaderDirectory.TagImageHeight, reader.GetInt16()); directory.SetInt(BmpHeaderDirectory.TagColourPlanes, reader.GetInt16()); directory.SetInt(BmpHeaderDirectory.TagBitsPerPixel, reader.GetInt16()); } else { directory.AddError("Unexpected DIB header size: " + headerSize); } } } catch (IOException) { directory.AddError("Unable to read BMP header"); } }
public virtual void Extract([NotNull] SequentialReader reader, [NotNull] Com.Drew.Metadata.Metadata metadata) { GifHeaderDirectory directory = new GifHeaderDirectory(); metadata.AddDirectory(directory); // FILE HEADER // // 3 - signature: "GIF" // 3 - version: either "87a" or "89a" // // LOGICAL SCREEN DESCRIPTOR // // 2 - pixel width // 2 - pixel height // 1 - screen and color map information flags (0 is LSB) // 0-2 Size of the global color table // 3 Color table sort flag (89a only) // 4-6 Color resolution // 7 Global color table flag // 1 - background color index // 1 - pixel aspect ratio reader.SetMotorolaByteOrder(false); try { string signature = reader.GetString(3); if (!signature.Equals("GIF")) { directory.AddError("Invalid GIF file signature"); return; } string version = reader.GetString(3); if (!version.Equals(Gif87aVersionIdentifier) && !version.Equals(Gif89aVersionIdentifier)) { directory.AddError("Unexpected GIF version"); return; } directory.SetString(GifHeaderDirectory.TagGifFormatVersion, version); directory.SetInt(GifHeaderDirectory.TagImageWidth, reader.GetUInt16()); directory.SetInt(GifHeaderDirectory.TagImageHeight, reader.GetUInt16()); short flags = reader.GetUInt8(); // First three bits = (BPP - 1) int colorTableSize = 1 << ((flags & 7) + 1); directory.SetInt(GifHeaderDirectory.TagColorTableSize, colorTableSize); if (version.Equals(Gif89aVersionIdentifier)) { bool isColorTableSorted = (flags & 8) != 0; directory.SetBoolean(GifHeaderDirectory.TagIsColorTableSorted, isColorTableSorted); } int bitsPerPixel = ((flags & unchecked ((int)(0x70))) >> 4) + 1; directory.SetInt(GifHeaderDirectory.TagBitsPerPixel, bitsPerPixel); bool hasGlobalColorTable = (flags & unchecked ((int)(0xf))) != 0; directory.SetBoolean(GifHeaderDirectory.TagHasGlobalColorTable, hasGlobalColorTable); directory.SetInt(GifHeaderDirectory.TagTransparentColorIndex, reader.GetUInt8()); int aspectRatioByte = reader.GetUInt8(); if (aspectRatioByte != 0) { float pixelAspectRatio = (float)((aspectRatioByte + 15d) / 64d); directory.SetFloat(GifHeaderDirectory.TagPixelAspectRatio, pixelAspectRatio); } } catch (IOException) { directory.AddError("Unable to read BMP header"); } }
public virtual void Extract([NotNull] SequentialReader reader, int length, [NotNull] Com.Drew.Metadata.Metadata metadata) { PhotoshopDirectory directory = new PhotoshopDirectory(); metadata.AddDirectory(directory); // Data contains a sequence of Image Resource Blocks (IRBs): // // 4 bytes - Signature "8BIM" // 2 bytes - Resource identifier // String - Pascal string, padded to make length even // 4 bytes - Size of resource data which follows // Data - The resource data, padded to make size even // // http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_pgfId-1037504 int pos = 0; while (pos < length) { try { // 4 bytes for the signature. Should always be "8BIM". string signature = reader.GetString(4); if (!signature.Equals("8BIM")) { throw new ImageProcessingException("Expecting 8BIM marker"); } pos += 4; // 2 bytes for the resource identifier (tag type). int tagType = reader.GetUInt16(); // segment type pos += 2; // A variable number of bytes holding a pascal string (two leading bytes for length). short descriptionLength = reader.GetUInt8(); pos += 1; // Some basic bounds checking if (descriptionLength < 0 || descriptionLength + pos > length) { throw new ImageProcessingException("Invalid string length"); } // We don't use the string value here reader.Skip(descriptionLength); pos += descriptionLength; // The number of bytes is padded with a trailing zero, if needed, to make the size even. if (pos % 2 != 0) { reader.Skip(1); pos++; } // 4 bytes for the size of the resource data that follows. int byteCount = reader.GetInt32(); pos += 4; // The resource data. sbyte[] tagBytes = reader.GetBytes(byteCount); pos += byteCount; // The number of bytes is padded with a trailing zero, if needed, to make the size even. if (pos % 2 != 0) { reader.Skip(1); pos++; } if (tagType == PhotoshopDirectory.TagIptc) { new IptcReader().Extract(new SequentialByteArrayReader(tagBytes), metadata, tagBytes.Length); } else { if (tagType == PhotoshopDirectory.TagIccProfileBytes) { new IccReader().Extract(new ByteArrayReader(tagBytes), metadata); } else { if (tagType == PhotoshopDirectory.TagExifData1 || tagType == PhotoshopDirectory.TagExifData3) { new ExifReader().Extract(new ByteArrayReader(tagBytes), metadata); } else { if (tagType == PhotoshopDirectory.TagXmpData) { new XmpReader().Extract(tagBytes, metadata); } else { directory.SetByteArray(tagType, tagBytes); } } } } if (tagType >= unchecked ((int)(0x0fa0)) && tagType <= unchecked ((int)(0x1387))) { PhotoshopDirectory._tagNameMap.Put(tagType, Sharpen.Extensions.StringFormat("Plug-in %d Data", tagType - unchecked ((int)(0x0fa0)) + 1)); } } catch (Exception ex) { directory.AddError(ex.Message); return; } } }
/// <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); } } } } } } } } } } } } } }
public virtual void Extract([NotNull] SequentialReader reader, [NotNull] Com.Drew.Metadata.Metadata metadata) { reader.SetMotorolaByteOrder(false); int type; int imageCount; // Read header (ICONDIR structure) try { int reserved = reader.GetUInt16(); if (reserved != 0) { IcoDirectory directory = new IcoDirectory(); directory.AddError("Invalid header bytes"); metadata.AddDirectory(directory); return; } type = reader.GetUInt16(); if (type != 1 && type != 2) { IcoDirectory directory = new IcoDirectory(); directory.AddError("Invalid type " + type + " -- expecting 1 or 2"); metadata.AddDirectory(directory); return; } imageCount = reader.GetUInt16(); if (imageCount == 0) { IcoDirectory directory = new IcoDirectory(); directory.AddError("Image count cannot be zero"); metadata.AddDirectory(directory); return; } } catch (IOException ex) { IcoDirectory directory = new IcoDirectory(); directory.AddError("Exception reading ICO file metadata: " + ex.Message); metadata.AddDirectory(directory); return; } // Read each embedded image IcoDirectory directory_1 = null; try { for (int imageIndex = 0; imageIndex < imageCount; imageIndex++) { directory_1 = new IcoDirectory(); metadata.AddDirectory(directory_1); directory_1.SetInt(IcoDirectory.TagImageType, type); directory_1.SetInt(IcoDirectory.TagImageWidth, reader.GetUInt8()); directory_1.SetInt(IcoDirectory.TagImageHeight, reader.GetUInt8()); directory_1.SetInt(IcoDirectory.TagColourPaletteSize, reader.GetUInt8()); // Ignore this byte (normally zero, though .NET's System.Drawing.Icon.Save method writes 255) reader.GetUInt8(); if (type == 1) { // Icon directory_1.SetInt(IcoDirectory.TagColourPlanes, reader.GetUInt16()); directory_1.SetInt(IcoDirectory.TagBitsPerPixel, reader.GetUInt16()); } else { // Cursor directory_1.SetInt(IcoDirectory.TagCursorHotspotX, reader.GetUInt16()); directory_1.SetInt(IcoDirectory.TagCursorHotspotY, reader.GetUInt16()); } directory_1.SetLong(IcoDirectory.TagImageSizeBytes, reader.GetUInt32()); directory_1.SetLong(IcoDirectory.TagImageOffsetBytes, reader.GetUInt32()); } } catch (IOException ex) { System.Diagnostics.Debug.Assert((directory_1 != null)); directory_1.AddError("Exception reading ICO file metadata: " + ex.Message); } }