208 lines
8.9 KiB
C++
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>
|