Page 1 of 1

[MagickCore] Reading an image from memory

Posted: 2018-08-17T10:14:13-07:00
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.

Re: [MagickCore] Reading an image from memory

Posted: 2018-08-18T05:22:53-07:00
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.

Re: [MagickCore] Reading an image from memory

Posted: 2018-08-20T09:56:36-07:00
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.