Search code examples
cluaimagemagickffiluajit

How to use MagickGetImageHistogram of ImageMagick C API


I have been using ImageMagick's C API using LuaJIT and FFI library and magick lua module for this. Now I want to use MagickGetImageHistogram method. So when it comes to pass an argument check my below code.

***image.lua***

local len = ffi.new("size_t[?]", 5)
local t = handle_result(self, lib.MagickGetImageHistogram(self.wand, len))

***lib.lua***

local ffi = require("ffi")
local lib
ffi.cdef([[  typedef void MagickWand;
typedef void PixelWand;

typedef int MagickBooleanType;
typedef int ExceptionType;
typedef int ssize_t;
typedef int CompositeOperator;
typedef int GravityType;
typedef int OrientationType;
typedef int InterlaceType;
typedef char DistortMethod[];

void MagickWandGenesis();
MagickWand* NewMagickWand();

PixelWand **MagickGetImageHistogram(MagickWand *wand, size_t *number_colors);

So I'm sure that my first argument is correct but not sure about second one. And it returns the image histogram as an array of PixelWand wands. So how do I convert it to LuaJIT structure?


Solution

  • I'm not sure about the parts of the question, but the expected behavior MagickGetImageHistogram is as follows.

    1. Method will return an array of pixel pointers.
    2. Argument size_t *number_colors will be updated with the count of pixels in array.
    3. Each pixel in array will need to invoke method PixelGetColorCount to retrieve the sum of pixels used by image.

    Here's a quick example in C.

    #include <stdio.h>
    #include <wand/MagickWand.h>
    
    int main(int argc, const char * argv[]) {
        // Prototype vars
        MagickWand * wand;
        PixelWand ** histogram;
        size_t histogram_count = 0;
        // Boot environment.
        MagickWandGenesis();
        // Allocate & read image
        wand = NewMagickWand();
        MagickReadImage(wand, "rose:");
        // Get Histogram as array of pixels
        histogram = MagickGetImageHistogram(wand, &histogram_count);
        // Iterate over each pixel & dump info.
        for (int i = 0; i < histogram_count; ++i)
        {
            printf("%s => %zu\n",
                   PixelGetColorAsString(histogram[i]),
                   PixelGetColorCount(histogram[i]));
        }
        // Clean-up
        histogram = DestroyPixelWands(histogram, histogram_count);
        wand = DestroyMagickWand(wand);
        MagickWandTerminus();
        return 0;
    }
    

    This example will output the expected text...

    // ...
    srgb(48,45,43) => 1
    srgb(50,45,42) => 2
    srgb(50,44,43) => 5
    srgb(51,45,43) => 1
    // ...
    

    So I would guess your lua script would look something like..

    ***image.lua***
    
    local tlen = ffi.new("size_t[1]")
    local t = lib.MagickGetImageHistogram(self.wand, tlen)
    for i=0,tlen[0] do
        handle_new_pixel(self, t[i], lib.PixelGetColorCount(t[i]))
    end