Загрузка изображений из памяти (libharu) из изображений Magick++

Я работаю над некоторым программным обеспечением для генерации PDF на C++, основанном на libharu, и я хотел бы иметь возможность сначала манипулировать изображениями с помощью Magick ++, а затем загружать их из памяти с помощью функции libharu:

HPDF_LoadRawImageFromMem()

Который согласно документации по сути загружает изображения с некоторых void * буфер.

Моя цель - получить это void* данные из Magick::Image экземпляр и загрузить это изображение в мой хару PDF на основе этих данных.

Я пытался написать void* или к Magick::Blob но единственным достижением, которое у меня было до сих пор, был какой-то черный прямоугольник вместо изображения, которое я ожидаю.

У кого-нибудь есть опыт преобразования необработанных данных изображений из одной библиотеки в другую?

Причина, по которой я пытаюсь сделать это из памяти, заключается в том, что до сих пор я записываю экземпляры Magick::Image в файл, а затем читаю из этого файла для загрузки, затем в хару, что является огромным ударом по производительности в контексте моего приложения.

3 ответа

Решение

Я немного запоздал, чтобы ответить, я думаю, но вот реальный ответ.

Я успешно добавил itk::Image в мой pdf с помощью LibHaru, поэтому он должен работать примерно так же для вас. Во-первых, вам нужно знать, является ли используемая вами библиотека мажорной строкой или мажорной колонкой. LibHaru (и все библиотеки, которые я знаю) работает в мажорной строке, так что ваша библиотека тоже должна, или вам нужно будет "транспонировать" ваши данные.

// Black and white image (8 bits per pixel)
itk::Image<unsigned char, 2>::Pointer image = ...;
const unsigned char *imageData = image->GetBufferPointer();
const HPDF_Image image = HPDF_LoadRawImageFromMem(m_Document,
    imageData, width, height, HPDF_CS_DEVICE_GRAY, 8);

// Or color image (24 bits per pixel, 8 bits per color component)
itk::Image<RGBPixel, 2>::Pointer image = ...;
const RGBPixel *imageData = image->GetBufferPointer();
const HPDF_Image image = HPDF_LoadRawImageFromMem(m_Document,
    reinterpret_cast<const unsigned char *>(imageData),
    width, height, HPDF_CS_DEVICE_RGB, 8);

// Usual LibHaru code. EndText, Position, Draw, StartText, etc.
// This code should not be dependant on the type
InsertImage(image);

Я думаю, что единственная сложная часть - reinterpret_cast. Черно-белое изображение не нужно, потому что оно уже определено как байт. Например, если у вас есть это изображение

102 255 255
 99 200   0
255   0 100
imageData == {102, 255, 255, 99, 200, 0, 255, 0, 100};

Однако, если у вас есть это цветное изображение

(  0,   0, 255) (0, 255, 255) ( 42, 255, 242)
(200, 200, 255) (0, 199, 199) (190, 190, 190)
imageData == {0, 0, 255, 0, 255, 255, 42, 255, 242, 200, 200, 255, ... }

который LibHaru поймет, потому что вы говорите ему использовать HPDF_CS_DEVICE_RGB, что означает, что он будет группировать данные в (R, G, B).

Конечно, используя ImageMagick, вам нужно найти способ доступа к первому пикселю. Вероятно, это такой метод, как data(), begin(), pointer() и т. Д.

К сожалению, я не работал ни с ImageMagic, ни с libharu, однако у меня есть некоторый опыт работы с изображениями, и, поскольку никто еще не ответил, может быть, я могу помочь. Проблема, вероятно, заключается в том, что существует множество необработанных форматов изображений, и я совершенно уверен, что обе библиотеки не понимают их одинаково. Что еще хуже, так это то, что интерпретация libharu в виде исходного изображения практически не документирована. Однако выводы о том, что libharu обрабатывает необработанные данные достаточно просто, можно сделать из параметров: "HPDF_LoadRawImageFromMem". Ширина и высота в значительной степени говорят сами за себя, с единственным вопросом об использовании (вероятно, пикселей). Более интересным является: "bits_per_component". Этот параметр, вероятно, описывает, сколько битов используется для определения одного пикселя (общие значения: 8: индексируются из палитры из 256 значений, 16: индексируются из палитры из 65535 значений, 24: один байт для красного, зеленого и синего соответственно [RGB], 32: как 24, но с альфа-каналом или 8 битами для голубого, пурпурного, желтого и черного [CMYK], 36: как 32, но с 9 битами на значение для упрощения транспонирования...). Проблема в паршивой документации типа: HPDF_ColorSpace, так как она, вероятно, описывает, как следует интерпретировать значения цвета с помощью: "bits_per_component". Похоже, что ImageMagic реализовал совершенно другой подход. Кажется, что объект изображения всегда имеет формат изображения (JPEG, PNG, GIF), поэтому объект изображения, вероятно, никогда не имеет "простого" представления памяти, но кодируется. Я бы порекомендовал переключить изображение ImagaMagic на формат TIFF, так как оно оправдывает сжатие и, следовательно, имеет сходный подход с предполагаемой необработанной интерпретацией libharu. Надеюсь, это помогло хоть немного... Ура Марк.

Никогда не поздно ответить.

Я использовал PNG BLOB в качестве промежуточного шага:

Image image;
image.read("file.jpg");

Blob blob;
image.write(blob, "PNG");

HPDF_Image pdfImg = HPDF_LoadPngImageFromMem(doc, (const HPDF_BYTE*)blob.data(), blob.length());
HPDF_Page_DrawImage(doc, pdfImg, 0, 0, image.columns(), image.rows());

PDF документ и создание страницы опущены для краткости.

Другие вопросы по тегам