WebP: C++98/STL parsing library

File extension

webp

KS implementation details

License: CC0-1.0
Minimal Kaitai Struct required: 0.11

References

This page hosts a formal specification of WebP using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Usage

Runtime library

All C++98/STL code generated by Kaitai Struct depends on the Kaitai Struct runtime library for C++/STL. You must add this dependency to your project before you can parse or serialize any data.

For C++, the easiest way is to clone the runtime library sources and build them along with your project.

Code

Using Kaitai Struct in C++/STL usually consists of 3 steps.

  1. We need to create an STL input stream (std::istream). One can open local file for that, or use existing std::string or char* buffer.
    #include <fstream>
    
    std::ifstream is("path/to/local/file.webp", std::ifstream::binary);
    
    #include <sstream>
    
    std::istringstream is(str);
    
    #include <sstream>
    
    const char buf[] = { ... };
    std::string str(buf, sizeof buf);
    std::istringstream is(str);
    
  2. We need to wrap our input stream into Kaitai stream:
    #include "kaitai/kaitaistream.h"
    
    kaitai::kstream ks(&is);
    
  3. And finally, we can invoke the parsing:
    webp_t data(&ks);
    

After that, one can get various attributes from the structure by invoking getter methods like:

data.magic() // => get magic

C++98/STL source code to parse WebP

webp.h

#ifndef WEBP_H_
#define WEBP_H_

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

class webp_t;

#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#include <set>
#include <vector>

#if KAITAI_STRUCT_VERSION < 11000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.11 or later is required"
#endif

/**
 * \sa https://developers.google.com/speed/webp/docs/riff_container Source
 */

class webp_t : public kaitai::kstruct {

public:
    class alph_t;
    class anim_t;
    class anmf_t;
    class chunk_t;
    class chunks_t;
    class vp8_t;
    class vp8l_t;
    class vp8x_t;
    class xmp_t;

    enum chunk_names_t {
        CHUNK_NAMES_XMP_VAR = 5262680,
        CHUNK_NAMES_VP8 = 540561494,
        CHUNK_NAMES_XMP = 542133592,
        CHUNK_NAMES_EXIF = 1179211845,
        CHUNK_NAMES_ANMF = 1179471425,
        CHUNK_NAMES_ALPH = 1213221953,
        CHUNK_NAMES_VP8L = 1278758998,
        CHUNK_NAMES_FRGM = 1296519750,
        CHUNK_NAMES_ANIM = 1296649793,
        CHUNK_NAMES_ICCP = 1346585417,
        CHUNK_NAMES_VP8X = 1480085590
    };
    static bool _is_defined_chunk_names_t(chunk_names_t v);

private:
    static const std::set<chunk_names_t> _values_chunk_names_t;
    static std::set<chunk_names_t> _build_values_chunk_names_t();

public:

    enum compression_method_t {
        COMPRESSION_METHOD_NONE = 0,
        COMPRESSION_METHOD_WEBP_LOSSLESS = 1
    };
    static bool _is_defined_compression_method_t(compression_method_t v);

private:
    static const std::set<compression_method_t> _values_compression_method_t;
    static std::set<compression_method_t> _build_values_compression_method_t();

public:

    enum filtering_method_t {
        FILTERING_METHOD_NONE = 0,
        FILTERING_METHOD_HORIZONTAL = 1,
        FILTERING_METHOD_VERTICAL = 2,
        FILTERING_METHOD_GRADIENT = 3
    };
    static bool _is_defined_filtering_method_t(filtering_method_t v);

private:
    static const std::set<filtering_method_t> _values_filtering_method_t;
    static std::set<filtering_method_t> _build_values_filtering_method_t();

public:

    enum preprocessing_t {
        PREPROCESSING_NONE = 0,
        PREPROCESSING_LEVEL_REDUCTION = 1
    };
    static bool _is_defined_preprocessing_t(preprocessing_t v);

private:
    static const std::set<preprocessing_t> _values_preprocessing_t;
    static std::set<preprocessing_t> _build_values_preprocessing_t();

public:

    webp_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, webp_t* p__root = 0);

private:
    void _read();
    void _clean_up();

public:
    ~webp_t();

    class alph_t : public kaitai::kstruct {

    public:

        alph_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent = 0, webp_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~alph_t();

    private:
        uint64_t m_reserved;
        preprocessing_t m_preprocessing;
        filtering_method_t m_filtering;
        compression_method_t m_compression;
        std::string m_data;
        webp_t* m__root;
        webp_t::chunk_t* m__parent;

    public:
        uint64_t reserved() const { return m_reserved; }
        preprocessing_t preprocessing() const { return m_preprocessing; }
        filtering_method_t filtering() const { return m_filtering; }
        compression_method_t compression() const { return m_compression; }
        std::string data() const { return m_data; }
        webp_t* _root() const { return m__root; }
        webp_t::chunk_t* _parent() const { return m__parent; }
    };

    /**
     * \sa https://developers.google.com/speed/webp/docs/riff_container#animation Source
     */

    class anim_t : public kaitai::kstruct {

    public:
        class bg_color_t;

        anim_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent = 0, webp_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~anim_t();

        class bg_color_t : public kaitai::kstruct {

        public:

            bg_color_t(kaitai::kstream* p__io, webp_t::anim_t* p__parent = 0, webp_t* p__root = 0);

        private:
            void _read();
            void _clean_up();

        public:
            ~bg_color_t();

        private:
            uint8_t m_blue;
            uint8_t m_green;
            uint8_t m_red;
            uint8_t m_alpha;
            webp_t* m__root;
            webp_t::anim_t* m__parent;

        public:
            uint8_t blue() const { return m_blue; }
            uint8_t green() const { return m_green; }
            uint8_t red() const { return m_red; }
            uint8_t alpha() const { return m_alpha; }
            webp_t* _root() const { return m__root; }
            webp_t::anim_t* _parent() const { return m__parent; }
        };

    private:
        bg_color_t* m_background_color;
        uint16_t m_loop_count;
        webp_t* m__root;
        webp_t::chunk_t* m__parent;

    public:
        bg_color_t* background_color() const { return m_background_color; }
        uint16_t loop_count() const { return m_loop_count; }
        webp_t* _root() const { return m__root; }
        webp_t::chunk_t* _parent() const { return m__parent; }
    };

    class anmf_t : public kaitai::kstruct {

    public:

        anmf_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent = 0, webp_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~anmf_t();

    private:
        bool f_frame_height;
        int32_t m_frame_height;

    public:
        int32_t frame_height();

    private:
        bool f_frame_width;
        int32_t m_frame_width;

    public:
        int32_t frame_width();

    private:
        bool f_frame_x;
        int32_t m_frame_x;

    public:
        int32_t frame_x();

    private:
        bool f_frame_y;
        int32_t m_frame_y;

    public:
        int32_t frame_y();

    private:
        uint64_t m_frame_x_div_2;
        uint64_t m_frame_y_div_2;
        uint64_t m_frame_width_minus_1;
        uint64_t m_frame_height_minus_1;
        uint64_t m_duration;
        uint64_t m_reserved;
        bool m_blending_method;
        bool m_disposal_method;
        std::string m_data;
        webp_t* m__root;
        webp_t::chunk_t* m__parent;

    public:
        uint64_t frame_x_div_2() const { return m_frame_x_div_2; }
        uint64_t frame_y_div_2() const { return m_frame_y_div_2; }
        uint64_t frame_width_minus_1() const { return m_frame_width_minus_1; }
        uint64_t frame_height_minus_1() const { return m_frame_height_minus_1; }
        uint64_t duration() const { return m_duration; }
        uint64_t reserved() const { return m_reserved; }
        bool blending_method() const { return m_blending_method; }
        bool disposal_method() const { return m_disposal_method; }
        std::string data() const { return m_data; }
        webp_t* _root() const { return m__root; }
        webp_t::chunk_t* _parent() const { return m__parent; }
    };

    class chunk_t : public kaitai::kstruct {

    public:

        chunk_t(kaitai::kstream* p__io, webp_t::chunks_t* p__parent = 0, webp_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~chunk_t();

    private:
        chunk_names_t m_name;
        uint32_t m_len_data;
        kaitai::kstruct* m_data;
        bool n_data;

    public:
        bool _is_null_data() { data(); return n_data; };

    private:
        std::string m_padding;
        bool n_padding;

    public:
        bool _is_null_padding() { padding(); return n_padding; };

    private:
        webp_t* m__root;
        webp_t::chunks_t* m__parent;
        std::string m__raw_data;
        kaitai::kstream* m__io__raw_data;

    public:
        chunk_names_t name() const { return m_name; }
        uint32_t len_data() const { return m_len_data; }
        kaitai::kstruct* data() const { return m_data; }
        std::string padding() const { return m_padding; }
        webp_t* _root() const { return m__root; }
        webp_t::chunks_t* _parent() const { return m__parent; }
        std::string _raw_data() const { return m__raw_data; }
        kaitai::kstream* _io__raw_data() const { return m__io__raw_data; }
    };

    class chunks_t : public kaitai::kstruct {

    public:

        chunks_t(kaitai::kstream* p__io, webp_t* p__parent = 0, webp_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~chunks_t();

    private:
        std::vector<chunk_t*>* m_chunks;
        webp_t* m__root;
        webp_t* m__parent;

    public:
        std::vector<chunk_t*>* chunks() const { return m_chunks; }
        webp_t* _root() const { return m__root; }
        webp_t* _parent() const { return m__parent; }
    };

    /**
     * \sa https://www.rfc-editor.org/rfc/rfc6386#section-9.1 Source
     */

    class vp8_t : public kaitai::kstruct {

    public:

        vp8_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent = 0, webp_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~vp8_t();

    private:
        bool m_frame_type;
        uint64_t m_version;
        bool m_show_frame;
        uint64_t m_len_first_partition;
        std::string m_start_code;
        uint64_t m_width;
        uint64_t m_horizontal_scale;
        uint64_t m_height;
        uint64_t m_vertical_scale;
        std::string m_data;
        webp_t* m__root;
        webp_t::chunk_t* m__parent;

    public:
        bool frame_type() const { return m_frame_type; }
        uint64_t version() const { return m_version; }
        bool show_frame() const { return m_show_frame; }
        uint64_t len_first_partition() const { return m_len_first_partition; }
        std::string start_code() const { return m_start_code; }
        uint64_t width() const { return m_width; }
        uint64_t horizontal_scale() const { return m_horizontal_scale; }
        uint64_t height() const { return m_height; }
        uint64_t vertical_scale() const { return m_vertical_scale; }
        std::string data() const { return m_data; }
        webp_t* _root() const { return m__root; }
        webp_t::chunk_t* _parent() const { return m__parent; }
    };

    /**
     * \sa https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification Source
     */

    class vp8l_t : public kaitai::kstruct {

    public:

        vp8l_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent = 0, webp_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~vp8l_t();

    private:
        bool f_image_height;
        int32_t m_image_height;

    public:
        int32_t image_height();

    private:
        bool f_image_width;
        int32_t m_image_width;

    public:
        int32_t image_width();

    private:
        uint8_t m_signature;
        uint64_t m_image_width_minus_1;
        uint64_t m_image_height_minus_1;
        bool m_alpha_is_used;
        uint64_t m_version_number;
        std::string m_data;
        webp_t* m__root;
        webp_t::chunk_t* m__parent;

    public:
        uint8_t signature() const { return m_signature; }
        uint64_t image_width_minus_1() const { return m_image_width_minus_1; }
        uint64_t image_height_minus_1() const { return m_image_height_minus_1; }

        /**
         * A hint only - it should not impact decoding. It should be `false` when
         * all alpha values are 255 in the picture, and `true` otherwise.
         */
        bool alpha_is_used() const { return m_alpha_is_used; }
        uint64_t version_number() const { return m_version_number; }
        std::string data() const { return m_data; }
        webp_t* _root() const { return m__root; }
        webp_t::chunk_t* _parent() const { return m__parent; }
    };

    class vp8x_t : public kaitai::kstruct {

    public:

        vp8x_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent = 0, webp_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~vp8x_t();

    private:
        bool f_canvas_height;
        int32_t m_canvas_height;

    public:
        int32_t canvas_height();

    private:
        bool f_canvas_width;
        int32_t m_canvas_width;

    public:
        int32_t canvas_width();

    private:
        uint64_t m_reserved1;
        bool m_icc_profile;
        bool m_alpha;
        bool m_exif;
        bool m_xmp;
        bool m_animation;
        bool m_reserved2;
        uint64_t m_reserved3;
        uint64_t m_canvas_width_minus_1;
        uint64_t m_canvas_height_minus_1;
        webp_t* m__root;
        webp_t::chunk_t* m__parent;

    public:
        uint64_t reserved1() const { return m_reserved1; }
        bool icc_profile() const { return m_icc_profile; }
        bool alpha() const { return m_alpha; }
        bool exif() const { return m_exif; }
        bool xmp() const { return m_xmp; }
        bool animation() const { return m_animation; }
        bool reserved2() const { return m_reserved2; }
        uint64_t reserved3() const { return m_reserved3; }
        uint64_t canvas_width_minus_1() const { return m_canvas_width_minus_1; }
        uint64_t canvas_height_minus_1() const { return m_canvas_height_minus_1; }
        webp_t* _root() const { return m__root; }
        webp_t::chunk_t* _parent() const { return m__parent; }
    };

    class xmp_t : public kaitai::kstruct {

    public:

        xmp_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent = 0, webp_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~xmp_t();

    private:
        std::string m_data;
        webp_t* m__root;
        webp_t::chunk_t* m__parent;

    public:
        std::string data() const { return m_data; }
        webp_t* _root() const { return m__root; }
        webp_t::chunk_t* _parent() const { return m__parent; }
    };

private:
    std::string m_magic;
    uint32_t m_len_data;
    std::string m_webp;
    chunks_t* m_payload;
    webp_t* m__root;
    kaitai::kstruct* m__parent;
    std::string m__raw_payload;
    kaitai::kstream* m__io__raw_payload;

public:
    std::string magic() const { return m_magic; }
    uint32_t len_data() const { return m_len_data; }
    std::string webp() const { return m_webp; }
    chunks_t* payload() const { return m_payload; }
    webp_t* _root() const { return m__root; }
    kaitai::kstruct* _parent() const { return m__parent; }
    std::string _raw_payload() const { return m__raw_payload; }
    kaitai::kstream* _io__raw_payload() const { return m__io__raw_payload; }
};

#endif  // WEBP_H_

webp.cpp

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

#include "webp.h"
#include "kaitai/exceptions.h"
std::set<webp_t::chunk_names_t> webp_t::_build_values_chunk_names_t() {
    std::set<webp_t::chunk_names_t> _t;
    _t.insert(webp_t::CHUNK_NAMES_XMP_VAR);
    _t.insert(webp_t::CHUNK_NAMES_VP8);
    _t.insert(webp_t::CHUNK_NAMES_XMP);
    _t.insert(webp_t::CHUNK_NAMES_EXIF);
    _t.insert(webp_t::CHUNK_NAMES_ANMF);
    _t.insert(webp_t::CHUNK_NAMES_ALPH);
    _t.insert(webp_t::CHUNK_NAMES_VP8L);
    _t.insert(webp_t::CHUNK_NAMES_FRGM);
    _t.insert(webp_t::CHUNK_NAMES_ANIM);
    _t.insert(webp_t::CHUNK_NAMES_ICCP);
    _t.insert(webp_t::CHUNK_NAMES_VP8X);
    return _t;
}
const std::set<webp_t::chunk_names_t> webp_t::_values_chunk_names_t = webp_t::_build_values_chunk_names_t();
bool webp_t::_is_defined_chunk_names_t(webp_t::chunk_names_t v) {
    return webp_t::_values_chunk_names_t.find(v) != webp_t::_values_chunk_names_t.end();
}
std::set<webp_t::compression_method_t> webp_t::_build_values_compression_method_t() {
    std::set<webp_t::compression_method_t> _t;
    _t.insert(webp_t::COMPRESSION_METHOD_NONE);
    _t.insert(webp_t::COMPRESSION_METHOD_WEBP_LOSSLESS);
    return _t;
}
const std::set<webp_t::compression_method_t> webp_t::_values_compression_method_t = webp_t::_build_values_compression_method_t();
bool webp_t::_is_defined_compression_method_t(webp_t::compression_method_t v) {
    return webp_t::_values_compression_method_t.find(v) != webp_t::_values_compression_method_t.end();
}
std::set<webp_t::filtering_method_t> webp_t::_build_values_filtering_method_t() {
    std::set<webp_t::filtering_method_t> _t;
    _t.insert(webp_t::FILTERING_METHOD_NONE);
    _t.insert(webp_t::FILTERING_METHOD_HORIZONTAL);
    _t.insert(webp_t::FILTERING_METHOD_VERTICAL);
    _t.insert(webp_t::FILTERING_METHOD_GRADIENT);
    return _t;
}
const std::set<webp_t::filtering_method_t> webp_t::_values_filtering_method_t = webp_t::_build_values_filtering_method_t();
bool webp_t::_is_defined_filtering_method_t(webp_t::filtering_method_t v) {
    return webp_t::_values_filtering_method_t.find(v) != webp_t::_values_filtering_method_t.end();
}
std::set<webp_t::preprocessing_t> webp_t::_build_values_preprocessing_t() {
    std::set<webp_t::preprocessing_t> _t;
    _t.insert(webp_t::PREPROCESSING_NONE);
    _t.insert(webp_t::PREPROCESSING_LEVEL_REDUCTION);
    return _t;
}
const std::set<webp_t::preprocessing_t> webp_t::_values_preprocessing_t = webp_t::_build_values_preprocessing_t();
bool webp_t::_is_defined_preprocessing_t(webp_t::preprocessing_t v) {
    return webp_t::_values_preprocessing_t.find(v) != webp_t::_values_preprocessing_t.end();
}

webp_t::webp_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, webp_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root ? p__root : this;
    m_payload = 0;
    m__io__raw_payload = 0;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void webp_t::_read() {
    m_magic = m__io->read_bytes(4);
    if (!(m_magic == std::string("\x52\x49\x46\x46", 4))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x52\x49\x46\x46", 4), m_magic, m__io, std::string("/seq/0"));
    }
    m_len_data = m__io->read_u4le();
    m_webp = m__io->read_bytes(4);
    if (!(m_webp == std::string("\x57\x45\x42\x50", 4))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x57\x45\x42\x50", 4), m_webp, m__io, std::string("/seq/2"));
    }
    m__raw_payload = m__io->read_bytes(len_data() - 4);
    m__io__raw_payload = new kaitai::kstream(m__raw_payload);
    m_payload = new chunks_t(m__io__raw_payload, this, m__root);
}

webp_t::~webp_t() {
    _clean_up();
}

void webp_t::_clean_up() {
    if (m__io__raw_payload) {
        delete m__io__raw_payload; m__io__raw_payload = 0;
    }
    if (m_payload) {
        delete m_payload; m_payload = 0;
    }
}

webp_t::alph_t::alph_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent, webp_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void webp_t::alph_t::_read() {
    m_reserved = m__io->read_bits_int_be(2);
    if (!(m_reserved == 0)) {
        throw kaitai::validation_not_equal_error<uint64_t>(0, m_reserved, m__io, std::string("/types/alph/seq/0"));
    }
    m_preprocessing = static_cast<webp_t::preprocessing_t>(m__io->read_bits_int_be(2));
    if (!webp_t::_is_defined_preprocessing_t(m_preprocessing)) {
        throw kaitai::validation_not_in_enum_error<webp_t::preprocessing_t>(m_preprocessing, m__io, std::string("/types/alph/seq/1"));
    }
    m_filtering = static_cast<webp_t::filtering_method_t>(m__io->read_bits_int_be(2));
    m_compression = static_cast<webp_t::compression_method_t>(m__io->read_bits_int_be(2));
    if (!webp_t::_is_defined_compression_method_t(m_compression)) {
        throw kaitai::validation_not_in_enum_error<webp_t::compression_method_t>(m_compression, m__io, std::string("/types/alph/seq/3"));
    }
    m__io->align_to_byte();
    m_data = m__io->read_bytes_full();
}

webp_t::alph_t::~alph_t() {
    _clean_up();
}

void webp_t::alph_t::_clean_up() {
}

webp_t::anim_t::anim_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent, webp_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_background_color = 0;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void webp_t::anim_t::_read() {
    m_background_color = new bg_color_t(m__io, this, m__root);
    m_loop_count = m__io->read_u2le();
}

webp_t::anim_t::~anim_t() {
    _clean_up();
}

void webp_t::anim_t::_clean_up() {
    if (m_background_color) {
        delete m_background_color; m_background_color = 0;
    }
}

webp_t::anim_t::bg_color_t::bg_color_t(kaitai::kstream* p__io, webp_t::anim_t* p__parent, webp_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void webp_t::anim_t::bg_color_t::_read() {
    m_blue = m__io->read_u1();
    m_green = m__io->read_u1();
    m_red = m__io->read_u1();
    m_alpha = m__io->read_u1();
}

webp_t::anim_t::bg_color_t::~bg_color_t() {
    _clean_up();
}

void webp_t::anim_t::bg_color_t::_clean_up() {
}

webp_t::anmf_t::anmf_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent, webp_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_frame_height = false;
    f_frame_width = false;
    f_frame_x = false;
    f_frame_y = false;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void webp_t::anmf_t::_read() {
    m_frame_x_div_2 = m__io->read_bits_int_le(24);
    m_frame_y_div_2 = m__io->read_bits_int_le(24);
    m_frame_width_minus_1 = m__io->read_bits_int_le(24);
    m_frame_height_minus_1 = m__io->read_bits_int_le(24);
    m_duration = m__io->read_bits_int_le(24);
    m_reserved = m__io->read_bits_int_be(6);
    if (!(m_reserved == 0)) {
        throw kaitai::validation_not_equal_error<uint64_t>(0, m_reserved, m__io, std::string("/types/anmf/seq/5"));
    }
    m_blending_method = m__io->read_bits_int_be(1);
    m_disposal_method = m__io->read_bits_int_be(1);
    m__io->align_to_byte();
    m_data = m__io->read_bytes_full();
}

webp_t::anmf_t::~anmf_t() {
    _clean_up();
}

void webp_t::anmf_t::_clean_up() {
}

int32_t webp_t::anmf_t::frame_height() {
    if (f_frame_height)
        return m_frame_height;
    f_frame_height = true;
    m_frame_height = frame_height_minus_1() + 1;
    return m_frame_height;
}

int32_t webp_t::anmf_t::frame_width() {
    if (f_frame_width)
        return m_frame_width;
    f_frame_width = true;
    m_frame_width = frame_width_minus_1() + 1;
    return m_frame_width;
}

int32_t webp_t::anmf_t::frame_x() {
    if (f_frame_x)
        return m_frame_x;
    f_frame_x = true;
    m_frame_x = frame_x_div_2() * 2;
    return m_frame_x;
}

int32_t webp_t::anmf_t::frame_y() {
    if (f_frame_y)
        return m_frame_y;
    f_frame_y = true;
    m_frame_y = frame_y_div_2() * 2;
    return m_frame_y;
}

webp_t::chunk_t::chunk_t(kaitai::kstream* p__io, webp_t::chunks_t* p__parent, webp_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__io__raw_data = 0;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void webp_t::chunk_t::_read() {
    m_name = static_cast<webp_t::chunk_names_t>(m__io->read_u4le());
    if (!webp_t::_is_defined_chunk_names_t(m_name)) {
        throw kaitai::validation_not_in_enum_error<webp_t::chunk_names_t>(m_name, m__io, std::string("/types/chunk/seq/0"));
    }
    m_len_data = m__io->read_u4le();
    n_data = true;
    switch (name()) {
    case webp_t::CHUNK_NAMES_ALPH: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new alph_t(m__io__raw_data, this, m__root);
        break;
    }
    case webp_t::CHUNK_NAMES_ANIM: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new anim_t(m__io__raw_data, this, m__root);
        break;
    }
    case webp_t::CHUNK_NAMES_ANMF: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new anmf_t(m__io__raw_data, this, m__root);
        break;
    }
    case webp_t::CHUNK_NAMES_VP8: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new vp8_t(m__io__raw_data, this, m__root);
        break;
    }
    case webp_t::CHUNK_NAMES_VP8L: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new vp8l_t(m__io__raw_data, this, m__root);
        break;
    }
    case webp_t::CHUNK_NAMES_VP8X: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new vp8x_t(m__io__raw_data, this, m__root);
        break;
    }
    case webp_t::CHUNK_NAMES_XMP: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new xmp_t(m__io__raw_data, this, m__root);
        break;
    }
    case webp_t::CHUNK_NAMES_XMP_VAR: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new xmp_t(m__io__raw_data, this, m__root);
        break;
    }
    default: {
        m__raw_data = m__io->read_bytes(len_data());
        break;
    }
    }
    n_padding = true;
    if (kaitai::kstream::mod(len_data(), 2) != 0) {
        n_padding = false;
        m_padding = m__io->read_bytes(1);
        if (!(m_padding == std::string("\x00", 1))) {
            throw kaitai::validation_not_equal_error<std::string>(std::string("\x00", 1), m_padding, m__io, std::string("/types/chunk/seq/3"));
        }
    }
}

webp_t::chunk_t::~chunk_t() {
    _clean_up();
}

void webp_t::chunk_t::_clean_up() {
    if (!n_data) {
        if (m__io__raw_data) {
            delete m__io__raw_data; m__io__raw_data = 0;
        }
        if (m_data) {
            delete m_data; m_data = 0;
        }
    }
    if (!n_padding) {
    }
}

webp_t::chunks_t::chunks_t(kaitai::kstream* p__io, webp_t* p__parent, webp_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_chunks = 0;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void webp_t::chunks_t::_read() {
    m_chunks = new std::vector<chunk_t*>();
    {
        int i = 0;
        while (!m__io->is_eof()) {
            m_chunks->push_back(new chunk_t(m__io, this, m__root));
            i++;
        }
    }
}

webp_t::chunks_t::~chunks_t() {
    _clean_up();
}

void webp_t::chunks_t::_clean_up() {
    if (m_chunks) {
        for (std::vector<chunk_t*>::iterator it = m_chunks->begin(); it != m_chunks->end(); ++it) {
            delete *it;
        }
        delete m_chunks; m_chunks = 0;
    }
}

webp_t::vp8_t::vp8_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent, webp_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void webp_t::vp8_t::_read() {
    m_frame_type = m__io->read_bits_int_le(1);
    if (!(m_frame_type == false)) {
        throw kaitai::validation_not_equal_error<bool>(false, m_frame_type, m__io, std::string("/types/vp8/seq/0"));
    }
    m_version = m__io->read_bits_int_le(3);
    if (!(m_version <= 3)) {
        throw kaitai::validation_greater_than_error<uint64_t>(3, m_version, m__io, std::string("/types/vp8/seq/1"));
    }
    m_show_frame = m__io->read_bits_int_le(1);
    m_len_first_partition = m__io->read_bits_int_le(19);
    m__io->align_to_byte();
    m_start_code = m__io->read_bytes(3);
    if (!(m_start_code == std::string("\x9D\x01\x2A", 3))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x9D\x01\x2A", 3), m_start_code, m__io, std::string("/types/vp8/seq/4"));
    }
    m_width = m__io->read_bits_int_le(14);
    m_horizontal_scale = m__io->read_bits_int_le(2);
    m_height = m__io->read_bits_int_le(14);
    m_vertical_scale = m__io->read_bits_int_le(2);
    m__io->align_to_byte();
    m_data = m__io->read_bytes_full();
}

webp_t::vp8_t::~vp8_t() {
    _clean_up();
}

void webp_t::vp8_t::_clean_up() {
}

webp_t::vp8l_t::vp8l_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent, webp_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_image_height = false;
    f_image_width = false;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void webp_t::vp8l_t::_read() {
    m_signature = m__io->read_u1();
    if (!(m_signature == 47)) {
        throw kaitai::validation_not_equal_error<uint8_t>(47, m_signature, m__io, std::string("/types/vp8l/seq/0"));
    }
    m_image_width_minus_1 = m__io->read_bits_int_le(14);
    m_image_height_minus_1 = m__io->read_bits_int_le(14);
    m_alpha_is_used = m__io->read_bits_int_le(1);
    m_version_number = m__io->read_bits_int_le(3);
    if (!(m_version_number == 0)) {
        throw kaitai::validation_not_equal_error<uint64_t>(0, m_version_number, m__io, std::string("/types/vp8l/seq/4"));
    }
    m__io->align_to_byte();
    m_data = m__io->read_bytes_full();
}

webp_t::vp8l_t::~vp8l_t() {
    _clean_up();
}

void webp_t::vp8l_t::_clean_up() {
}

int32_t webp_t::vp8l_t::image_height() {
    if (f_image_height)
        return m_image_height;
    f_image_height = true;
    m_image_height = image_height_minus_1() + 1;
    return m_image_height;
}

int32_t webp_t::vp8l_t::image_width() {
    if (f_image_width)
        return m_image_width;
    f_image_width = true;
    m_image_width = image_width_minus_1() + 1;
    return m_image_width;
}

webp_t::vp8x_t::vp8x_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent, webp_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_canvas_height = false;
    f_canvas_width = false;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void webp_t::vp8x_t::_read() {
    m_reserved1 = m__io->read_bits_int_be(2);
    if (!(m_reserved1 == 0)) {
        throw kaitai::validation_not_equal_error<uint64_t>(0, m_reserved1, m__io, std::string("/types/vp8x/seq/0"));
    }
    m_icc_profile = m__io->read_bits_int_be(1);
    m_alpha = m__io->read_bits_int_be(1);
    m_exif = m__io->read_bits_int_be(1);
    m_xmp = m__io->read_bits_int_be(1);
    m_animation = m__io->read_bits_int_be(1);
    m_reserved2 = m__io->read_bits_int_be(1);
    if (!(m_reserved2 == false)) {
        throw kaitai::validation_not_equal_error<bool>(false, m_reserved2, m__io, std::string("/types/vp8x/seq/6"));
    }
    m_reserved3 = m__io->read_bits_int_be(24);
    if (!(m_reserved3 == 0)) {
        throw kaitai::validation_not_equal_error<uint64_t>(0, m_reserved3, m__io, std::string("/types/vp8x/seq/7"));
    }
    m_canvas_width_minus_1 = m__io->read_bits_int_le(24);
    m_canvas_height_minus_1 = m__io->read_bits_int_le(24);
    if (!(m_canvas_height_minus_1 <= 4294967295UL / canvas_width() - 1)) {
        throw kaitai::validation_greater_than_error<uint64_t>(4294967295UL / canvas_width() - 1, m_canvas_height_minus_1, m__io, std::string("/types/vp8x/seq/9"));
    }
}

webp_t::vp8x_t::~vp8x_t() {
    _clean_up();
}

void webp_t::vp8x_t::_clean_up() {
}

int32_t webp_t::vp8x_t::canvas_height() {
    if (f_canvas_height)
        return m_canvas_height;
    f_canvas_height = true;
    m_canvas_height = canvas_height_minus_1() + 1;
    return m_canvas_height;
}

int32_t webp_t::vp8x_t::canvas_width() {
    if (f_canvas_width)
        return m_canvas_width;
    f_canvas_width = true;
    m_canvas_width = canvas_width_minus_1() + 1;
    return m_canvas_width;
}

webp_t::xmp_t::xmp_t(kaitai::kstream* p__io, webp_t::chunk_t* p__parent, webp_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void webp_t::xmp_t::_read() {
    m_data = kaitai::kstream::bytes_to_str(m__io->read_bytes_full(), "UTF-8");
}

webp_t::xmp_t::~xmp_t() {
    _clean_up();
}

void webp_t::xmp_t::_clean_up() {
}