Search code examples
c++imagemagickmagick++graphical-programming

How to convert the imagemagick sparse-color Barycentric command line to magick++ code?


I am trying to convert a simple ImageMagick command line to Magick++/c++ code. However it didn't work as expected. The offical website lack of API example. I can not figure out the problem even I dive into the related implement code. And Google doesn't give any hint.

ImageMagick command:

convert -size 543x114 xc: -sparse-color Barycentric '0,0 red 0,%h blue' gradient.png

I want to copy its effect by following code, but the output is inconsistent.

Magick++ code:

#include <Magick++.h>

int main()
{
    int width = 543;
    int height = 114;
    Magick::Image gradImage(Magick::Geometry(width, height), Magick::Color("white"));
    // installed magick++ is built --with-quantum-depth=8
    double maxRGB = 255;

    double args[] = {
        0, 0,
        maxRGB, 0, 0,
        0, height,
        0, 0, maxRGB
    };

    gradImage.sparseColor(
        (Magick::ChannelType)((Magick::DefaultChannels & ~Magick::OpacityChannel) & ~Magick::IndexChannel),
        Magick::BarycentricColorInterpolate,
        sizeof(args) / sizeof(double),
        args
    );

    gradImage.write("gradient.png");
}

CMakelist.txt:

cmake_minimum_required(VERSION 3.16)

project(demo)
find_package(ImageMagick COMPONENTS Magick++)
include_directories(
    ${ImageMagick_INCLUDE_DIRS}
)

add_executable(
    demo
    main.cpp
)

target_link_libraries(
    demo
    ${ImageMagick_Magick++_LIBRARY}
)

generated by command: imagemagick

generated by magick++:magick++

Other Info:

  • OS: Ubuntu 20.04
  • ImageMagick: 7.1.1 (built from source: ./configure --with-quantum-depth=8 && make)

Any help is appreciated!

I want the magick++ code have same effect with the command line


Solution

  • You've almost got it! It might be worth peaking at the source code for GenerateCoefficients to read the expected arguments, and SparseColorOption to see how the CLI options get parsed.

    • The R, G, B values should be in a range between 0.0 & 1.0.
    • You'll need at least 3 points, as the coefficients for Barycentric are the same as Affine.
    • If you're not targeting color traits / masks, just use DefaultChannels.

    Try the following...

    #include <Magick++.h>
    
    int main(int argc, char **argv)
    {
      double
        width = 543.0,
        height = 114.0;
      Magick::InitializeMagick(*argv);
      Magick::Geometry rect((int)width, (int)height);
      Magick::Image gradImage(rect, Magick::Color("white"));
      Magick::ColorRGB color1("red");
      Magick::ColorRGB color2("blue");
      double args[15] = {
            0,      0, color1.red(), color1.green(), color1.blue(),
        width,      0, color1.red(), color1.green(), color1.blue(),
            0, height, color2.red(), color2.green(), color2.blue()
      };
      gradImage.sparseColor(
        Magick::DefaultChannels,
        Magick::BarycentricColorInterpolate,
        15,
        args
      );
      gradImage.write("gradient.png");
    }
    

    Sparse-Color Barycentric

    Don't forget to call Magick::InitializeMagick() first thing!