@Override
    void extractMetadata(InputStream stream, ContentHandler contentHandler, Metadata metadata,
                         ParseContext parseContext)
            throws IOException, SAXException, TikaException {

        // Check for the magic header signature
        byte[] signature = new byte[4];
        IOUtils.readFully(stream, signature);
        if (signature[0] == (byte) 'B' && signature[1] == (byte) 'P' &&
                signature[2] == (byte) 'G' && signature[3] == (byte) 0xfb) {
            // Good, signature found
        } else {
            throw new TikaException("BPG magic signature invalid");
        }

        // Grab and decode the first byte
        int pdf = stream.read();

        // Pixel format: Greyscale / 4:2:0 / 4:2:2 / 4:4:4
        int pixelFormat = pdf & 0x7;
        // TODO Identify a suitable metadata key for this

        // Is there an alpha plane as well as a colour plane?
        boolean hasAlphaPlane1 = (pdf & 0x8) == 0x8;
        // TODO Identify a suitable metadata key for this+hasAlphaPlane2

        // Bit depth minus 8
        int bitDepth = (pdf >> 4) + 8;
        metadata.set(TIFF.BITS_PER_SAMPLE, Integer.toString(bitDepth));

        // Grab and decode the second byte
        int cer = stream.read();

        // Colour Space: YCbCr / RGB / YCgCo / YCbCrK / CMYK
        int colourSpace = cer & 0x15;
        switch (colourSpace) {
            case 0:
                metadata.set(Photoshop.COLOR_MODE, "YCbCr Colour");
                break;
            case 1:
                metadata.set(Photoshop.COLOR_MODE, "RGB Colour");
                break;
            case 2:
                metadata.set(Photoshop.COLOR_MODE, "YCgCo Colour");
                break;
            case 3:
                metadata.set(Photoshop.COLOR_MODE, "YCbCrK Colour");
                break;
            case 4:
                metadata.set(Photoshop.COLOR_MODE, "CMYK Colour");
                break;
        }

        // Are there extensions or not?
        boolean hasExtensions = (cer & 16) == 16;

        // Is the Alpha Plane 2 flag set?
        boolean hasAlphaPlane2 = (cer & 32) == 32;

        // cer then holds 2 more booleans - limited range, reserved

        // Width and height next
        int width = (int) EndianUtils.readUE7(stream);
        int height = (int) EndianUtils.readUE7(stream);
        metadata.set(TIFF.IMAGE_LENGTH, height);
        metadata.set(TIFF.IMAGE_WIDTH, width);

        // Picture Data length
        EndianUtils.readUE7(stream);

        // Extension Data Length, if extensions present
        long extensionDataLength = 0;
        if (hasExtensions) {
            extensionDataLength = EndianUtils.readUE7(stream);
        }

        // Alpha Data Length, if alpha used
        long alphaDataLength = 0;
        if (hasAlphaPlane1 || hasAlphaPlane2) {
            alphaDataLength = EndianUtils.readUE7(stream);
        }

        // Extension Data
        if (hasExtensions) {
            long extensionsDataSeen = 0;
            ImageMetadataExtractor metadataExtractor = new ImageMetadataExtractor(metadata);

            while (extensionsDataSeen < extensionDataLength) {
                int extensionType = (int) EndianUtils.readUE7(stream);
                int extensionLength = (int) EndianUtils.readUE7(stream);
                if (extensionLength > maxRecordLength) {
                    throw new TikaMemoryLimitException("extension length (" +
                            extensionLength + " bytes) is greater than 'maxRecordLength' (" +
                            maxRecordLength + " bytes).  If this file is not corrupt, " +
                            "consider bumping the maxRecordLength via tika-config.xml");
                }
                switch (extensionType) {
                    case EXTENSION_TAG_EXIF:
                        metadataExtractor.parseRawExif(stream, extensionLength, true);
                        break;
                    case EXTENSION_TAG_XMP:
                        handleXMP(stream, extensionLength, metadataExtractor);
                        break;
                    default:
                        IOUtils.skipFully(stream, extensionLength);
                }
                extensionsDataSeen += extensionLength;
            }
        }
        // HEVC Header + Data
        // Alpha HEVC Header + Data
        // We can't do anything with these parts
    }
Parser for the Better Portable Graphics (BPG) File Format.
<p/>
Documentation on the file format is available from
http://bellard.org/bpg/bpg_spec.txt
tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/BPGParser.java