@Override
    public String getXmpXml(final ByteSource byteSource, final XmpImagingParameters<GifImagingParameters> params) throws ImagingException, IOException {
        try (InputStream is = byteSource.getInputStream()) {
            final GifHeaderInfo ghi = readHeader(is, null);

            if (ghi.globalColorTableFlag) {
                readColorTable(is, ghi.sizeOfGlobalColorTable);
            }

            final List<GifBlock> blocks = readBlocks(ghi, is, true, null);

            final List<String> result = new ArrayList<>();
            for (final GifBlock block : blocks) {
                if (block.blockCode != XMP_COMPLETE_CODE) {
                    continue;
                }

                final GenericGifBlock genericBlock = (GenericGifBlock) block;

                final byte[] blockBytes = genericBlock.appendSubBlocks(true);
                if (blockBytes.length < XMP_APPLICATION_ID_AND_AUTH_CODE.length) {
                    continue;
                }

                if (!BinaryFunctions.compareBytes(blockBytes, 0, XMP_APPLICATION_ID_AND_AUTH_CODE, 0, XMP_APPLICATION_ID_AND_AUTH_CODE.length)) {
                    continue;
                }

                final byte[] gifMagicTrailer = new byte[256];
                for (int magic = 0; magic <= 0xff; magic++) {
                    gifMagicTrailer[magic] = (byte) (0xff - magic);
                }

                if (blockBytes.length < XMP_APPLICATION_ID_AND_AUTH_CODE.length + gifMagicTrailer.length) {
                    continue;
                }
                if (!BinaryFunctions.compareBytes(blockBytes, blockBytes.length - gifMagicTrailer.length, gifMagicTrailer, 0, gifMagicTrailer.length)) {
                    throw new ImagingException("XMP block in GIF missing magic trailer.");
                }

                // XMP is UTF-8 encoded xml.
                final String xml = new String(blockBytes, XMP_APPLICATION_ID_AND_AUTH_CODE.length,
                        blockBytes.length - (XMP_APPLICATION_ID_AND_AUTH_CODE.length + gifMagicTrailer.length), StandardCharsets.UTF_8);
                result.add(xml);
            }

            if (result.isEmpty()) {
                return null;
            }
            if (result.size() > 1) {
                throw new ImagingException("More than one XMP Block in GIF.");
            }
            return result.get(0);
        }
    }
Extracts embedded XML metadata as XML string.
<p>

@param byteSource File containing image data.
@param params     Map of optional parameters, defined in ImagingConstants.
@return Xmp Xml as String, if present. Otherwise, returns null.
src/main/java/org/apache/commons/imaging/formats/gif/GifImageParser.java