[Bf-blender-cvs] [618a28368a9] greasepencil-object: GPencil: New operator to extract palettes from Images
Antonio Vazquez
noreply at git.blender.org
Sat Nov 16 20:19:32 CET 2019
Commit: 618a28368a9aebd5f08d8c4ef61d1f7c15dfd707
Author: Antonio Vazquez
Date: Sat Nov 16 20:19:25 2019 +0100
Branches: greasepencil-object
https://developer.blender.org/rB618a28368a9aebd5f08d8c4ef61d1f7c15dfd707
GPencil: New operator to extract palettes from Images
Also more changes to sort colors, add a threshold , etc.
===================================================================
M source/blender/editors/gpencil/gpencil_intern.h
M source/blender/editors/gpencil/gpencil_ops.c
M source/blender/editors/gpencil/gpencil_vertex_ops.c
===================================================================
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 3c5cbe8617b..db08e71279c 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -507,6 +507,7 @@ void GPENCIL_OT_stroke_merge_material(struct wmOperatorType *ot);
void GPENCIL_OT_material_to_vertex_color(struct wmOperatorType *ot);
void GPENCIL_OT_extract_palette(struct wmOperatorType *ot);
+void GPENCIL_OT_extract_palette_from_image(struct wmOperatorType *ot);
void GPENCIL_OT_transform_fill(struct wmOperatorType *ot);
void GPENCIL_OT_reset_transform_fill(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 0a0a3ff079e..0715237dabd 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -454,6 +454,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_material_to_vertex_color);
WM_operatortype_append(GPENCIL_OT_extract_palette);
+ WM_operatortype_append(GPENCIL_OT_extract_palette_from_image);
WM_operatortype_append(GPENCIL_OT_transform_fill);
WM_operatortype_append(GPENCIL_OT_reset_transform_fill);
diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c
index eff9ba4c814..0a52d7cecbc 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_ops.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c
@@ -24,6 +24,8 @@
#include "MEM_guardedalloc.h"
+#include "IMB_imbuf_types.h"
+
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
@@ -37,6 +39,7 @@
#include "BKE_context.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
+#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_paint.h"
@@ -496,12 +499,95 @@ void GPENCIL_OT_vertex_color_set(wmOperatorType *ot)
RNA_def_float(ot->srna, "factor", 1.0f, 0.001f, 1.0f, "Factor", "Mix Factor", 0.001f, 1.0f);
}
+typedef struct GPHue {
+ float rgb[3];
+ float hue;
+ float sat;
+} GPHue;
+
+/* helper function to sort using qsort */
+static int gpencil_compare_hue_sat(const void *a1, const void *a2)
+{
+ const GPHue *ps1 = a1, *ps2 = a2;
+ int a = ps1->hue * 1e6 + ps1->sat * 1e3;
+ int b = ps2->hue * 1e6 + ps2->sat * 1e3;
+
+ if (a < b) {
+ return -1;
+ }
+ else if (a > b) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static bool gpencil_create_palette_from_hash(Main *bmain, GHash *color_table)
+{
+ GPHue *color_array = NULL;
+ GPHue *col_elm = NULL;
+ bool done = false;
+
+ int totpal = BLI_ghash_len(color_table);
+
+ if (totpal > 0) {
+ color_array = MEM_calloc_arrayN(totpal, sizeof(GPHue), __func__);
+ /* Put all colors in an array. */
+ GHashIterator gh_iter;
+ int t = 0;
+ GHASH_ITER (gh_iter, color_table) {
+ const uint col = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter));
+ float r, g, b;
+ float h, s, v;
+ cpack_to_rgb(col, &r, &g, &b);
+ rgb_to_hsv(r, g, b, &h, &s, &v);
+
+ col_elm = &color_array[t];
+ col_elm->rgb[0] = r;
+ col_elm->rgb[1] = g;
+ col_elm->rgb[2] = b;
+ col_elm->hue = h;
+ col_elm->sat = s;
+ t++;
+ }
+ }
+
+ /* Create the Palette. */
+ if (totpal > 0) {
+ /* Sort by Hue and saturation. */
+ qsort(color_array, totpal, sizeof(GPHue), gpencil_compare_hue_sat);
+
+ Palette *palette = BKE_palette_add(bmain, "Palette");
+ if (palette) {
+ for (int i = 0; i < totpal; i++) {
+ col_elm = &color_array[i];
+ PaletteColor *palcol = BKE_palette_color_add(palette);
+ if (palcol) {
+ copy_v3_v3(palcol->rgb, col_elm->rgb);
+ }
+ }
+ done = true;
+ }
+ }
+ else {
+ done = false;
+ }
+
+ if (totpal > 0) {
+ MEM_SAFE_FREE(color_array);
+ }
+
+ return done;
+}
+
/* Helper to extract color for palette. */
-static bool gp_extract_palette(bContext *C, const bool selected)
+static bool gp_extract_palette(bContext *C, const bool selected, const int threshold)
{
Main *bmain = CTX_data_main(C);
Object *ob = CTX_data_active_object(C);
bool done = false;
+ const float range = pow(10.0f, threshold);
+ float col[3];
GHash *color_table = BLI_ghash_int_new(__func__);
@@ -545,8 +631,11 @@ static bool gp_extract_palette(bContext *C, const bool selected)
/* Fill color. */
if (gps->mix_color_fill[3] > 0.0f) {
- uint key = rgb_to_cpack(
- gps->mix_color_fill[0], gps->mix_color_fill[1], gps->mix_color_fill[2]);
+ col[0] = truncf(gps->mix_color_fill[0] * range) / range;
+ col[1] = truncf(gps->mix_color_fill[1] * range) / range;
+ col[2] = truncf(gps->mix_color_fill[2] * range) / range;
+
+ uint key = rgb_to_cpack(col[0], col[1], col[2]);
if (!BLI_ghash_haskey(color_table, POINTER_FROM_INT(key))) {
BLI_ghash_insert(color_table, POINTER_FROM_INT(key), POINTER_FROM_INT(key));
@@ -557,7 +646,11 @@ static bool gp_extract_palette(bContext *C, const bool selected)
bGPDspoint *pt;
int i;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- uint key = rgb_to_cpack(pt->mix_color[0], pt->mix_color[1], pt->mix_color[2]);
+ col[0] = truncf(pt->mix_color[0] * range) / range;
+ col[1] = truncf(pt->mix_color[1] * range) / range;
+ col[2] = truncf(pt->mix_color[2] * range) / range;
+
+ uint key = rgb_to_cpack(col[0], col[1], col[2]);
if (!BLI_ghash_haskey(color_table, POINTER_FROM_INT(key))) {
BLI_ghash_insert(color_table, POINTER_FROM_INT(key), POINTER_FROM_INT(key));
}
@@ -568,27 +661,7 @@ static bool gp_extract_palette(bContext *C, const bool selected)
CTX_DATA_END;
/* Create the Palette. */
- if (BLI_ghash_len(color_table) > 0) {
- GHashIterator gh_iter;
- Palette *palette = BKE_palette_add(bmain, "Palette");
- if (palette) {
- GHASH_ITER (gh_iter, color_table) {
- const uint col = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter));
- float r, g, b;
- cpack_to_rgb(col, &r, &g, &b);
- PaletteColor *palcol = BKE_palette_color_add(palette);
- if (palcol) {
- palcol->rgb[0] = r;
- palcol->rgb[1] = g;
- palcol->rgb[2] = b;
- }
- }
- done = true;
- }
- }
- else {
- done = false;
- }
+ done = gpencil_create_palette_from_hash(bmain, color_table);
/* Free memory. */
BLI_ghash_free(color_table, NULL, NULL);
@@ -823,7 +896,7 @@ static int gp_material_to_vertex_exec(bContext *C, wmOperator *op)
/* Generate a Palette. */
if (palette) {
- gp_extract_palette(C, selected);
+ gp_extract_palette(C, selected, 1);
}
/* Clean unused materials. */
@@ -857,6 +930,7 @@ void GPENCIL_OT_material_to_vertex_color(wmOperatorType *ot)
"Remove any unused material after the conversion");
RNA_def_boolean(ot->srna, "palette", true, "Create Palette", "Create a new palette with colors");
RNA_def_boolean(ot->srna, "selected", false, "Only Selected", "Convert only selected strokes");
+ RNA_def_int(ot->srna, "threshold", 3, 1, 4, "Threshold", "", 1, 4);
}
/* Extract Palette from Vertex Color. */
@@ -874,8 +948,9 @@ static bool gp_extract_palette_poll(bContext *C)
static int gp_extract_palette_exec(bContext *C, wmOperator *op)
{
const bool selected = RNA_boolean_get(op->ptr, "selected");
+ const int threshold = RNA_int_get(op->ptr, "threshold");
- if (gp_extract_palette(C, selected)) {
+ if (gp_extract_palette(C, selected, threshold)) {
BKE_reportf(op->reports, RPT_INFO, "Palette created");
}
else {
@@ -902,4 +977,106 @@ void GPENCIL_OT_extract_palette(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_boolean(
ot->srna, "selected", false, "Only Selected", "Convert only selected strokes");
+ RNA_def_int(ot->srna, "threshold", 1, 1, 4, "Threshold", "", 1, 4);
+}
+
+/* Extract Palette from Image. */
+static bool gp_extract_palette_img_poll(bContext *C)
+{
+ SpaceLink *sl = CTX_wm_space_data(C);
+ if (sl->spacetype == SPACE_IMAGE) {
+ return true;
+ }
+
+ return false;
+}
+
+/* return pixel data (rgba) at index */
+static void get_pixel(const ImBuf *ibuf, const int idx, float r_col[3])
+{
+ if (ibuf->rect_float) {
+ const float *frgba = &ibuf->rect_float[idx * 4];
+ copy_v3_v3(r_col, frgba);
+ }
+ else if (ibuf->rect) {
+ float r, g, b;
+ uint *cp = &ibuf->rect[idx];
+ uint a = *cp;
+ cpack_to_rgb(a, &r, &g, &b);
+ r_col[0] = r;
+ r_col[1] = g;
+ r_col[2] = b;
+ }
+ else {
+ BLI_assert(!"gpencil_fill.c - get_pixel() non-float case is used!");
+ zero_v4(r_col);
+ }
+}
+
+static int gp_extract_palette_img_exec(bContext *C, wmOperator *op)
+{
+ const int threshold = RNA_int_get(op->ptr, "threshold");
+
+ Main *bmain = CTX_data_main(C);
+ bool done = false;
+ int totpal = 0;
+
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *image = sima->image;
+ ImageUser iuser = sima->iuser;
+ void *lock;
+ ImBuf *ibuf;
+ GHash *color_table = BLI_ghash_int_new(__func__);
+
+ ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
+
+ if (ibuf->rect) {
+ const int maxpixel = (ibuf->x * ibuf->y) - 1;
+
+ /* Extract all colors. */
+ for (int v = maxpixel; v != 0; v--) {
+ float col[3];
+ get_pixel(ibuf, v, col);
+
+ const float range = pow(10.0f, threshold);
+ col[0] = truncf(col[0] * range) / range;
+ col[1] = truncf(col[1] * range) / range;
+ col[2] = truncf(col[2] * range) / range;
+
+ uint key = rgb_to_cpack(col[0], col[1], col[2]);
+ if (!BLI_ghash_haskey(color_table, POINTER_FROM_INT(key))) {
+ BLI_ghash_insert(color_table, POINTER_FROM_INT(key), POINTER_FROM_INT(key));
+ }
+ }
+
+ done = gpencil_create_palette_from_hash(bmain, color_table);
+ }
+
+ /* Free memory. */
+ BLI_ghash_free(color_table, NULL, NULL);
+ BKE_image_release_ibuf(image, ibuf, lock);
+
+ if (done) {
+ BKE_reportf(op->reports, RPT_INFO, "Palette crea
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list