Boost::GIL:读取具有 alpha 通道的 *.png 图像缺少抗锯齿功能

2024-01-28

我用的是boost 1.74。

因此,毫无例外地捕获并休息我的实际代码如下所示:

typedef std::vector<int32_t> FlatINT32TArr;

using PreviewImageT = bg::rgba8_image_t;
using PreviewViewT = bg::rgba8_view_t;
using PreviewPixelT = bg::rgba8_pixel_t;

void read_pixel_arr(FlatINT32TArr r_preview_flat_arr, const std::wstring& filepath)
{
  std::ifstream byte_stream(filepath, std::ios::binary);

  PreviewImageT image;

  bg::read_and_convert_image(
    byte_stream, image, bg::image_read_settings<bg::png_tag>());

  const int image_width = (int)image.width();
  const int image_height = (int)image.height();

  const int preview_pixel_count = image_width * image_height;

  PreviewViewT preview_view;
  PreviewPixelT* buff1 = new PreviewPixelT[preview_pixel_count];
  preview_view = bg::interleaved_view(
    image_width, image_height, buff1,
    image_width * sizeof(PreviewPixelT));

  bg::copy_and_convert_pixels(
    bg::flipped_up_down_view(const_view(image)), preview_view);

  r_preview_flat_arr = FlatINT32TArr(preview_pixel_count);
  memcpy(
    &r_preview_flat_arr[0],
    &preview_view[0],
    sizeof(PreviewPixelT) * preview_pixel_count
  );
}

它读取 * .png 图像文件并将其转换为 int32_t 数组。 (该数组随后用于生成 OpenGL 纹理)。

所以,原始图像文件是:

它是从 Adob​​e Illustrator 导出的,带有 alpha 通道,去隔行。

这里我有一些无法解决的问题:

  • 二次采样。

enter image description here - here is result. As you can see, image is so much aliased as a stairs, why? How to solve it?

  • 交错。

enter image description here - here is result. As you can see, is there one more line from image bottom on the top. Temporary it was solved by exporting deinterlaced image but it is not the best way. How can I solve it using gil?

还有一项测试: 原始的(带有 alpha 通道渐变):

Result:


似乎有什么不对劲after显示的转换。

当我将预览数据保存为 PNG 时:

bg::write_view("output.png", preview_view, bg::png_tag{});

我得到预期的输出:

这是预览缓冲区(buff1)与将其复制到平面 int32 向量中完全相同。

另请注意

  • 返回参数是按值传递的,这意味着它实际上不会被更改read_pixel_arr (added &用于通过引用传递)
  • 出现内存泄漏,因为buff1从未被释放。下面,我用一个修复了它unique_ptr.

住在科里鲁 http://coliru.stacked-crooked.com/a/50b9d1aa0ac8edd4

void read_pixel_arr(FlatINT32TArr& r_preview_flat_arr, std::string filepath) {
    std::ifstream byte_stream(filepath, std::ios::binary);

    bg::image_read_settings<bg::png_tag> settings;
    //settings._read_transparency_data = true;

    PreviewImageT image;
    bg::read_and_convert_image(byte_stream, image, settings);

    auto width   = image.width();
    auto height  = image.height();
    auto npixels = width * height;

    auto buff1 = std::make_unique<PreviewPixelT[]>(npixels);
    auto preview_view = bg::interleaved_view(
            width, height, buff1.get(),
            width * sizeof(PreviewPixelT));
    assert(buff1.get() == &preview_view[0]); // checking understanding

    bg::copy_and_convert_pixels(
            bg::flipped_up_down_view(const_view(image)), preview_view);

    r_preview_flat_arr = FlatINT32TArr(npixels);
    memcpy(r_preview_flat_arr.data(), 
           buff1.get(),
           sizeof(PreviewPixelT) * npixels);

    bg::write_view("output.png", preview_view, bg::png_tag{});
}

int main() {
    FlatINT32TArr v(1 << 20);
    read_pixel_arr(v, "sample.png");
}

大大简化

Using read_image_info您可以避免分配缓冲区 3 次并复制它多次:

  1. 对于图像缓冲区(仅用于复制和检测宽度/高度)
  2. for the buff1(最初也是泄露的)
  3. 对于平面数组(std::vector)

相反,让我们从文件信息中检测尺寸,然后读取directly进入平面数组:

auto flatvector_view(FlatINT32TArr& v, long width) {
    return bg::interleaved_view(
       width, v.size()/width,
       reinterpret_cast<PreviewPixelT*>(v.data()),
       width * sizeof(PreviewPixelT));
}

long read_pixel_arr(FlatINT32TArr& r_pixeldata, std::string filepath) {
    bg::image_read_settings<bg::png_tag> settings;
    auto info   = bg::read_image_info(filepath, settings);
    auto width  = info._info._width;
    auto height = info._info._height;
    r_pixeldata.resize(width * height);

    bg::read_and_convert_view(filepath,
        bg::flipped_up_down_view(flatvector_view(r_pixeldata, width)),
        settings);

    return width;
}

int main() {
    FlatINT32TArr v;
    auto width = read_pixel_arr(v, "sample.png");

    bg::write_view("output.png", flatvector_view(v, width), bg::png_tag{});
}

请注意,reinterpret_cast是由static_assert。它在逻辑上相当于你的memcpy类型双关语。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Boost::GIL:读取具有 alpha 通道的 *.png 图像缺少抗锯齿功能 的相关文章

随机推荐