public JpegXmpPackets GetXmpPackets()
        {
            if (!fileParsed)
            {
                ParseFile();
                fileParsed = true;
            }

            if (mainXmpPacket == null)
            {
                // The file does not contain any XMP data.
                return(null);
            }

            if (mergedXmpPacket == null)
            {
                if (extendedXmpPacket != null)
                {
                    mergedXmpPacket = XmpUtil.MergeExtendedXmp(mainXmpPacket, extendedXmpPacket);
                }
                else
                {
                    mergedXmpPacket = mainXmpPacket.Clone();
                }
            }

            return(new JpegXmpPackets(mainXmpPacket, extendedXmpPacket, mergedXmpPacket));
        }
        private void GatherXmpDataFromFile(EndianBinaryReader reader)
        {
            ushort marker = reader.ReadUInt16();

            // Check the file signature.
            if (marker == JpegMarkers.StartOfImage)
            {
                while (reader.Position < reader.Length)
                {
                    marker = reader.ReadUInt16();
                    if (marker == 0xFFFF)
                    {
                        // Skip the first padding byte and read the marker again.
                        reader.Position++;
                        continue;
                    }

                    if (marker == JpegMarkers.StartOfScan || marker == JpegMarkers.EndOfImage)
                    {
                        // The application data segments always come before these markers.
                        break;
                    }

                    ushort segmentLength = reader.ReadUInt16();

                    if (segmentLength < 2)
                    {
                        ExceptionUtil.ThrowFormatException($"JPEG segment length must be in the range of [2, 65535], actual value: { segmentLength }");
                    }

                    // The segment length field includes its own length in the total.
                    segmentLength -= sizeof(ushort);

                    if (marker == JpegMarkers.App1)
                    {
                        if (mainXmpPacket == null && segmentLength >= MainXmpSignatureLength)
                        {
                            string sig = reader.ReadAsciiString(MainXmpSignatureLength);
                            if (sig.Equals(MainXmpSignature, StringComparison.Ordinal))
                            {
                                byte[] xmpPacketBytes = reader.ReadBytes(segmentLength - MainXmpSignatureLength);

                                mainXmpPacket = new XmpPacket(xmpPacketBytes);

                                extendedXmpGuid = XmpUtil.GetExtendedXmpGuid(mainXmpPacket);
                                continue;
                            }
                            else
                            {
                                reader.Position -= MainXmpSignatureLength;
                            }
                        }

                        if (segmentLength >= ExtendedXmpPrefixLength)
                        {
                            string sig = reader.ReadAsciiString(ExtendedXmpSignatureLength);
                            if (sig.Equals(ExtendedXmpSignature, StringComparison.Ordinal))
                            {
                                string guid   = reader.ReadAsciiString(ExtendedXmpGUIDLength);
                                uint   length = reader.ReadUInt32();
                                uint   offset = reader.ReadUInt32();

                                byte[] data = reader.ReadBytes(segmentLength - ExtendedXmpPrefixLength);

                                if (extendedXmpChunks.TryGetValue(guid, out ExtendedXmp value))
                                {
                                    value.AddChunk(data, offset, length);
                                }
                                else
                                {
                                    extendedXmpChunks.Add(guid, new ExtendedXmp(data, offset, length));
                                }

                                continue;
                            }
                            else
                            {
                                segmentLength -= ExtendedXmpSignatureLength;
                            }
                        }
                    }

                    reader.Position += segmentLength;
                }
            }
        }