1

我正在使用提升 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 通道,去隔行扫描。

在这里,我遇到了一些我无法解决的问题:

  • 二次抽样。

在此处输入图像描述- 这是结果。如您所见,图像与楼梯一样多,为什么?如何解决?

  • 交错。

在此处输入图像描述- 这是结果。如您所见,从图像底部到顶部是否还有一行。暂时通过导出去隔行图像来解决它,但这不是最好的方法。如何使用 gil 解决它?

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

在此处输入图像描述

结果:

在此处输入图像描述

4

1 回答 1

1

显示的转换似乎有问题。

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

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

我得到了预期的输出:

在此处输入图像描述

这就是预览缓冲区 ( buff1),就像您在平面 int32 向量中复制它一样。

另请注意

  • 返回参数是按值传递的,这意味着它实际上不会被更改read_pixel_arr&为传递引用添加)
  • 存在内存泄漏,因为buff1从未释放。下面,我用unique_ptr.

住在科利鲁

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");
}

大大简化

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

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

相反,让我们从文件信息中检测维度,并直接读入平面数组:

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类型双关语。


于 2020-11-29T21:19:19.113 回答