A good way to implement mutual conversion of user-defined classes?
-
hustbaer schrieb:
I'd like to know what those types are. Without that knowledge one can only speculate as to what would be the best way to do things.
You are right. I need to convert colors from one color space to another. This needs to be done very fast.
Color is something like that:
template<idColorFormat CF, idColorComponentType CT> struct tColor;idColorFormatis something likecfRGB,cfBGR,cfGrayscale,cfIndexed.
idColorComponentTypeis something likectUChar,ctUShort,ctUInt,ctFloat,ctDouble.I have already done all possible conversions of colors from one pair of parameters
<CF,CT>to any other pair. The idea is thattColorcontain 3 or 1 components inside:template<idColorComponentType CT> tColorComponent; template<idColorComponentType CT> tColor<cfRGB,CT> { tColorComponent<CT> r,g,b; ... };So, the conversion operators of
tColordeal with differentidColorFormat, whiletColorComponentdeal with differentidColorComponentType.So (if omit
cfIndexed), I need (3*3-3)+(5*5-5) = 6+20 conversion operators. And I have done this.The problem is that I need to go further, and make color space conversion. I decided to use ONLY
cfRGBcolor format for such conversions. Color space is something like that:enum idColorSpace{csCIEXYZ, //CIE 1931 XYZ color space. X,Y,Z values are stored in R,G,B respectively csSRGBLinear, //sRGB Linear color space csSRGB, //sRGB color space csCIELAB}; //CIE 1976 LAB color space. L,A,B values are stored in G,R,B respectively template<idColorSpace T> struct tColorSpace{}; //To store idColorSpace as compile-time constant to use function overloading instead of template specialization.I think conversion functions should look like that:
template<idColorComponentType CT1, idColorComponentType CT2, idColorSpace CS1, idColorSpace CS2> inline void ConvertColor(tColor<cfRGB,CT1> const &c1, tColor<cfRGB,CT2> &c2, tColorSpace<CS1>, tColorSpace<CS2>, bool clip);Notice that I perform color space conversion at the same time as color component type conversion. This is very important to be able to do some optimizations (such as using of tables).
-
SAn schrieb:
But how to make this? I need to write something like that:
template<class T = tMyType4 or tMyType5> inline void Convert(tMyType1 const &vInput, T &vOutput) { ... }you could use a traits-template (like std::iterator_traits).
-
example:
class CA {}; class CB {}; class CC {}; class CD {}; class CE {}; namespace hidden { struct float_cat {}; struct other_cat {}; // assign categories (concepts) to the userdefined classes template < class T > struct traits {}; template <> struct traits<CA> { typedef other_cat cat; }; template <> struct traits<CB> { typedef other_cat cat; }; template <> struct traits<CC> { typedef other_cat cat; }; template <> struct traits<CD> { typedef float_cat cat; }; template <> struct traits<CE> { typedef float_cat cat; }; template < class A, class B, class CAT > void convert( A const &a, B &b, CAT c ); // specialized template-instances for category float_cat ... template < class B > void convert( CA const &a, B &b, float_cat c ) { TEST; } template < class B > void convert( CB const &a, B &b, float_cat c ) { TEST; } template < class B > void convert( CC const &a, B &b, float_cat c ) { TEST; } // ...and other_cat void convert( CA const &a, CB &b, other_cat c ) { TEST; } void convert( CA const &a, CC &b, other_cat c ) { TEST; } /*...*/ } template < class T > void convert( T const& a, T &b ) { b = a; } // call the right function by passing a dummy-instance of type traits::cat template < class A, class B > void convert( A const& a, B &b ) { hidden::convert( a, b, typename hidden::traits<B>::cat() ); }man verzeihe mein englisch...
... und dass ich tatsächlich 5 klassen deklariert hab...
-
I don't have much time to think about this right now, but you could have a look at GIL:
http://www.boost.org/doc/libs/1_36_0/libs/gil/doc/index.htmlMaybe you could use it directly, or maybe you find some clever idea in there that you could borrow

-
hustbaer schrieb:
I don't have much time to think about this right now, but you could have a look at GIL:
http://www.boost.org/doc/libs/1_36_0/libs/gil/doc/index.htmlMaybe you could use it directly, or maybe you find some clever idea in there that you could borrow

Very interesting! In fact, I'm not familiar with Boost, Iterators and other such things. So, I need something simplier. But I will look at color conversion there...
-
Do you have one instance of your class per pixel? I think this will be much overhead.
-
asdfgfvsd schrieb:
Do you have one instance of your class per pixel? I think this will be much overhead.
C++ classes do not have any overhead in particular compared to C-structs or plain old data types. They are more or less syntactic sugar, if you do not use (dynamic) polymorphism. The compiler takes care of optimizations. I think this is called the "zero cost" principle of C++.
-
I think normally int or float arrays are used to represent the pixels of an image. I have never seen an array of classes to store pixles.
Will this have the same speed?std::vector<int> pixels; ... for(...) pixels[pos+0] = r; pixels[pos+1] = g; pixels[pos+2] = b; std::vector<PixelClass> pixels; ... for(...) pixels[pos].r = r; pixels[pos].g = g; pixels[pos].b = b;
-
Will this have the same speed?
Nothing is ever the same.
But both solutions should be close.It all depends on what the compiler will optimize better, and of course on what alignment the compiler will be using for the RGB-struct. And probably a dozen other little things.
-
wandrer schrieb:
example:
[...]
man verzeihe mein englisch...
... und dass ich tatsächlich 5 klassen deklariert hab...Thank you! This is exactly what I need.
In fact, I already have traits of 3 types in my libriary:
enum idColorComponentFamily { ccfUnsignedInteger, ccfSignedInteger, ccfFloatingPoint };I just could't figure out how to use that until I have seen your example.
Now I will do that way:
ccfUnsignedInteger— depend of type,ccfSignedInteger— forbidden, because signed integers are special cases,ccfFloatingPoint— use the same algorithm for bothfloatanddouble.
-
asdfgfvsd schrieb:
I think normally int or float arrays are used to represent the pixels of an image. I have never seen an array of classes to store pixles.
Will this have the same speed?std::vector<int> pixels; ... for(...) pixels[pos+0] = r; pixels[pos+1] = g; pixels[pos+2] = b; std::vector<PixelClass> pixels; ... for(...) pixels[pos].r = r; pixels[pos].g = g; pixels[pos].b = b;Yes, this will have the same speed for most cases.