不使用reinterpret_cast,如何将Boost::GIL bits8*转换为gray8_ptr_t?

16

我试图按照 GIL 的设计准则进行工作,我使用 bits__ 作为我的通道数据类型。我经常有外部数据需要包装成 GIL 图像视图。然而,即使对于数据指针我使用了 bits__ 类型,我仍然不得不在创建图像视图之前添加 reinterpret_cast。请看下面的代码:

int width = 3;
int height = 2;

boost::gil::bits8 data8[] = {0, 1, 100, 200, 50, 51};
boost::gil::bits8* pBits8 = data8;
boost::gil::gray8_ptr_t pGray8 = pBits8;

boost::gil::gray8_view_t v = interleaved_view(width, height, pGray8, width * sizeof(boost::gil::bits8));

在第6行出现错误,提示“error C2440: 'initializing' : cannot convert from 'boost::gil::bits8 *' to 'boost::gil::gray8_ptr_t' 1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast”。

尽可能深入源代码后,看起来这些类型确实是不相关的。bits8只是unsigned char,但是gray8_ptr_t是指向struct pixel<bits8,gray_layout_t>的指针。此结构体的唯一元素是一个bits8,因此reinterpret_cast看起来很安全,并且对我所进行的测试也可以正常工作。

然而,我经常将外部数据包装成图像视图,并且在每个地方都使用reinterpret_cast感觉有问题。是否有更安全的方法来构造用于GIL的像素指针?

当前的解决方法:

template<class Dest, class Src>
Dest gil_safe_ptr_cast(Src src)
{
    // this cast is unsafe, use reinterpret_cast 
    BOOST_STATIC_ASSERT(false);
}
template<> boost::gil::gray8_ptr_t gil_safe_ptr_cast(boost::gil::bits8* pBits8)
{
    return reinterpret_cast<boost::gil::gray8_ptr_t>(pBits8);
}
boost::gil::bits8* pBits8 = data8;
boost::gil::gray8_ptr_t pGray8 = gil_safe_ptr_cast<boost::gil::gray8_ptr_t>(pBits8); // works
boost::gil::bits16* pBits16 = NULL;
boost::gil::gray8_ptr_t pGray82 = gil_safe_ptr_cast<boost::gil::gray8_ptr_t>(pBits16); // compile error as expected

在我第一次看到这个问题的标题时,我怀疑你可能会对危险的强制类型转换有些疯狂,但现在看来你对此非常谨慎。 - Lightness Races in Orbit
1
我已经创建了一个解决方法,基本上是一系列已知对于此操作安全的转换列表。 - totowtwo
2
最好自己创建像素结构并将bits8放入其中,这样更安全。对于反向转换,只需从结构中提取bits8即可。 - Michal M
2个回答

1
template<class Dest, class Src>
Dest gil_safe_ptr_cast(Src src)
{
    // this cast is unsafe, use reinterpret_cast 
    BOOST_STATIC_ASSERT(false);
}
template<> boost::gil::gray8_ptr_t gil_safe_ptr_cast(boost::gil::bits8* pBits8)
{
    return reinterpret_cast<boost::gil::gray8_ptr_t>(pBits8);
}
boost::gil::bits8* pBits8 = data8;
boost::gil::gray8_ptr_t pGray8 = gil_safe_ptr_cast<boost::gil::gray8_ptr_t>(pBits8); // works
boost::gil::bits16* pBits16 = NULL;
boost::gil::gray8_ptr_t pGray82 = gil_safe_ptr_cast<boost::gil::gray8_ptr_t>(pBits16); // compile error as expected

1
这里使用了reinterpret_cast。之前的“不使用reinterpret_cast”呢? - Brilliand

1

要将bits8*转换为gray8_ptr_t,需要创建一个名为pixel的结构体,并将bits8传递给构造函数:

gray8_ptr_t convert_gray8_ptr_t(bits8* src) {
    return new struct pixel<bits8,gray_layout_t>(*src);
}

要进行转换,请使用结构体的转换运算符:

bits8* convert_bits8(gray8_ptr_t src) {
    bits8* result = new bits8;
    *result = (bits8) *src;
    return result;
}

当然,这两个函数都会分配内存,作为函数可能是不必要的(最好作为内联代码)。


这些不仅会分配内存,而且只会复制单个值。如果您插入此 convert_gray8_ptr_t,则从 v 访问除像素 (0,0) 以外的任何内容都可能导致访问冲突,并且至少是未初始化的值。 - totowtwo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接