Как прочитать информацию об изображении из строки байтов python с помощью Boost:: GIL?

Я пишу функцию для чтения ширины и высоты изображения из заголовка файла.

int read_image_dimensions() {
    namespace bg = boost::gil;

    std::string filepath = "image.png";
    std::ifstream byte_stream(filepath, std::ios::binary);

    int width = 0, height = 0;
    bg::image_read_info<bg::png_tag> png_tag_info;

    png_tag_info = bg::read_image_info(byte_stream, bg::image_read_settings<bg::png_tag>())._info;
    width = png_tag_info._width; height = png_tag_info._height;

    std::cout << width << "x" << height << std::endl;
    return 0;
}

И я понятия не имею, как читать информацию об изображении из байтов python Данные изображения взяты из Blender API, они были такими же, как записано в файле изображения.

using namespace boost::python;

int read_image_dimensions(object &image) {
    object image_packed_file = extract<object>(image.attr("packed_file"));
    object packed_data = extract<object>(image_packed_file.attr("data"));
    size_t packed_size = extract<size_t>(image_packed_file.attr("size"));

    // ... 
}

person vanyOk    schedule 07.05.2020    source источник
comment
В настоящее время я не могу настроить рабочий venv с помощью bpy, но я думаю, вы, вероятно, сможете отработать второй пример, который я привел здесь: stackoverflow. com/a/61450277/85371   -  person sehe    schedule 08.05.2020
comment
К сожалению, основная задача — использовать байты python в виде файла (байтовые данные там точно такие же, как и в образе на диске, там известный размер файла).   -  person vanyOk    schedule 08.05.2020
comment
Но это легкая часть. Если вы не возражаете, что я игнорирую все, что связано с питоном, я отвечу именно так.   -  person sehe    schedule 08.05.2020


Ответы (1)


Итак, игнорируя материал python, давайте просто предположим, что вы каким-то образом завладели байтами:

std::vector<char> pydata;

Затем вы можете просто создать поток этого. Есть несколько способов добиться этого, но позвольте мне использовать Boost Iostreams, чтобы сделать это более эффективно:

io::stream<io::array_source> byte_stream(pydata.data(), pydata.size());

Это все. Остальное то, что у вас было.

Живая демонстрация

Это демонстрирует, что моя фотография профиля имеет размер 200x200 пикселей:

#include <boost/gil/extension/io/png.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <iostream>

namespace bg = boost::gil;
namespace io = boost::iostreams;

extern std::vector<char> pydata;

int main() {
    io::stream<io::array_source> byte_stream(pydata.data(), pydata.size());

    auto info = bg::read_image_info(
            byte_stream,
            bg::image_read_settings<bg::png_tag>())
        ._info;

    std::cout << "Dimensions: " << info._width << "x" << info._height << "\n";
}

static char const polar_bear[] {
  "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d"
  "\x49\x48\x44\x52\x00\x00\x00\xc8\x00\x00\x00\xc8"
  "\x08\x06\x00\x00\x00\xad\x58\xae\x9e\x00\x00\x20"
  "\x00\x49\x44\x41\x54\x78\x9c\x94\xbd\x59\xb3\x2d"
  "\xcb\x71\x1e\xf6\x65\x56\x75\xf7\x5a\x7b\xef\x73"
  "\xee\x39\x77\xc0\x9d\x31\x03\xc4\x44\xc0\x00\x88"
  // 5623 lines snipped...
  "\x45\x4e\x44\xae\x42\x60\x82"
};

std::vector<char> pydata { std::begin(polar_bear), std::end(polar_bear) };

Отпечатки

Dimensions: 200x200
person sehe    schedule 08.05.2020
comment
Большое спасибо, это работает! Я просто не уверен, правильно ли я поступил: string pf_data = extract<string>(image_packed_file.attr("data")); Во всяком случае, он прочитал размер 50 изображений *.jpg за 0,075017 с. - person vanyOk; 08.05.2020
comment
Я думаю, что Boost Python должен быть относительно безопасным в том смысле, что если extract<std::string> работает, то это правильно :) И эта скорость кажется впечатляющей. Хороший. Обратите внимание, что на самом деле он не читается за пределами заголовка PNG - как вы можете видеть из моего фрагмента, который работает только с ~ 72 байтами данных. - person sehe; 08.05.2020