<commit_before>#include "image.h"

static VALUE ImageClass;

namespace Spyglass {
  namespace Image {
    void define_ruby_class() {
      // Class definition
      ImageClass = rb_define_class_under(Spyglass::get_ruby_module(), "Image", rb_cObject);
      rb_define_alloc_func(ImageClass, rb_alloc);
      rb_define_method(ImageClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 0);

      // Class methods
      rb_define_singleton_method(ImageClass, "load", RUBY_METHOD_FUNC(rb_load), -1);

      // Instance methods
      rb_define_method(ImageClass, "canny", RUBY_METHOD_FUNC(rb_canny), 2);
      rb_define_method(ImageClass, "canny!", RUBY_METHOD_FUNC(rb_canny_inplace), 2);
      rb_define_method(ImageClass, "cols", RUBY_METHOD_FUNC(rb_get_cols), 0);
      rb_define_method(ImageClass, "contours", RUBY_METHOD_FUNC(rb_get_contours), 0);
      rb_define_method(ImageClass, "convert", RUBY_METHOD_FUNC(rb_convert), 1);
      rb_define_method(ImageClass, "convert!", RUBY_METHOD_FUNC(rb_convert_inplace), 1);
      rb_define_method(ImageClass, "copy!", RUBY_METHOD_FUNC(rb_copy_inplace), -1);
      rb_define_method(ImageClass, "crop", RUBY_METHOD_FUNC(rb_crop), 1);
      rb_define_method(ImageClass, "crop!", RUBY_METHOD_FUNC(rb_crop_inplace), 1);
      rb_define_method(ImageClass, "dilate", RUBY_METHOD_FUNC(rb_dilate), -1);
      rb_define_method(ImageClass, "dilate!", RUBY_METHOD_FUNC(rb_dilate_inplace), -1);
      rb_define_method(ImageClass, "draw_contours", RUBY_METHOD_FUNC(rb_draw_contours), 1);
      rb_define_method(ImageClass, "draw_rectangle", RUBY_METHOD_FUNC(rb_draw_rectangle), 1);
      rb_define_method(ImageClass, "erode", RUBY_METHOD_FUNC(rb_erode), -1);
      rb_define_method(ImageClass, "erode!", RUBY_METHOD_FUNC(rb_erode_inplace), -1);
      rb_define_method(ImageClass, "mean", RUBY_METHOD_FUNC(rb_mean), -1);
      rb_define_method(ImageClass, "rows", RUBY_METHOD_FUNC(rb_get_rows), 0);
      rb_define_method(ImageClass, "size", RUBY_METHOD_FUNC(rb_get_size), 0);
      rb_define_method(ImageClass, "write", RUBY_METHOD_FUNC(rb_write), 1);
    }

    VALUE get_ruby_class() {
      return ImageClass;
    }

    static VALUE rb_alloc(VALUE self) {
      cv::Mat *mat = new cv::Mat();
      return Data_Wrap_Struct(ImageClass, NULL, rb_free, mat);
    }

    static void rb_free(cv::Mat *img) {
      img->~Mat();
      delete img;
    }

    static VALUE rb_initialize(VALUE self) {
      return self;
    }

    static VALUE rb_canny(VALUE self, VALUE threshold1, VALUE threshold2) {
      Check_Type(threshold1, T_FIXNUM);
      Check_Type(threshold2, T_FIXNUM);

      cv::Mat *img = SG_GET_IMAGE(self);
      cv::Mat canny;

      cv::Canny(*img, canny, NUM2INT(threshold1), NUM2INT(threshold2));
      return Data_Wrap_Struct(ImageClass, NULL, rb_free, new cv::Mat(canny));
    }

    static VALUE rb_canny_inplace(VALUE self, VALUE threshold1, VALUE threshold2) {
      Check_Type(threshold1, T_FIXNUM);
      Check_Type(threshold2, T_FIXNUM);

      cv::Mat *img = SG_GET_IMAGE(self);

      cv::Canny(*img, *img, NUM2INT(threshold1), NUM2INT(threshold2));
      return self;
    }


    static VALUE rb_copy_inplace(int argc, VALUE *argv, VALUE self) {
      VALUE src, mask;
      rb_scan_args(argc, argv, "11", &src, &mask);

      if(CLASS_OF(src) != ImageClass) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Image)",
            rb_obj_classname(src));
      }

      if(RTEST(mask) && CLASS_OF(mask) != ImageClass) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Rect)",
            rb_obj_classname(mask));
      }

      cv::Mat *dest = SG_GET_IMAGE(self);
      cv::Mat *_src = SG_GET_IMAGE(src);

      if(RTEST(mask)) {
        cv::Mat *_mask = SG_GET_IMAGE(mask);
        _src->copyTo(*dest, *_mask);
      } else {
        _src->copyTo(*dest);
      }

      Data_Set_Struct(self, dest);
      return self;
    }

    static VALUE rb_dilate(int argc, VALUE *argv, VALUE self) {
      VALUE iterations;
      rb_scan_args(argc, argv, "01", &iterations);

      if(RTEST(iterations) && TYPE(iterations) != T_FIXNUM) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Fixnum)",
            rb_obj_classname(iterations));
      }

      int iter = RTEST(iterations) ? FIX2INT(iterations) : 1;

      cv::Mat *img = SG_GET_IMAGE(self);

      cv::Mat *new_img = new cv::Mat();
      cv::dilate(*img, *new_img, cv::Mat(), cv::Point(-1, -1), iter);
      return Data_Wrap_Struct(ImageClass, NULL, rb_free, new_img);
    }

    static VALUE rb_dilate_inplace(int argc, VALUE *argv, VALUE self) {
      VALUE iterations;
      rb_scan_args(argc, argv, "01", &iterations);

      if(RTEST(iterations) && TYPE(iterations) != T_FIXNUM) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Fixnum)",
            rb_obj_classname(iterations));
      }

      int iter = RTEST(iterations) ? FIX2INT(iterations) : 1;

      cv::Mat *img = SG_GET_IMAGE(self);

      cv::dilate(*img, *img, cv::Mat(), cv::Point(-1, -1), iter);
      return self;
    }

    static VALUE rb_draw_contours(VALUE self, VALUE contours) {
      if(TYPE(contours) != T_ARRAY && CLASS_OF(contours) == Contour::get_ruby_class())
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Array or Spyglass::Contour)",
            rb_obj_classname(contours));

      cv::Mat *img = SG_GET_IMAGE(self);
      std::vector<std::vector<cv::Point> > ctrs;

      if(TYPE(contours) == T_ARRAY) {
        for(int idx = 0; idx < RARRAY_LEN(contours); idx++) {
          std::vector<cv::Point *> *contour = SG_GET_CONTOUR(rb_ary_entry(contours, idx));
          ctrs.push_back(Contour::to_value_vector(contour));
        }
      } else {
        std::vector<cv::Point *> *contour = SG_GET_CONTOUR(contours);
        ctrs.push_back(Contour::to_value_vector(contour));
      }

      for(int idx = 0; idx < ctrs.size(); idx++)
        cv::drawContours(*img, ctrs, idx, cv::Scalar(0, 0, 0));

      return self;<commit_msg>Fix the logic that picks up on the parameter type for Image#draw_contours<commit_after>#include "image.h"

static VALUE ImageClass;

namespace Spyglass {
  namespace Image {
    void define_ruby_class() {
      // Class definition
      ImageClass = rb_define_class_under(Spyglass::get_ruby_module(), "Image", rb_cObject);
      rb_define_alloc_func(ImageClass, rb_alloc);
      rb_define_method(ImageClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 0);

      // Class methods
      rb_define_singleton_method(ImageClass, "load", RUBY_METHOD_FUNC(rb_load), -1);

      // Instance methods
      rb_define_method(ImageClass, "canny", RUBY_METHOD_FUNC(rb_canny), 2);
      rb_define_method(ImageClass, "canny!", RUBY_METHOD_FUNC(rb_canny_inplace), 2);
      rb_define_method(ImageClass, "cols", RUBY_METHOD_FUNC(rb_get_cols), 0);
      rb_define_method(ImageClass, "contours", RUBY_METHOD_FUNC(rb_get_contours), 0);
      rb_define_method(ImageClass, "convert", RUBY_METHOD_FUNC(rb_convert), 1);
      rb_define_method(ImageClass, "convert!", RUBY_METHOD_FUNC(rb_convert_inplace), 1);
      rb_define_method(ImageClass, "copy!", RUBY_METHOD_FUNC(rb_copy_inplace), -1);
      rb_define_method(ImageClass, "crop", RUBY_METHOD_FUNC(rb_crop), 1);
      rb_define_method(ImageClass, "crop!", RUBY_METHOD_FUNC(rb_crop_inplace), 1);
      rb_define_method(ImageClass, "dilate", RUBY_METHOD_FUNC(rb_dilate), -1);
      rb_define_method(ImageClass, "dilate!", RUBY_METHOD_FUNC(rb_dilate_inplace), -1);
      rb_define_method(ImageClass, "draw_contours", RUBY_METHOD_FUNC(rb_draw_contours), 1);
      rb_define_method(ImageClass, "draw_rectangle", RUBY_METHOD_FUNC(rb_draw_rectangle), 1);
      rb_define_method(ImageClass, "erode", RUBY_METHOD_FUNC(rb_erode), -1);
      rb_define_method(ImageClass, "erode!", RUBY_METHOD_FUNC(rb_erode_inplace), -1);
      rb_define_method(ImageClass, "mean", RUBY_METHOD_FUNC(rb_mean), -1);
      rb_define_method(ImageClass, "rows", RUBY_METHOD_FUNC(rb_get_rows), 0);
      rb_define_method(ImageClass, "size", RUBY_METHOD_FUNC(rb_get_size), 0);
      rb_define_method(ImageClass, "write", RUBY_METHOD_FUNC(rb_write), 1);
    }

    VALUE get_ruby_class() {
      return ImageClass;
    }

    static VALUE rb_alloc(VALUE self) {
      cv::Mat *mat = new cv::Mat();
      return Data_Wrap_Struct(ImageClass, NULL, rb_free, mat);
    }

    static void rb_free(cv::Mat *img) {
      img->~Mat();
      delete img;
    }

    static VALUE rb_initialize(VALUE self) {
      return self;
    }

    static VALUE rb_canny(VALUE self, VALUE threshold1, VALUE threshold2) {
      Check_Type(threshold1, T_FIXNUM);
      Check_Type(threshold2, T_FIXNUM);

      cv::Mat *img = SG_GET_IMAGE(self);
      cv::Mat canny;

      cv::Canny(*img, canny, NUM2INT(threshold1), NUM2INT(threshold2));
      return Data_Wrap_Struct(ImageClass, NULL, rb_free, new cv::Mat(canny));
    }

    static VALUE rb_canny_inplace(VALUE self, VALUE threshold1, VALUE threshold2) {
      Check_Type(threshold1, T_FIXNUM);
      Check_Type(threshold2, T_FIXNUM);

      cv::Mat *img = SG_GET_IMAGE(self);

      cv::Canny(*img, *img, NUM2INT(threshold1), NUM2INT(threshold2));
      return self;
    }


    static VALUE rb_copy_inplace(int argc, VALUE *argv, VALUE self) {
      VALUE src, mask;
      rb_scan_args(argc, argv, "11", &src, &mask);

      if(CLASS_OF(src) != ImageClass) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Image)",
            rb_obj_classname(src));
      }

      if(RTEST(mask) && CLASS_OF(mask) != ImageClass) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Rect)",
            rb_obj_classname(mask));
      }

      cv::Mat *dest = SG_GET_IMAGE(self);
      cv::Mat *_src = SG_GET_IMAGE(src);

      if(RTEST(mask)) {
        cv::Mat *_mask = SG_GET_IMAGE(mask);
        _src->copyTo(*dest, *_mask);
      } else {
        _src->copyTo(*dest);
      }

      Data_Set_Struct(self, dest);
      return self;
    }

    static VALUE rb_dilate(int argc, VALUE *argv, VALUE self) {
      VALUE iterations;
      rb_scan_args(argc, argv, "01", &iterations);

      if(RTEST(iterations) && TYPE(iterations) != T_FIXNUM) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Fixnum)",
            rb_obj_classname(iterations));
      }

      int iter = RTEST(iterations) ? FIX2INT(iterations) : 1;

      cv::Mat *img = SG_GET_IMAGE(self);

      cv::Mat *new_img = new cv::Mat();
      cv::dilate(*img, *new_img, cv::Mat(), cv::Point(-1, -1), iter);
      return Data_Wrap_Struct(ImageClass, NULL, rb_free, new_img);
    }

    static VALUE rb_dilate_inplace(int argc, VALUE *argv, VALUE self) {
      VALUE iterations;
      rb_scan_args(argc, argv, "01", &iterations);

      if(RTEST(iterations) && TYPE(iterations) != T_FIXNUM) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Fixnum)",
            rb_obj_classname(iterations));
      }

      int iter = RTEST(iterations) ? FIX2INT(iterations) : 1;

      cv::Mat *img = SG_GET_IMAGE(self);

      cv::dilate(*img, *img, cv::Mat(), cv::Point(-1, -1), iter);
      return self;
    }

    static VALUE rb_draw_contours(VALUE self, VALUE contours) {
      if(TYPE(contours) != T_ARRAY && CLASS_OF(contours) != Contour::get_ruby_class())
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Array or Spyglass::Contour)",
            rb_obj_classname(contours));

      cv::Mat *img = SG_GET_IMAGE(self);
      std::vector<std::vector<cv::Point> > ctrs;

      if(TYPE(contours) == T_ARRAY) {
        for(int idx = 0; idx < RARRAY_LEN(contours); idx++) {
          std::vector<cv::Point *> *contour = SG_GET_CONTOUR(rb_ary_entry(contours, idx));
          ctrs.push_back(Contour::to_value_vector(contour));
        }
      } else {
        std::vector<cv::Point *> *contour = SG_GET_CONTOUR(contours);
        ctrs.push_back(Contour::to_value_vector(contour));
      }

      for(int idx = 0; idx < ctrs.size(); idx++)
        cv::drawContours(*img, ctrs, idx, cv::Scalar(0, 0, 0));

      return self;
{'fraction_non_alphanumeric': 0.1349009900990099, 'fraction_numerical': 0.009240924092409241, 'mean_word_length': 3.705357142857143, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4187712', 'n_tokens_mistral': 4481, 'n_tokens_neox': 4229, 'n_words': 782}