c++imageopencvmagick++

How to visualize arrays data?


I have three 2-dimensional arrays with a certain size and some uint16_t values for rgb. So when these arrays are completely filled with data(i am filling them together, so it's happens at the same time) i have to visualize these arrays with PNG or JPG image format, save it and then start filling arrays again with new data. I am thinking about creating vector of structures with 3 fields for each color, mb with this data structure it will be easier to deal with this task. Can somebody tell me, please, what the best way to do this?

Thank you in advance.


Solution

  • If your using Magick++, I believe you want to use Magick::Image.read method. Specifically the function signature ...

    Magick++/Image.h

    // Read single image frame from an array of raw pixels, with
    // specified storage type (ConstituteImage), e.g.
    // image.read( 640, 480, "RGB", 0, pixels );
    void read(const size_t width_,const size_t height_,const std::string &map_,
              const StorageType type_,const void *pixels_);
    

    This will allow you to arbitrary read raster-data from a memory address; provided that you define the size (width & height), channel mappings, and storage size.

    I have three 2-dimensional arrays with a certain size and some uint16_t values for rgb.

    I would recommend "importing" each array into a single temporary image, and composite-copy each color channel into a final image.

    Without seeing your code, I would guess you have something like this defined...

    // Example 4x4 image broken into three 2d arrays.
    uint16_t
        red[4][4]   = {
            {0xFFFF,0xFFFF,0xFFFF,0xFFFF},
            {0x9999,0x9999,0x9999,0x9999},
            {0x6666,0x6666,0x6666,0x6666},
            {0x0000,0x0000,0x0000,0x0000}
        },
        green[4][4] = {
            {0xFFFF,0x9999,0x6666,0x0000},
            {0xFFFF,0x9999,0x6666,0x0000},
            {0xFFFF,0x9999,0x6666,0x0000},
            {0xFFFF,0x9999,0x6666,0x0000}
        },
        blue[4][4]  = {
            {0x0000,0x0000,0x0000,0x0000},
            {0x6666,0x6666,0x6666,0x6666},
            {0x9999,0x9999,0x9999,0x9999},
            {0xFFFF,0xFFFF,0xFFFF,0xFFFF}
        };
    

    So the process would be:

    1. Create blank canvas for the finial image.
    2. Load each 2d array into a temporary raster.
    3. Composite-Copy the temporary raster to the final image.
    4. Repeat as needed.

    For example..

    // Create blank canvas.
    Magick::Image ctx;
    ctx.size(Magick::Geometry(4, 4));
    
    {// Build & copy RED channel.
        Magick::Image redImage;
        redImage.read(4, 4, "R", Magick::ShortPixel, red);
        ctx.composite(redImage, 0, 0, Magick::CopyRedCompositeOp);
    }
    {// Build & copy GREEN channel.
        Magick::Image greenImage;
        greenImage.read(4, 4, "G", Magick::ShortPixel, green);
        ctx.composite(greenImage, 0, 0, Magick::CopyGreenCompositeOp);
    
    }
    {// Build & copy Blue channel
        Magick::Image blueImage;
        blueImage.read(4, 4, "B", Magick::ShortPixel, blue);
        ctx.composite(blueImage, 0, 0, Magick::CopyBlueCompositeOp);
    }
    
    ctx.sample(Magick::Geometry(200, 200)); // Enlarge so we can see the results.
    ctx.write("output.png");
    

    output.png

    Of course you could probably eliminate this entirely be allocating a 1d array, build the "RGB" raster, and call Magick::Image.read once.

    size_t
     x,
     y,
     i,
     width = 4,
     height = 4;
    uint16_t raster[width * height * 3];
    for(y = 0, i = 0; y < height; ++y) {
        for(x = 0; x < width; ++x) {
            raster[ i++ ] = red[y][x];
            raster[ i++ ] = green[y][x];
            raster[ i++ ] = blue[y][x];
        }
    }
    Magick::Image ctx(4, 4, "RGB", Magick::ShortPixel, raster);
    

    YMMV