private List<GifBlock> readBlocks(final GifHeaderInfo ghi, final InputStream is, final boolean stopBeforeImageData, final FormatCompliance formatCompliance)
            throws ImagingException, IOException {
        final List<GifBlock> result = new ArrayList<>();

        while (true) {
            final int code = is.read();

            switch (code) {
            case -1:
                throw new ImagingException("GIF: unexpected end of data");

            case IMAGE_SEPARATOR:
                final ImageDescriptor id = readImageDescriptor(ghi, code, is, stopBeforeImageData, formatCompliance);
                result.add(id);
                // if (stopBeforeImageData)
                // return result;

                break;

            case EXTENSION_CODE: {
                final int extensionCode = is.read();
                final int completeCode = (0xff & code) << 8 | 0xff & extensionCode;

                switch (extensionCode) {
                case 0xf9:
                    final GraphicControlExtension gce = readGraphicControlExtension(completeCode, is);
                    result.add(gce);
                    break;

                case COMMENT_EXTENSION:
                case PLAIN_TEXT_EXTENSION: {
                    final GenericGifBlock block = readGenericGifBlock(is, completeCode);
                    result.add(block);
                    break;
                }

                case APPLICATION_EXTENSION_LABEL: {
                    // 255 (hex 0xFF) Application
                    // Extension Label
                    final byte[] label = readSubBlock(is);

                    if (formatCompliance != null) {
                        formatCompliance.addComment("Unknown Application Extension (" + new String(label, StandardCharsets.US_ASCII) + ")", completeCode);
                    }

                    if (label.length > 0) {
                        final GenericGifBlock block = readGenericGifBlock(is, completeCode, label);
                        result.add(block);
                    }
                    break;
                }

                default: {

                    if (formatCompliance != null) {
                        formatCompliance.addComment("Unknown block", completeCode);
                    }

                    final GenericGifBlock block = readGenericGifBlock(is, completeCode);
                    result.add(block);
                    break;
                }
                }
            }
                break;

            case TERMINATOR_BYTE:
                return result;

            case 0x00: // bad byte, but keep going and see what happens
                break;

            default:
                throw new ImagingException("GIF: unknown code: " + code);
            }
        }
    }
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