diff --git a/src/include/OpenImageIO/imagebuf.h b/src/include/OpenImageIO/imagebuf.h index e209dba08e..4fd4a4db30 100644 --- a/src/include/OpenImageIO/imagebuf.h +++ b/src/include/OpenImageIO/imagebuf.h @@ -1604,6 +1604,30 @@ class OIIO_API ImageBuf { m_nchannels); } + /// Set the number of deep data samples at this pixel. (Only use + /// this if deep_alloc() has not yet been called on the buffer.) + void set_deep_samples(int n) + { + ensure_writable(); + return const_cast(m_ib)->set_deep_samples(m_x, m_y, m_z, + n); + } + + /// Set the deep data value of sample s of channel c. (Only use this + /// if deep_alloc() has been called.) + void set_deep_value(int c, int s, float value) + { + ensure_writable(); + return const_cast(m_ib)->set_deep_value(m_x, m_y, m_z, c, + s, value); + } + void set_deep_value(int c, int s, uint32_t value) + { + ensure_writable(); + return const_cast(m_ib)->set_deep_value(m_x, m_y, m_z, c, + s, value); + } + protected: friend class ImageBuf; friend class ImageBufImpl; @@ -1799,30 +1823,6 @@ class OIIO_API ImageBuf { TypeDesc::BASETYPE(m_pixeltype), m_proxydata, m_nchannels); } - - /// Set the number of deep data samples at this pixel. (Only use - /// this if deep_alloc() has not yet been called on the buffer.) - void set_deep_samples(int n) - { - ensure_writable(); - return const_cast(m_ib)->set_deep_samples(m_x, m_y, m_z, - n); - } - - /// Set the deep data value of sample s of channel c. (Only use this - /// if deep_alloc() has been called.) - void set_deep_value(int c, int s, float value) - { - ensure_writable(); - return const_cast(m_ib)->set_deep_value(m_x, m_y, m_z, c, - s, value); - } - void set_deep_value(int c, int s, uint32_t value) - { - ensure_writable(); - return const_cast(m_ib)->set_deep_value(m_x, m_y, m_z, c, - s, value); - } }; diff --git a/src/include/OpenImageIO/imagebufalgo_util.h b/src/include/OpenImageIO/imagebufalgo_util.h index 97924cc936..afbc944208 100644 --- a/src/include/OpenImageIO/imagebufalgo_util.h +++ b/src/include/OpenImageIO/imagebufalgo_util.h @@ -275,8 +275,16 @@ inline TypeDesc type_merge (TypeDesc a, TypeDesc b, TypeDesc c) } +inline bool is_common_pixel_type(TypeDesc t) +{ + return t.basetype == TypeDesc::FLOAT || t.basetype == TypeDesc::UINT8 + || t.basetype == TypeDesc::UINT16 || t.basetype == TypeDesc::HALF; +} + + // Macro to call a type-specialized version func(R,...) +// instantiated for EVERY pixel type we support. #define OIIO_DISPATCH_TYPES(ret,name,func,type,R,...) \ switch (type.basetype) { \ case TypeDesc::FLOAT : \ @@ -329,6 +337,8 @@ inline TypeDesc type_merge (TypeDesc a, TypeDesc b, TypeDesc c) } // Macro to call a type-specialized version func(R,...). +// instantiated for EVERY combination of pixel type we support. +// Note: The combinatorics here are brutal! Only do this if necessary. #define OIIO_DISPATCH_TYPES2(ret,name,func,Rtype,Atype,R,...) \ switch (Rtype.basetype) { \ case TypeDesc::FLOAT : \ @@ -380,10 +390,10 @@ inline TypeDesc type_merge (TypeDesc a, TypeDesc b, TypeDesc c) /* other types: punt and convert to float, then copy back */ \ ImageBuf Rtmp; \ if ((R).initialized()) \ - Rtmp.copy (R, TypeDesc::FLOAT); \ + Rtmp.copy(R, TypeFloat); \ ret = func (Rtmp, __VA_ARGS__); \ if (ret) \ - (R).copy (Rtmp); \ + (R).copy(Rtmp, (R).pixeltype()); \ else \ (R).errorfmt("{}", Rtmp.geterror()); \ } \ @@ -400,101 +410,199 @@ inline TypeDesc type_merge (TypeDesc a, TypeDesc b, TypeDesc c) ret = func (R, A, __VA_ARGS__); break; \ case TypeDesc::UINT16: \ ret = func (R, A, __VA_ARGS__); break; \ - default: { \ - /* other types: punt and convert to float, then copy back */ \ - ImageBuf Atmp; \ - Atmp.copy (A, TypeDesc::FLOAT); \ - ret = func (R, Atmp, __VA_ARGS__); \ - } \ + default: \ + OIIO_DASSERT(0 && "bad type"); \ + ret = false; \ + break; \ } // Macro to call a type-specialized version func(R,A,...) for -// the most common types, and even for uncommon types when src and dst types -// are identical. It will auto-convert remaining rare cases to float. -#define OIIO_DISPATCH_COMMON_TYPES2(ret,name,func,Rtype,Atype,R,A,...) \ - if (Rtype == Atype) { \ - /* All data types, when Rtype == Atype */ \ - switch (Atype.basetype) { \ - case TypeDesc::FLOAT : \ - ret = func (R, A, __VA_ARGS__); break; \ - case TypeDesc::UINT8 : \ - ret = func (R, A, __VA_ARGS__); break; \ - case TypeDesc::UINT16: \ - ret = func (R, A, __VA_ARGS__); break; \ - case TypeDesc::HALF : \ - ret = func (R, A, __VA_ARGS__); break; \ - case TypeDesc::INT8 : \ - ret = func (R, A, __VA_ARGS__); break; \ - case TypeDesc::INT16 : \ - ret = func (R, A, __VA_ARGS__); break; \ - case TypeDesc::UINT : \ - ret = func (R, A, __VA_ARGS__); break; \ - case TypeDesc::INT : \ - ret = func (R, A, __VA_ARGS__); break; \ - case TypeDesc::DOUBLE : \ - ret = func (R, A, __VA_ARGS__); break; \ - default: \ - (R).errorfmt("{}: Unsupported pixel data format '{}'", name, Atype); \ - ret = false; \ +// the most common types. It will auto-convert remaining rare cases to float. +#define OIIO_DISPATCH_COMMON_TYPES2_FULL(ret, name, func, Rtype_, Atype_, R, A, ...)\ + { \ + OIIO_ASSERT((R).initialized()); \ + ret = false; \ + auto Rptr = &R; \ + auto Aptr = &A; \ + ImageBuf Rtmp, Atmp; \ + TypeDesc Rtype = Rtype_, Atype = Atype_; \ + if (!ImageBufAlgo::is_common_pixel_type(Atype)) { \ + Atype = TypeDesc::FLOAT; \ + Atmp.copy(A, Atype); \ + Aptr = &Atmp; \ + } \ + if (!ImageBufAlgo::is_common_pixel_type(Rtype)) { \ + Rtype = TypeDesc::FLOAT; \ + Rtmp.copy(R, Rtype); \ + Rptr = &Rtmp; \ + } \ + if (Rtype == TypeFloat) { \ + OIIO_DISPATCH_COMMON_TYPES2_HELP(ret, name, func, float, Atype, \ + *Rptr, *Aptr, __VA_ARGS__); \ + } else if (Rtype == TypeUInt8) { \ + OIIO_DISPATCH_COMMON_TYPES2_HELP(ret, name, func, uint8_t, Atype, \ + *Rptr, *Aptr, __VA_ARGS__); \ + } else if (Rtype == TypeHalf) { \ + OIIO_DISPATCH_COMMON_TYPES2_HELP(ret, name, func, half, Atype, \ + *Rptr, *Aptr, __VA_ARGS__); \ + } else if (Rtype == TypeUInt16) { \ + OIIO_DISPATCH_COMMON_TYPES2_HELP(ret, name, func, uint16_t, Atype, \ + *Rptr, *Aptr, __VA_ARGS__); \ + } else { \ + OIIO_DASSERT(0 && "bad type"); \ + } \ + if (Rptr != &(R)) { \ + /* If we used Rtmp, copy pixels or errors to the real R */ \ + if (ret) \ + (R).copy(*Rptr, (R).pixeltype()); \ + else \ + (R).errorfmt("{}", Rptr->geterror()); \ + } \ + } + + +// Macro to call a type-specialized version func(R,A,...) for +// the most common types. It will auto-convert remaining rare cases to float. +#define OIIO_DISPATCH_COMMON_TYPES2(ret, name, func, Rtype_, Atype_, R, A, ...)\ + { \ + OIIO_ASSERT((R).initialized()); \ + ret = false; \ + auto Rptr = &R; \ + auto Aptr = &A; \ + ImageBuf Rtmp, Atmp; \ + TypeDesc Rtype = Rtype_, Atype = Atype_; \ + if (!ImageBufAlgo::is_common_pixel_type(Atype)) { \ + Atype = TypeDesc::FLOAT; \ + Atmp.copy(A, Atype); \ + Aptr = &Atmp; \ + } \ + if (!ImageBufAlgo::is_common_pixel_type(Rtype) || (Rtype != Atype && Rtype != TypeFloat)) { \ + Rtype = TypeDesc::FLOAT; \ + Rtmp.copy(R, Rtype); \ + Rptr = &Rtmp; \ + } \ + OIIO_ASSERT(Rtype == TypeFloat || Rtype == Atype); \ + if (Rtype == TypeFloat) { \ + switch (Atype.basetype) { \ + case TypeDesc::FLOAT : \ + ret = func (*Rptr, *Aptr, __VA_ARGS__); break; \ + case TypeDesc::UINT8 : \ + ret = func (*Rptr, *Aptr, __VA_ARGS__); break; \ + case TypeDesc::HALF : \ + ret = func (*Rptr, *Aptr, __VA_ARGS__); break; \ + case TypeDesc::UINT16: \ + ret = func (*Rptr, *Aptr, __VA_ARGS__); break; \ + default: \ + OIIO_DASSERT(0 && "bad type"); \ + ret = false; \ + break; \ + } \ + } else if (Rtype == TypeUInt8) { \ + switch (Atype.basetype) { \ + case TypeDesc::FLOAT : \ + ret = func (*Rptr, *Aptr, __VA_ARGS__); break; \ + case TypeDesc::UINT8 : \ + ret = func (*Rptr, *Aptr, __VA_ARGS__); break; \ + /* case TypeDesc::HALF :*/ \ + /* ret = func (*Rptr, *Aptr, __VA_ARGS__); break;*/ \ + /* case TypeDesc::UINT16:*/ \ + /* ret = func (*Rptr, *Aptr, __VA_ARGS__); break;*/ \ + default: \ + OIIO_DASSERT(0 && "bad type"); \ + ret = false; \ + break; \ + } \ + } else if (Rtype == TypeHalf) { \ + switch (Atype.basetype) { \ + case TypeDesc::FLOAT : \ + ret = func (*Rptr, *Aptr, __VA_ARGS__); break; \ + /* case TypeDesc::UINT8 : */ \ + /* ret = func (*Rptr, *Aptr, __VA_ARGS__); break; */ \ + case TypeDesc::HALF : \ + ret = func (*Rptr, *Aptr, __VA_ARGS__); break; \ + /* case TypeDesc::UINT16: */ \ + /* ret = func (*Rptr, *Aptr, __VA_ARGS__); break; */ \ + default: \ + OIIO_DASSERT(0 && "bad type"); \ + ret = false; \ + break; \ + } \ + } else if (Rtype == TypeUInt16) { \ + switch (Atype.basetype) { \ + case TypeDesc::FLOAT : \ + ret = func (*Rptr, *Aptr, __VA_ARGS__); break; \ + /*case TypeDesc::UINT8 : */ \ + /* ret = func (*Rptr, *Aptr, __VA_ARGS__); break; */ \ + /*case TypeDesc::HALF : */ \ + /* ret = func (*Rptr, *Aptr, __VA_ARGS__); break; */ \ + case TypeDesc::UINT16: \ + ret = func (*Rptr, *Aptr, __VA_ARGS__); break; \ + default: \ + OIIO_DASSERT(0 && "bad type"); \ + ret = false; \ + break; \ + } \ + } else { \ + OIIO_DASSERT(0 && "bad type"); \ + } \ + if (Rptr != &(R)) { \ + /* If we used Rtmp, copy pixels or errors to the real R */ \ + if (ret) \ + (R).copy(*Rptr, (R).pixeltype()); \ + else \ + (R).errorfmt("{}", Rptr->geterror()); \ + } \ + } + + +// Macro to call a type-specialized version func(R,A,...) for +// the most common types. It will auto-convert other cases to/from float. +// This is the case for when we don't actually write to the read-only R image. +#define OIIO_DISPATCH_COMMON_TYPES2_CONST(ret,name,func,Rtype_,Atype_,R,A,...) \ + { \ + OIIO_ASSERT((R).initialized()); \ + ret = false; \ + auto Rptr = &R; \ + auto Aptr = &A; \ + ImageBuf Rtmp, Atmp; \ + TypeDesc Rtype = Rtype_, Atype = Atype_; \ + if (!ImageBufAlgo::is_common_pixel_type(Rtype)) { \ + Rtype = TypeDesc::FLOAT; \ + Rtmp.copy(R, Rtype); \ + Rptr = &Rtmp; \ + } \ + if (!ImageBufAlgo::is_common_pixel_type(Atype)) { \ + Atype = TypeDesc::FLOAT; \ + Atmp.copy(A, Atype); \ + Aptr = &Atmp; \ } \ - } else { \ - /* When Rtype != Atype, handle the common pairs */ \ switch (Rtype.basetype) { \ case TypeDesc::FLOAT : \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,float,Atype,R,A,__VA_ARGS__); \ + OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,float,Atype,*Rptr,*Aptr, __VA_ARGS__); \ break; \ case TypeDesc::UINT8 : \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,uint8_t,Atype,R,A,__VA_ARGS__); \ + OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,uint8_t,Atype,*Rptr,*Aptr, __VA_ARGS__); \ break; \ case TypeDesc::HALF : \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,half,Atype,R,A,__VA_ARGS__); \ + OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,half,Atype,*Rptr,*Aptr, __VA_ARGS__); \ break; \ case TypeDesc::UINT16: \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,uint16_t,Atype,R,A,__VA_ARGS__); \ + OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,uint16_t,Atype,*Rptr,*Aptr, __VA_ARGS__); \ + break; \ + default: \ + OIIO_DASSERT(0 && "bad type"); \ break; \ - default: { \ - /* other combinations: convert to float, then copy back */ \ - ImageBuf Rtmp; \ - if ((R).initialized()) \ - Rtmp.copy (R, TypeDesc::FLOAT); \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,float,Atype,Rtmp,A,__VA_ARGS__); \ - if (ret) \ - (R).copy (Rtmp); \ - else \ - (R).errorfmt("{}", Rtmp.geterror()); \ - } \ } \ } -// Macro to call a type-specialized version func(R,A,...) for -// the most common types. It will auto-convert other cases to/from float. -// This is the case for when we don't actually write to the read-only R image. -#define OIIO_DISPATCH_COMMON_TYPES2_CONST(ret,name,func,Rtype,Atype,R,A,...) \ - switch (Rtype.basetype) { \ - case TypeDesc::FLOAT : \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,float,Atype,R,A,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT8 : \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,unsigned char,Atype,R,A,__VA_ARGS__); \ - break; \ - case TypeDesc::HALF : \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,half,Atype,R,A,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT16: \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,unsigned short,Atype,R,A,__VA_ARGS__); \ - break; \ - default: { \ - /* other types: punt and convert to float, then copy back */ \ - ImageBuf Rtmp; \ - if ((R).initialized()) \ - Rtmp.copy (R, TypeDesc::FLOAT); \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,float,Atype,Rtmp,A,__VA_ARGS__); \ - } } - - // Helper, do not call from the outside world. -#define OIIO_DISPATCH_COMMON_TYPES3_HELP2(ret,name,func,Rtype,Atype,Btype,R,A,B,...) \ +// This is the the case where we're switching based on the result. Be very +// stingy about the types directly supported here, for all others, write into +// a temp float buffer and copy back. Remember that if the result had the same +// type as both inputs, we wouldn't be here all, so this is already an +// inefficient case. +#define OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,Atype,Btype,R,A,B,...) \ switch (Rtype.basetype) { \ case TypeDesc::FLOAT : \ ret = func (R,A,B,__VA_ARGS__); break; \ @@ -504,91 +612,114 @@ inline TypeDesc type_merge (TypeDesc a, TypeDesc b, TypeDesc c) ret = func (R,A,B,__VA_ARGS__); break; \ case TypeDesc::UINT16: \ ret = func (R,A,B,__VA_ARGS__); break; \ - default: { \ - /* other types: punt and convert to float, then copy back */ \ - ImageBuf Rtmp; \ - if ((R).initialized()) \ - Rtmp.copy (R, TypeDesc::FLOAT); \ - ret = func (R,A,B,__VA_ARGS__); \ - if (ret) \ - (R).copy (Rtmp); \ - else \ - (R).errorfmt("{}", Rtmp.geterror()); \ - } \ - } - -// Helper, do not call from the outside world. -#define OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,Atype,Btype,R,A,B,...) \ - switch (Btype.basetype) { \ - case TypeDesc::FLOAT : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP2(ret,name,func,Rtype,Atype,float,R,A,B,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT8 : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP2(ret,name,func,Rtype,Atype,unsigned char,R,A,B,__VA_ARGS__); \ - break; \ - case TypeDesc::HALF : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP2(ret,name,func,Rtype,Atype,half,R,A,B,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT16 : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP2(ret,name,func,Rtype,Atype,unsigned short,R,A,B,__VA_ARGS__); \ + default: \ + OIIO_DASSERT(0 && "bad type"); \ break; \ - default: { \ - /* other types: punt and convert to float */ \ - ImageBuf Btmp; \ - Btmp.copy (B, TypeDesc::FLOAT); \ - OIIO_DISPATCH_COMMON_TYPES3_HELP2(ret,name,func,Rtype,Atype,float,R,A,Btmp,__VA_ARGS__); \ - } \ } // Macro to call a type-specialized version func(R,A,B,...) -// the most common types, and for all types when all three images have -// the same type. Remaining rare cases will auto-convert to float. -#define OIIO_DISPATCH_COMMON_TYPES3(ret,name,func,Rtype,Atype,Btype,R,A,B,...) \ - if (Rtype == Atype && Rtype == Btype) { \ - /* All data types, when Rtype == Atype */ \ +// the most common type combination. Remaining rare cases will auto-convert to +// float. Specifically: anything not {float,half,uint8,uint16} is converted +// to float; if A and B's types don't match, they are converted to float; and +// if R doesn't either match A and B or is float, then A and B are also +#define OIIO_DISPATCH_COMMON_TYPES3(ret,name,func,Rtype_,Atype_,Btype_,R,A,B,...) \ + { \ + OIIO_ASSERT((R).initialized()); \ + ret = false; \ + auto Rptr = &R; \ + auto Aptr = &A; \ + auto Bptr = &B; \ + ImageBuf Rtmp, Atmp, Btmp; \ + TypeDesc Rtype = Rtype_, Atype = Atype_, Btype = Btype_; \ + if (!ImageBufAlgo::is_common_pixel_type(Atype) || (Atype != Btype && Atype != TypeFloat)) { \ + Atype = TypeDesc::FLOAT; \ + Atmp.copy(A, Atype); \ + Aptr = &Atmp; \ + } \ + if (!ImageBufAlgo::is_common_pixel_type(Btype) || (Atype != Btype && Btype != TypeFloat)) { \ + Btype = TypeDesc::FLOAT; \ + Btmp.copy(B, Btype); \ + Bptr = &Btmp; \ + } \ + OIIO_ASSERT(Atype == Btype); \ + if (!ImageBufAlgo::is_common_pixel_type(Rtype) || (Rtype != Atype && Rtype != TypeFloat)) { \ + Rtype = TypeDesc::FLOAT; \ + Rtmp.copy(R, Rtype); \ + Rptr = &Rtmp; \ + } \ + OIIO_ASSERT(Rtype == Atype || Rtype == TypeFloat); \ switch (Atype.basetype) { \ case TypeDesc::FLOAT : \ - ret = func (R, A, B, __VA_ARGS__); break;\ - case TypeDesc::UINT8 : \ - ret = func (R, A, B, __VA_ARGS__); break; \ - case TypeDesc::UINT16: \ - ret = func (R, A, B, __VA_ARGS__); break; \ - case TypeDesc::HALF : \ - ret = func (R, A, B, __VA_ARGS__); break; \ - case TypeDesc::INT8 : \ - ret = func (R, A, B, __VA_ARGS__); break; \ - case TypeDesc::INT16 : \ - ret = func (R, A, B, __VA_ARGS__); break; \ - case TypeDesc::UINT : \ - ret = func (R, A, B, __VA_ARGS__); break; \ - case TypeDesc::INT : \ - ret = func (R, A, B, __VA_ARGS__); break; \ - case TypeDesc::DOUBLE : \ - ret = func (R, A, B, __VA_ARGS__); break; \ - default: \ - (R).errorfmt("{}: Unsupported pixel data format '{}'", name, Atype); \ - ret = false; \ - } \ - } else { \ - switch (Atype.basetype) { \ - case TypeDesc::FLOAT : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,float,Btype,R,A,B,__VA_ARGS__); \ + switch (Rtype.basetype) { \ + case TypeDesc::FLOAT : \ + ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break; \ + /*case TypeDesc::UINT8 :*/ \ + /* ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break;*/ \ + /*case TypeDesc::HALF :*/ \ + /* ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break;*/ \ + /*case TypeDesc::UINT16:*/ \ + /* ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break;*/ \ + default: \ + OIIO_ASSERT(0 && "bad type"); \ + break; \ + } \ break; \ case TypeDesc::UINT8 : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,unsigned char,Btype,R,A,B,__VA_ARGS__); \ + switch (Rtype.basetype) { \ + case TypeDesc::FLOAT : \ + ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break; \ + case TypeDesc::UINT8 : \ + ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break; \ + /*case TypeDesc::HALF :*/ \ + /* ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break;*/ \ + /*case TypeDesc::UINT16:*/ \ + /* ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break;*/ \ + default: \ + OIIO_ASSERT(0 && "bad type"); \ + break; \ + } \ break; \ case TypeDesc::HALF : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,half,Btype,R,A,B,__VA_ARGS__); \ + switch (Rtype.basetype) { \ + case TypeDesc::FLOAT : \ + ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break; \ + /*case TypeDesc::UINT8 :*/ \ + /* ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break;*/ \ + case TypeDesc::HALF : \ + ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break; \ + /*case TypeDesc::UINT16: */ \ + /* ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break;*/ \ + default: \ + OIIO_ASSERT(0 && "bad type"); \ + break; \ + } \ break; \ case TypeDesc::UINT16: \ - OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,unsigned short,Btype,R,A,B,__VA_ARGS__); \ + switch (Rtype.basetype) { \ + case TypeDesc::FLOAT : \ + ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break; \ + /*case TypeDesc::UINT8 : \ + ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break; */ \ + /*case TypeDesc::HALF : \ + ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break; */ \ + case TypeDesc::UINT16: \ + ret = func(*Rptr,*Aptr,*Bptr,__VA_ARGS__); break; \ + default: \ + OIIO_ASSERT(0 && "bad type"); \ + break; \ + } \ break; \ default: \ - /* other types: punt and convert to float */ \ - ImageBuf Atmp; \ - Atmp.copy (A, TypeDesc::FLOAT); \ - OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,float,Btype,R,Atmp,B,__VA_ARGS__); \ + OIIO_ASSERT(0 && "bad type"); \ + break; \ } \ + if (Rptr != &(R)) { \ + /* If we used Rtmp, copy pixels or errors to the real R */ \ + if (ret) \ + (R).copy(*Rptr, (R).pixeltype()); \ + else \ + (R).errorfmt("{}", Rptr->geterror()); \ + } \ } @@ -611,8 +742,8 @@ inline TypeDesc type_merge (TypeDesc a, TypeDesc b, TypeDesc c) #define IBA_FIX_PERCHAN_LEN_DEF(av,len) \ IBA_FIX_PERCHAN_LEN (av, len, 0.0f, av.size() ? av.back() : 0.0f); -// clang-format on +// clang-format on /// Simple image per-pixel unary operation: Given a source image `src`, return