Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image#morphology and Image#morphology_channel #40

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions ext/RMagick/rmagick.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ typedef enum _QuantumExpressionOperator
EXTERN VALUE Module_Magick;
EXTERN VALUE Class_ImageList;
EXTERN VALUE Class_Info;
EXTERN VALUE Class_KernelInfo;
EXTERN VALUE Class_Draw;
EXTERN VALUE Class_DrawOptions;
EXTERN VALUE Class_Image;
Expand Down Expand Up @@ -417,6 +418,9 @@ EXTERN VALUE Class_StretchType;
EXTERN VALUE Class_StyleType;
EXTERN VALUE Class_WeightType;
EXTERN VALUE Class_VirtualPixelMethod;
EXTERN VALUE Class_GeometryFlags;
EXTERN VALUE Class_MorphologyMethod;
EXTERN VALUE Class_KernelInfoType;

/**
* Commonly-used IDs
Expand Down Expand Up @@ -839,6 +843,21 @@ extern VALUE rm_info_new(void);
extern DisposeType rm_dispose_to_enum(const char *);
extern GravityType rm_gravity_to_enum(const char *);

// rmkinfo.c

extern VALUE KernelInfo_alloc(VALUE);

extern VALUE KernelInfo_initialize(VALUE, VALUE);
extern VALUE KernelInfo_zero_nans(VALUE);
extern VALUE KernelInfo_unity_add(VALUE, VALUE);
extern VALUE KernelInfo_show(VALUE);
extern VALUE KernelInfo_scale(VALUE, VALUE, VALUE);
extern VALUE KernelInfo_scale_geometry(VALUE, VALUE);
extern VALUE KernelInfo_clone(VALUE);

extern VALUE KernelInfo_builtin(VALUE, VALUE, VALUE);


// rmimage.c
ATTR_WRITER(Image, alpha)
ATTR_ACCESSOR(Image, background_color)
Expand Down Expand Up @@ -973,6 +992,8 @@ extern VALUE Image_contrast(int, VALUE *, VALUE);
extern VALUE Image_contrast_stretch_channel(int, VALUE *, VALUE);
extern VALUE Image_convolve(VALUE, VALUE, VALUE);
extern VALUE Image_convolve_channel(int, VALUE *, VALUE);
extern VALUE Image_morphology(VALUE, VALUE, VALUE, VALUE);
extern VALUE Image_morphology_channel(VALUE, VALUE, VALUE, VALUE, VALUE);
extern VALUE Image_copy(VALUE);
extern VALUE Image_crop(int, VALUE *, VALUE);
extern VALUE Image_crop_bang(int, VALUE *, VALUE);
Expand Down Expand Up @@ -1191,6 +1212,7 @@ extern VALUE Enum_initialize(VALUE, VALUE, VALUE);
extern VALUE Enum_to_s(VALUE);
extern VALUE Enum_to_i(VALUE);
extern VALUE Enum_spaceship(VALUE, VALUE);
extern VALUE Enum_bitwise_or(VALUE, VALUE);
extern VALUE Enum_case_eq(VALUE, VALUE);
extern VALUE Enum_type_initialize(VALUE, VALUE, VALUE);
extern VALUE Enum_type_each(VALUE);
Expand Down
36 changes: 36 additions & 0 deletions ext/RMagick/rmenum.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,42 @@ Enum_spaceship(VALUE self, VALUE other)
return rb_funcall(CLASS_OF(self), rm_ID_spaceship, 1, CLASS_OF(other));
}

/**
* Bitwise OR for enums
*
* Ruby usage:
* - @verbatim Enum1 | Enum2 @endverbatim
*
* Notes:
* - Enums must be instances of the same class.
*
* @param Enum1 this object
* @param Enum2 another enum
* @return new Enum instance
*/
VALUE
Enum_bitwise_or(VALUE self, VALUE another)
{
VALUE new_enum, cls;
MagickEnum *this, *that, *new_enum_data;

cls = CLASS_OF(self);
if (CLASS_OF(another) != cls)
{
rb_raise(rb_eArgError, "Expected class %s but got %s", rb_class2name(cls), rb_class2name(CLASS_OF(another)));
}

new_enum = Enum_alloc(cls);

Data_Get_Struct(self, MagickEnum, this);
Data_Get_Struct(another, MagickEnum, that);
Data_Get_Struct(new_enum, MagickEnum, new_enum_data);

new_enum_data->id = rb_to_id(rb_sprintf("%s|%s", rb_id2name(this->id), rb_id2name(that->id)));
new_enum_data->val = this->val | that->val;

return new_enum;
}

/**
* Return the name of an enum.
Expand Down
72 changes: 72 additions & 0 deletions ext/RMagick/rmimage.c
Original file line number Diff line number Diff line change
Expand Up @@ -4088,6 +4088,78 @@ Image_contrast_stretch_channel(int argc, VALUE *argv, VALUE self)
return rm_image_new(new_image);
}

/** Apply a user supplied kernel to the image according to the given mophology method.
*
* Ruby Usage:
* - @verbatim Image#morphology(method, iterations, kernel) @endverbatim
*
* @param self this object
* @param method is one of morphology methods defined by Magick::MorphologyMethod
* @param iterations apply the operation this many times (or no change).
* A value of -1 means loop until no change found.
* How this is applied may depend on the morphology method.
* Typically this is a value of 1.
* @param kernel morphology kernel to apply
*/

VALUE
Image_morphology(VALUE self, VALUE method_v, VALUE iterations, VALUE kernel_v)
{
static VALUE default_channels_const = 0;

if(!default_channels_const)
default_channels_const = rb_const_get(Module_Magick, rb_intern("DefaultChannels"));

return Image_morphology_channel(self, default_channels_const, method_v, iterations, kernel_v);
}

/** Apply a user supplied kernel to the image channel according to the given mophology method.
*
* Ruby Usage:
* - @verbatim Image#morphology_channel(channel, method, iterations, kernel) @endverbatim
*
* @param self this object
* @param channel is a channel type defined by Magick::ChannelType
* @param method is one of morphology methods defined by Magick::MorphologyMethod
* @param iterations apply the operation this many times (or no change).
* A value of -1 means loop until no change found.
* How this is applied may depend on the morphology method.
* Typically this is a value of 1.
* @param kernel morphology kernel to apply
*/

VALUE
Image_morphology_channel(VALUE self, VALUE channel_v, VALUE method_v, VALUE iterations, VALUE kernel_v)
{
Image *image, *new_image;
ExceptionInfo exception;
MorphologyMethod method;
ChannelType channel;
KernelInfo *kernel;

VALUE_TO_ENUM(method_v, method, MorphologyMethod);
VALUE_TO_ENUM(channel_v, channel, ChannelType);
Check_Type(iterations, T_FIXNUM);

if (TYPE(kernel_v) == T_STRING)
kernel_v = rb_class_new_instance(1, &kernel_v, Class_KernelInfo);

if (!rb_obj_is_kind_of(kernel_v, Class_KernelInfo))
rb_raise(rb_eArgError, "expected String or Magick::KernelInfo");

Data_Get_Struct(kernel_v, KernelInfo, kernel);

image = rm_check_destroyed(self);
GetExceptionInfo(&exception);

new_image = MorphologyImageChannel(image, channel, method, NUM2LONG(iterations), kernel, &exception);
rm_check_exception(&exception, new_image, DestroyOnError);
DestroyExceptionInfo(&exception);

rm_ensure_result(new_image);
return rm_image_new(new_image);
}

/**
* Apply a custom convolution kernel to the image.
*
Expand Down
Loading