Question

I am working on some pdf generation software in c++ based on libharu and I would like to be able to first manipulate images using Magick++ and then load them from memory using libharu function:

HPDF_LoadRawImageFromMem()

Which according to the documentation essentially load images from some void *buffer.

My goal is to be able to get this void* data out of a Magick::Image instance and load this image into my haru pdf based on this data.

I have tried writing to a void*or to a Magick::Blob but the only achievement I have had so far was some black rectangle instead of the image I am expecting.

Does anyone have any experience in converting Raw image data from one library into another one ?

The reason I am trying to do this from memory is because so far I am writing Magick::Image instances into a file and then reading from this file to load then in haru, which is a huge performance hit in the context of my Application.

Was it helpful?

Solution

I'm a little late to answer I guess, but here's a real-life answer.

I successfully added an itk::Image to my pdf using LibHaru so it should work about the same for you. First, you need to know if the library you use is row major or column major. LibHaru (and all the libraries I know) works in row major, so your library should too, or you will need to "transpose" your data.

// 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);

I think the only complicated part is the reinterpret_cast. The black and white image don't need one because it's already defined as byte. For example, if you have this image

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

However, if you have this color image

(  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, ... }

which LibHaru will inderstand because you tell him to use HPDF_CS_DEVICE_RGB, which means that it will group the data in (R, G, B).

Of course, using ImageMagick, you need to find how to access the first pixel. It's probably a method like data(), begin(), pointer(), etc.

OTHER TIPS

Unfortunately I neither worked with ImageMagic nor libharu, however I have some experience with image processing and since nobody answered yet, maybe I can be of some help. The problem is probably that there is a plethora of raw image formats and I'm quite sure that both libraries do not have the same understanding of these. What makes things worse is that the raw image interpretation of libharu is virtually not documented. However the conclusions that libharu handles raw data quite straightforward can be drawn from the parameters of: "HPDF_LoadRawImageFromMem". Width and Height are pretty much self-explanatory, with the only question of the used (probably pixels). More interesting is: "bits_per_component". This parameter probably describes how many bits are used to define one pixel (common values are 8: indexed from a palette of 256 values, 16: indexed from a palette of 65535 values, 24: one byte for red, green, and blue respectivly [RGB], 32: as 24 but with alpha channel or 8 bits for cyan, magenta, yellow, and black [CMYK], 36: as 32 but with 9 bit per value for easier transpostion...). A problem is the lousy documentation of the type: HPDF_ColorSpace, since it probably describes how color values of with: "bits_per_component" are to be interpreted. A totally different approach seems to be implemented by ImageMagic. An image object seems to have always an image format (JPEG, PNG, GIF), therefore an image object probably never has a "straightforward" memory representation but is encoded. My recommendation would be to switch the ImagaMagic image to the TIFF format, since it condones compression and therefore has a similar approach to the assumed raw interpretation by libharu. Hope this helped at least a bit... Cheers Mark.

It is never late to answer.

I have used a PNG blob as intermediate step:

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 document and page creation omitted for brevity.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top