[Bf-blender-cvs] [a05408220df] greasepencil-object: GPencil: New operator to generate Grease Pencil from images

Antonio Vazquez noreply at git.blender.org
Sun Dec 8 13:17:06 CET 2019


Commit: a05408220dfd143e70cf20b0584910c130246d35
Author: Antonio Vazquez
Date:   Sun Dec 8 13:16:58 2019 +0100
Branches: greasepencil-object
https://developer.blender.org/rBa05408220dfd143e70cf20b0584910c130246d35

GPencil: New operator to generate Grease Pencil from images

This takes a image and generate a new grease pencil object and each pixel is a vertex point. THe image is generated by lines.

As an option, an inverted  mask can be generated

===================================================================

M	release/scripts/startup/bl_ui/space_image.py
M	source/blender/blenkernel/BKE_gpencil.h
M	source/blender/blenkernel/intern/gpencil.c
M	source/blender/editors/gpencil/gpencil_convert.c
M	source/blender/editors/gpencil/gpencil_intern.h
M	source/blender/editors/gpencil/gpencil_ops.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index d4aab89ba3f..0677e2e4b62 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -254,6 +254,7 @@ class IMAGE_MT_image(Menu):
         if ima:
             layout.separator()
             layout.operator("palette.extract_from_image", text="Extract Palette")
+            layout.operator("gpencil.image_to_grease_pencil", text="Generate Grease Pencil")
 
 
 class IMAGE_MT_image_invert(Menu):
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 8050c027de0..8dc19ed32e5 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -34,6 +34,7 @@ struct Main;
 struct Material;
 struct Object;
 struct Scene;
+struct SpaceImage;
 struct ToolSettings;
 struct bDeformGroup;
 struct bGPDframe;
@@ -296,6 +297,11 @@ void BKE_gpencil_convert_curve(struct Main *bmain,
 
 void BKE_gpencil_palette_ensure(struct Main *bmain, struct Scene *scene);
 
+bool BKE_gpencil_from_image(struct SpaceImage *sima,
+                            struct bGPDframe *gpf,
+                            const float size,
+                            const bool mask);
+
 extern void (*BKE_gpencil_batch_cache_dirty_tag_cb)(struct bGPdata *gpd);
 extern void (*BKE_gpencil_batch_cache_free_cb)(struct bGPdata *gpd);
 
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 80ae8308934..69a4fca1485 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -39,12 +39,15 @@
 
 #include "BLT_translation.h"
 
+#include "IMB_imbuf_types.h"
+
 #include "DNA_anim_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_material_types.h"
 #include "DNA_gpencil_types.h"
 #include "DNA_userdef_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_space_types.h"
 #include "DNA_object_types.h"
 
 #include "BKE_action.h"
@@ -55,6 +58,7 @@
 #include "BKE_deform.h"
 #include "BKE_gpencil.h"
 #include "BKE_icons.h"
+#include "BKE_image.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
@@ -3560,3 +3564,82 @@ void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene)
     }
   }
 }
+
+static void BKE_gpencil_get_pixel(const ImBuf *ibuf, const int idx, float r_col[4])
+{
+  if (ibuf->rect_float) {
+    const float *frgba = &ibuf->rect_float[idx * 4];
+    copy_v4_v4(r_col, frgba);
+  }
+  else if (ibuf->rect) {
+    unsigned char *cp = (unsigned char *)(ibuf->rect + idx);
+    r_col[0] = (float)cp[0] / 255.0f;
+    r_col[1] = (float)cp[1] / 255.0f;
+    r_col[2] = (float)cp[2] / 255.0f;
+    r_col[3] = (float)cp[3] / 255.0f;
+  }
+  else {
+    zero_v4(r_col);
+  }
+}
+
+bool BKE_gpencil_from_image(SpaceImage *sima, bGPDframe *gpf, const float size, const bool mask)
+{
+  Image *image = sima->image;
+  bool done = false;
+
+  if (image == NULL) {
+    return false;
+  }
+
+  ImageUser iuser = sima->iuser;
+  void *lock;
+  ImBuf *ibuf;
+
+  ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
+
+  if (ibuf->rect) {
+    int img_x = ibuf->x;
+    int img_y = ibuf->y;
+
+    // space = 0.005 pixels = image.pixels
+    float color[4];
+    bGPDspoint *pt;
+    for (int row = 0; row < img_y; row++) {
+      /* Create new stroke */
+      bGPDstroke *gps = BKE_gpencil_add_stroke(gpf, 0, img_x, size * 1000);
+      done = true;
+      for (int col = 0; col < img_x; col++) {
+        int pix = ((row * img_x) + col);
+        BKE_gpencil_get_pixel(ibuf, pix, color);
+        pt = &gps->points[col];
+        pt->pressure = 1.2f; /* expand the point to avoid gaps. */
+        pt->x = col * size;
+        pt->z = row * size;
+        if (!mask) {
+          copy_v3_v3(pt->mix_color, color);
+          pt->mix_color[3] = 1.0f;
+          pt->strength = color[3];
+        }
+        else {
+          zero_v3(pt->mix_color);
+          pt->mix_color[3] = 1.0f;
+          pt->strength = 1.0f - color[3];
+        }
+
+        /* Selet Alpha points. */
+        if (pt->strength < 0.03f) {
+          gps->flag |= GP_STROKE_SELECT;
+          pt->flag |= GP_SPOINT_SELECT;
+        }
+      }
+      /* Dissolve any selected point. */
+      BKE_gpencil_dissolve_points(gpf, gps, GP_SPOINT_SELECT);
+    }
+  }
+
+  /* Free memory. */
+  BKE_image_release_ibuf(image, ibuf, lock);
+
+  return done;
+}
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index 4a91a90c075..11317491227 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -1749,4 +1749,87 @@ void GPENCIL_OT_convert(wmOperatorType *ot)
   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 }
 
-/* ************************************************ */
+/* Generate Grease Pencil from Image. */
+static bool image_to_gpencil_poll(bContext *C)
+{
+  SpaceLink *sl = CTX_wm_space_data(C);
+  if (sl->spacetype == SPACE_IMAGE) {
+    return true;
+  }
+
+  return false;
+}
+
+static int image_to_gpencil_exec(bContext *C, wmOperator *op)
+{
+  const float size = RNA_float_get(op->ptr, "size");
+  const bool is_mask = RNA_boolean_get(op->ptr, "mask");
+
+  Main *bmain = CTX_data_main(C);
+  Scene *scene = CTX_data_scene(C);
+  SpaceImage *sima = CTX_wm_space_image(C);
+  bool done = false;
+
+  if (sima->image == NULL) {
+    return OPERATOR_CANCELLED;
+  }
+
+  /* Create Object. */
+  const float *cur = scene->cursor.location;
+  ushort local_view_bits = 0;
+  Object *ob = ED_gpencil_add_object(C, cur, local_view_bits);
+  DEG_relations_tag_update(bmain); /* added object */
+
+  /* Create material slot. */
+  Material *ma = BKE_gpencil_object_material_new(bmain, ob, "Image Material", NULL);
+  MaterialGPencilStyle *gp_style = ma->gp_style;
+  gp_style->mode = GP_STYLE_MODE_BOX;
+
+  /* Add layer and frame. */
+  bGPdata *gpd = (bGPdata *)ob->data;
+  bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, "Image Layer", true);
+  bGPDframe *gpf = BKE_gpencil_frame_addnew(gpl, CFRA);
+  done = BKE_gpencil_from_image(sima, gpf, size, is_mask);
+
+  if (done) {
+    BKE_reportf(op->reports, RPT_INFO, "Object created");
+  }
+
+  return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_image_to_grease_pencil(wmOperatorType *ot)
+{
+  PropertyRNA *prop;
+
+  /* identifiers */
+  ot->name = "Generate Grease Pencil Object using image as source";
+  ot->idname = "GPENCIL_OT_image_to_grease_pencil";
+  ot->description = "Generate a Grease Pencil Object using Image as source";
+
+  /* api callbacks */
+  ot->exec = image_to_gpencil_exec;
+  ot->poll = image_to_gpencil_poll;
+
+  /* flags */
+  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+  /* properties */
+  ot->prop = RNA_def_float(ot->srna,
+                           "size",
+                           0.005f,
+                           0.0001f,
+                           10.0f,
+                           "Point Size",
+                           "Size used for graese pencil points",
+                           0.001f,
+                           1.0f);
+  RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+
+  prop = RNA_def_boolean(ot->srna,
+                         "mask",
+                         false,
+                         "Generate Mask",
+                         "Create an inverted image for masking using alpha channel");
+  RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 9c1e0a30709..ee0cbdf7c93 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -465,6 +465,7 @@ void GPENCIL_OT_frame_clean_fill(struct wmOperatorType *ot);
 void GPENCIL_OT_frame_clean_loose(struct wmOperatorType *ot);
 
 void GPENCIL_OT_convert(struct wmOperatorType *ot);
+void GPENCIL_OT_image_to_grease_pencil(struct wmOperatorType *ot);
 
 enum {
   GP_STROKE_JOIN = -1,
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 0efead2f9fe..dc4927c252f 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -595,6 +595,8 @@ void ED_operatortypes_gpencil(void)
 
   WM_operatortype_append(GPENCIL_OT_convert);
 
+  WM_operatortype_append(GPENCIL_OT_image_to_grease_pencil);
+
   WM_operatortype_append(GPENCIL_OT_stroke_arrange);
   WM_operatortype_append(GPENCIL_OT_stroke_change_color);
   WM_operatortype_append(GPENCIL_OT_stroke_lock_color);



More information about the Bf-blender-cvs mailing list