[MagickCore] Reading an image from memory

Questions and postings pertaining to the development of ImageMagick, feature enhancements, and ImageMagick internals. ImageMagick source code and algorithms are discussed here. Usage questions which are too arcane for the normal user list should also be posted here.
Post Reply
atomic
Posts: 2
Joined: 2018-08-17T09:18:59-07:00
Authentication code: 1152

[MagickCore] Reading an image from memory

Post by atomic »

I'm using the MagickCore API to load images in a game engine. I have an in-memory file buffer that I'm loading an image (such as a .png) out of. I'm then sticking the decoded data into another in-memory buffer. My current idea requires an extra copy that I'd like to get rid of:

Code: Select all

std::vector<uint8> inputData;
std::vector<uint32> outputData;
int desiredChannelCount;

ImageInfo* imInfo = AcquireImageInfo();
SetImageInfoBlob(imInfo, inputData.data(), inputData.size());
Image* imImage = ReadImage(imInfo, exInfo);
Quantum* pixels = GetAuthenticPixels(imImage, 0, 0, imImage->columns, imImage->rows, exInfo);
size_t pixelsSize = imImage->columns * imImage->rows * desiredChannelCount * sizeof(Quantum);
memcpy(image.data.data(), pixels, pixelsSize);
What's the proper way to do a fully in-memory decode without an extra copy?

For additional context, I'm trying to decode a .bmp that has 3 8-bit channels into raw pixel data that has 4 32-bit channels and I want to do it efficiently.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: [MagickCore] Reading an image from memory

Post by magick »

Have you carefully read https://www.imagemagick.org/script/arch ... .php#cache? Direct copy from ImageMagick's pixel staging buffer typically won't work unless, in your case, desiredChannelCount is GetPixelChannels(image) and you are prepared to utilize the pixels of type Quantum. Recall, Quantum might be char, unsigned short, unsigned int, or floats depending on the ImageMagick Quantum depth (8, 16, 32, HDRI) and the number of channels might be typically 1 through 5 channels. Copying the entire image is generally discouraged and instead we recommend processing one row of the image at a time. However, requesting the entire image as you have done is OK-- if you understand the memory / performance tradeoffs.
atomic
Posts: 2
Joined: 2018-08-17T09:18:59-07:00
Authentication code: 1152

Re: [MagickCore] Reading an image from memory

Post by atomic »

I'm now using StreamImage instead. Is this the correct way to decode an image into memory that I control? I can stream from a blob to a file easily enough (error handling and resource cleanup omitted):

Code: Select all

    std::vector<uint8> inputData;
    char* outputFile = "C:\\Users\\atomic\\Desktop\\img_test.raw";

    ImageInfo* imReadInfo = AcquireImageInfo();
    SetImageInfoBlob(imReadInfo, inputData.data(), inputData.size());

    ImageInfo* imWriteInfo = AcquireImageInfo();

    StreamInfo* strInfo = AcquireStreamInfo(imWriteInfo, exInfo);
    SetStreamInfoMap(strInfo, "RGBA");
    SetStreamInfoStorageType(strInfo, FloatPixel);

    OpenStream(imWriteInfo, strInfo, outputFile, exInfo);
    Image* imImage = StreamImage(imReadInfo, strInfo, exInfo);
but the moment I switch the output file to a blob it explodes

Code: Select all

    std::vector<uint8> inputData;
    std::vector<uint32> outputData;

    ImageInfo* imReadInfo = AcquireImageInfo();
    SetImageInfoBlob(imReadInfo, inputData.data(), inputData.size());

    ImageInfo* imWriteInfo = AcquireImageInfo();
    outputData.reserve(256 * 256 * 4 * 4);
    SetImageInfoBlob(imWriteInfo, outputData.data(), outputData.size());

    StreamInfo* strInfo = AcquireStreamInfo(imWriteInfo, exInfo);
    SetStreamInfoMap(strInfo, "RGBA");
    SetStreamInfoStorageType(strInfo, FloatPixel);

    OpenStream(imWriteInfo, strInfo, "", exInfo);
    Image* imImage = StreamImage(imReadInfo, strInfo, exInfo);
How do I tell StreamImage to write to my memory buffer? Currently, I think it's assuming the blob is Magick owned memory and tries to realloc, causing the crash.
Post Reply