#pragma once #include #include #include "packing_info.h" #include #include #include "lib_begin.h" using namespace cgv::type::info; namespace cgv { namespace data { /** define standard formats, which should be used to avoid wrong assignment of component names */ enum ComponentFormat { CF_UNDEF, /// undefinded format with no component CF_R, /// red channel of color format CF_G, /// green channel of color format CF_B, /// blue channel of color format CF_A, /// alpha format CF_L, /// color format with luminance component L CF_I, /// color format with intensity component I CF_LA, /// color format with luminance and alpha components: L and A CF_IA, /// color format with intensity and alpha components: I and A CF_RGB, /// color format with components R, G and B CF_RGBA, /// color format with components R, G, B and A CF_BGR, /// color format with components B, G and R CF_BGRA, /// color format with components B, G, R and A CF_D, /// depth component CF_S, /// stencil component CF_P2D, /// point format with components px and py CF_P3D, /// point format with components px, py and pz CF_P4D, /// point format with components px, py, pz and pw CF_N2D, /// normal format with components nx and ny CF_N3D, /// normal format with components nx, ny and nz CF_T2D, /// texture coordinats format with components ts and tt CF_T3D, /// texture coordinats format with components ts, tt and tr CF_T4D, /// texture coordinats format with components ts, tt, tr and tq CF_LAST /// this is always the last entry in the component formats and used for iteration }; /** the component format inherits the information of a packing_info and adds information on the component type, which components are present in the data and in which order they appear */ class CGV_API component_format : public packing_info { protected: /// store the type id of the component type TypeId component_type; /// store all component names in one string separated with 0-chars std::string component_string; /// store the position of each component in the component string std::vector component_positions; /// extract components from component string void extract_components(); /// store the last error that appeared during parsing of a description static std::string last_error; public: /// construct from description string, see set_component_format for docu explicit component_format(const std::string& description); /** set component format from description string, which has the following syntax. If a parse error arises, return false and set the static last_error member, which can be queried with get_last_error(): \verbatim component_format <- [type] [attributes] '[' component [',' component]* ']' component <- component_name [attributes] attributes <- [':' bit_depth]['|' alignment] type <- "undef" | "bool" | "int8" | "int16" | "int32" | "uint64" | "uint8" | "uint16" | "uint32" | "uint64" | "flt16" | "flt32" | "flt64" | "string" component_name : string ... name of component, i.e. "R", "Cb", "px", ... bit_depth : unsigned int ... number of bits used to represent a component alignment : unsigned int ... number of bits to which a component is aligned \endverbatim Some examples of valid component format description strings: - \c "uint8:3|4[R,G,B,A]" ... four components represented as unsigned integers with no more than 8 bits. Actually, each component is stored with 3 bits and aligned to a bit index which is a multiple of 4 - \c "uint8[R:5,G:6,B:5]" ... three components packed into 16 bits with 5 bits for R, 6 for G and 5 for B. - \c "flt32[px,py]" ... two components of 32 bit floats - \c "[D]" ... one depth component without specified type, which defaults to "undef" and implies that the default depth format should be used. */ bool set_component_format(const std::string& description); /// comma separated list of component descriptors, for example "R,G,B" void set_components(const std::string& _components); /// returns an error string after parsing of description string has failed static const std::string& get_last_error(); /** construct component format from component type, comma or colon separated list of component names, component alignment and bit depths for packed formats*/ component_format(TypeId _component_type = TI_UNDEF, const std::string& _component_name_list = "", unsigned int align = 1, unsigned int d0 = 0, unsigned int d1 = 0, unsigned int d2 = 0, unsigned int d3 = 0); /// construct component format from component type, standard component format, component alignment and bit depths for packed formats component_format(TypeId _component_type, ComponentFormat cf, unsigned int align = 1, unsigned int d0 = 0, unsigned int d1 = 0, unsigned int d2 = 0, unsigned int d3 = 0); /// define stream out operator friend FRIEND_MEMBER_API std::ostream& operator << (std::ostream& os, const component_format& cf); /// constant access to the i-th component stored at the given location template T get(int ci, const void* ptr) const { if (is_packing()) { if (get_component_type() <= TI_INT64) { int i = packing_info::get_signed(ci, ptr); return type_access::get(&i, get_component_type()); } else { unsigned int i = packing_info::get_unsigned(ci, ptr); return type_access::get(&i, get_component_type()); } } else return type_access::get(static_cast(ptr)+ci*align(get_type_size(get_component_type()),get_component_alignment()), get_component_type()); } /// write access to the i-th component, return whether write was successful template bool set(int ci, void* ptr, const T& v) const { if (is_packing()) { if (get_component_type() <= TI_INT64) { int i = 0; return type_access::set(&i, get_component_type(), v) && packing_info::set_signed(ci, ptr, i); } else { unsigned int i = 0; return type_access::set(&i, get_component_type(), v) && packing_info::set_unsigned(ci, ptr, i); } } else return type_access::set(static_cast(ptr)+ci*align(get_type_size(get_component_type()),get_component_alignment()), get_component_type(), v); } /// return whether the component format is defined bool empty() const; /// clear the component format void clear(); /// return the packing info by simple conversion of the this pointer const packing_info& get_packing_info() const; /// set packing info by simply assigning to a converted this pointer void set_packing_info(const packing_info& pi); /// return the number of components unsigned int get_nr_components() const; /// return the index of a component given by name or -1 if not found unsigned int get_component_index(const std::string& name) const; /// return the name of the component with index i std::string get_component_name(unsigned int i) const; /// return whether the component format is one of the standard formats ComponentFormat get_standard_component_format() const; /// set component names from a comma or colon separated list of names void set_component_names(const std::string& _component_name_list); /// set the component names from a standard component format void set_component_format(ComponentFormat _cf); /// return the component type TypeId get_component_type() const; /// set the component type void set_component_type(TypeId _type_id); /// return the size of one entry of components in bytes unsigned int get_entry_size() const; /// comparison between component formats bool operator == (const component_format& cf) const; /// comparison between component formats bool operator != (const component_format& cf) const; }; /** stream out operator writes the component format in the syntax of description strings as defined in the docu of set_component_format(). */ extern CGV_API std::ostream& operator << (std::ostream& os, const component_format& cf); /// default function to check whether fmt1 is a better match to fmt than fmt2 extern CGV_API bool fmt1_compares_better(const component_format& fmt, const component_format& fmt1, const component_format& fmt2); /** find the best matching format in a list of formats described by strings and return index of best match */ extern CGV_API unsigned int find_best_match( const component_format& fmt, const char** format_descriptions, const component_format* fmt0 = 0, bool (*fmt1_better_match)( const component_format& fmt, const component_format& fmt1, const component_format& fmt2) = fmt1_compares_better); } } #include