Search code examples
c++imagematrixintel-ipp

ipp - Converting float matrix to rgb


I have the following code written to have IPP resize my matrix:

#include "ipp_mx.h"
#include "ipp.h"

#include "stdafx.h"
#define IPPCALL(name) name

int main()
{
    IppiSize srcSize = { 3,3 };
    float srcImage[9] =
    { 20, 40, 30,
      35, 55, 70,
      100, 30, 20 };
    float* src = new float[srcSize.width*srcSize.height];
    for (int i = 0; i < srcSize.width*srcSize.height; i++) {
        src[i] = srcImage[i];
    }
    double xFactor = 10; double yFactor = 10;

    int numChannels = 1;
    int bytesPerPixel = 4;
    int srcStep = srcSize.width*bytesPerPixel*numChannels;
    IppiRect srcRoi = { 0, 0, srcSize.width, srcSize.width };

    float* dest = new float[srcSize.width*srcSize.height*xFactor*yFactor];
    IppiSize destSize = { srcSize.width*xFactor, srcSize.height*yFactor };
    int destStep = destSize.width*bytesPerPixel*numChannels;
    IppiRect destRoi = { 0, 0, destSize.width, destSize.width };

    double xShift = 0; double yShift = 0;

    int interpolation = 1; //nearest neighbour

    int bufSize;
    IPPCALL(ippiResizeGetBufSize)(srcRoi, destRoi, 1, interpolation, &bufSize);
    unsigned char* buffer = new unsigned char[bufSize];

    IPPCALL(ippiResizeSqrPixel_32f_C1R)(src, srcSize, srcStep, srcRoi, dest, destStep, destRoi, xFactor, yFactor, xShift, yShift, interpolation, buffer);
    return 0;
}

Is there an IPP function I can use that now converts this float matrix dest to an RGB24 format, given a colour map?

I know I can do it by hand in a for loop, but the raw matrices I want to work with are much larger and for loops may not cut it.


Solution

  • The technique I found to work consists of 3 steps:

    1. Convert/truncate the float value to unsigned char - in my case the input values are within the 8 bit range and I don't care about the decimal numbers.
    2. Convert the unsigned char value to 3 channel RGB gray which essentially assigns the same input values to all 3 channels.
    3. Construct a palette to map 3 channel values to another 3 channel values.
    4. Pass the palette and the input value to a lookup table function.

    This is demonstrated on the code below. Note that my palette was setup to assign green for values under 30 and blue for values greater or equals than 30.

    unsigned char** GeneratePalette()
    {
        unsigned char red[256];
        unsigned char green[256];
        unsigned char blue[256];
    
        for(int value = 0; value < 256; value++)
        {
            if(value < 30)
            {
                red[value] = 0;
                green[value] = 255;
                blue[value] = 0;
            }
            else
            {
                red[value] = 0;
                green[value] = 0;
                blue[value] = 255;
            }
        }
    
        unsigned char* table[3] = { red, green, blue };
        return table;
    }
    
    void Test()
    {
        unsigned char** palette = GeneratePalette();
        IppiSize srcSize = { 2,1 };
        float src[2] = { 54, 19 };
        unsigned char truncated[2];
    
        IPPCALL(ippiConvert_32f8u_C1R)(src, srcSize.width * sizeof(float), truncated, srcSize.width * sizeof(unsigned char), srcSize, ippRndZero);
        unsigned char copied[6] = {0};
        IPPCALL(ippiGrayToRGB_8u_C1C3R)(truncated, srcSize.width * sizeof(unsigned char), copied, srcSize.width * sizeof(unsigned char) * 3, srcSize);
        unsigned char dest[6];
    
        IPPCALL(ippiLUTPalette_8u_C3R)(copied, 6, dest, 6, srcSize, palette, 8);
    }
    
    int main()
    {
        Test();
        return 0;
    }
    

    In the end, this was not very efficient and working on a single for loop was faster.