CGII/framework/include/cgv/data/component_format.h
2018-05-17 16:01:02 +02:00

208 lines
8.9 KiB
C++

#pragma once
#include <cgv/type/info/type_id.h>
#include <cgv/type/info/type_access.h>
#include "packing_info.h"
#include <string>
#include <vector>
#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<unsigned short> 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 <typename T>
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<T>::get(&i, get_component_type());
}
else {
unsigned int i = packing_info::get_unsigned(ci, ptr);
return type_access<T>::get(&i, get_component_type());
}
}
else
return type_access<T>::get(static_cast<const unsigned char*>(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 <typename T>
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<T>::set(&i, get_component_type(), v) && packing_info::set_signed(ci, ptr, i);
}
else {
unsigned int i = 0;
return type_access<T>::set(&i, get_component_type(), v) && packing_info::set_unsigned(ci, ptr, i);
}
}
else
return type_access<T>::set(static_cast<unsigned char*>(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 <cgv/config/lib_end.h>