1

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?

Megool
  • 963
  • 2
  • 8
  • 29
  • You do not write "one row at a time" to a .jpg file. I suggest you explore the documentation for ImageMagick. – Weather Vane Mar 24 '17 at 20:32
  • 1
    BTW the `imagemagick` tag says it *"is an open source software suite for displaying, converting and editing raster image files."* – Weather Vane Mar 24 '17 at 20:45
  • 1
    Yes, you need `MagickWandGenesis()`, `NewMagickWand()`,`MagickNewImage()`, then `MagickImportImagePixels()` to read your arbitrary RGB pixels. – Mark Setchell Mar 25 '17 at 16:26

1 Answers1

2

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.

emcconville
  • 23,800
  • 4
  • 50
  • 66
  • for ImageMagick 7. use PixelInfo pixel instead of MagickPixelPacket pixel, and PixelSetPixelColor instead of PixelSetMagickColor. Refer [this](http://www.imagemagick.org/api/MagickCore/pixel_8h_source.html) – Rahul May 18 '17 at 10:11