cimagemagickrgbrastermagickwand

ImageMagick to write image file row by row (or band by band)


Does ImageMagick (C API MagickWand) have a functionality to generate an image file (.jpg, .tif) using RGB raster data?

If so, can it also generate an image file band by band, meaning write few rows at a time until it writes the whole image? Or one row at a time?


Solution

  • I believe you are describing image row iterators. ImageMagick provided PixelIterator methods to allow traversing of image data.

    Here's a quick example.

    #include <stdio.h>
    #include <wand/MagickWand.h>
    
    int main(int argc, const char * argv[]) {
        // Set up IM environment.
        MagickWandGenesis();
    
        // Prototype
        MagickWand * wand;
        PixelWand * bg;
        PixelIterator * iter;
        PixelWand ** row;
        MagickPixelPacket pixel;
    
        size_t
            x,
            y,
            row_width,
            width  = 200,
            height = 50;
    
        unsigned int
            seed = 0xABCD;
    
        // Allocate & initialize.
        wand = NewMagickWand();
        bg = NewPixelWand();
    
        // Create an empty image.
        PixelSetColor(bg, "WHITE");
        MagickNewImage(wand, width, height, bg);
    
        // Free color resource.
        bg = DestroyPixelWand(bg);
    
        srand(seed); // Seed random number.
    
        // Allocate & initialize pixel iterator
        iter = NewPixelIterator(wand);
    
        // Loop through all rows.
        for (y = 0; y < height; ++ y)
        {
            // Pull all pixels in a row.
            row = PixelGetNextIteratorRow(iter, &row_width);
            // Iterate over all pixels collected.
            for (x = 0; x < row_width; ++x)
            {
                // Copy pixel data to packet.
                PixelGetMagickColor(row[x], &pixel);
                // Set random colors.
                pixel.red   = rand() & QuantumRange;
                pixel.green = rand() & QuantumRange;
                pixel.blue  = rand() & QuantumRange;
                // Put data back to pixel from packet.
                PixelSetMagickColor(row[x], &pixel);
            }
            // Sync manipulated data on buffer back to image.
            PixelSyncIterator(iter);
        }
    
        /******************************
         Let's set row 16 to be all RED
         ******************************/
        PixelSetIteratorRow(iter, 15);
        row = PixelGetNextIteratorRow(iter, &row_width);
        for (x = 0; x < row_width; ++x)
        {
            PixelGetMagickColor(row[x], &pixel);
            pixel.red   = QuantumRange;
            pixel.green = 0;
            pixel.blue  = 0;
            PixelSetMagickColor(row[x], &pixel);
        }
        // Sync manipulated data on buffer back to image.
        PixelSyncIterator(iter);
    
        // Free iterator resorce.
        iter = DestroyPixelIterator(iter);
    
        MagickWriteImage(wand, "/tmp/output.png");
        // Free image data.
        wand = DestroyMagickWand(wand);
    
        MagickWandTerminus();
        return 0;
    }
    

    output.png

    Please note that the above example uses ImageMagick 6. For ImageMagick 7, please review Porting Guide.