/*
Method: Magick::colors [ { |colorinfo| } ]
Purpose: If called with the optional block, iterates over the colors,
otherwise returns an array of Magick::Color objects
Notes: There are 3 implementations
*/
VALUE
Magick_colors(VALUE class)
{
#if defined(HAVE_GETCOLORINFOARRAY) // GraphicsMagick
ColorInfo **color_ary;
ExceptionInfo exception;
volatile VALUE ary;
int x;
GetExceptionInfo(&exception);
color_ary = GetColorInfoArray(&exception);
HANDLE_ERROR
if (rb_block_given_p())
{
x = 0;
while(color_ary[x])
{
rb_yield(Color_from_ColorInfo(color_ary[x]));
x += 1;
}
magick_free(color_ary);
return class;
}
else
{
ary = rb_ary_new();
x = 0;
while (color_ary[x])
{
rb_ary_push(ary, Color_from_ColorInfo(color_ary[x]));
x += 1;
}
magick_free(color_ary);
return ary;
}
#elif defined(HAVE_GETCOLORINFOLIST) // ImageMagick 6.0.0
const ColorInfo **color_info_list;
unsigned long number_colors, x;
volatile VALUE ary;
#if defined(HAVE_OLD_GETCOLORINFOLIST)
color_info_list = GetColorInfoList("*", &number_colors);
#else
// IM 6.1.3 added an exception parm to GetColorInfoList
ExceptionInfo exception;
GetExceptionInfo(&exception);
color_info_list = GetColorInfoList("*", &number_colors, &exception);
HANDLE_ERROR
#endif
if (rb_block_given_p())
{
for(x = 0; x < number_colors; x++)
{
rb_yield(Color_from_ColorInfo(color_info_list[x]));
}
magick_free(color_info_list);
return class;
}
else
{
ary = rb_ary_new2((long) number_colors);
for(x = 0; x < number_colors; x++)
{
rb_ary_push(ary, Color_from_ColorInfo(color_info_list[x]));
}
magick_free(color_info_list);
return ary;
}
#else // ImageMagick < 6.0.0
const ColorInfo *color_list;
ColorInfo *color;
ExceptionInfo exception;
volatile VALUE ary, el;
GetExceptionInfo(&exception);
color_list = GetColorInfo("*", &exception);
DestroyExceptionInfo(&exception);
// The order of the colors list can change in mid-iteration,
// so the only way we can guarantee a single pass thru the list
// is to copy the elements into an array without returning to
// IM. So, we always create a Ruby array and either return it
// or iterate over it.
ary = rb_ary_new();
for (color = (ColorInfo *)color_list; color; color = color->next)
{
rb_ary_push(ary, Color_from_ColorInfo(color));
}
// If block, iterate over colors
if (rb_block_given_p())
{
while ((el = rb_ary_shift(ary)) != Qnil)
{
rb_yield(el);
}
return class;
}
else
{
return ary;
}
#endif
}