-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Fixed bug for drawing mask contour on a transparent background. #389
base: main
Are you sure you want to change the base?
Conversation
looks good, can you add a test? |
The contour used was lacking a transparency channel. Also fixed the conditions for plotting a contour. Now contour_color=None or contour_width=0 means that no contour will be plotted.
1c2dd8d
to
b612fe3
Compare
Should be good now. |
test/test_wordcloud.py
Outdated
mask = np.array(Image.open(mask_file)) | ||
w = WordCloud(mode='RGBA', background_color=None, contour_color='blue', contour_width=2, mask=mask, | ||
max_words=50, width=800, height=800) | ||
w.generate(THIS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So does this give an error? You could probaby also just create an empty mask to reproduce it instead of loading one, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if what you describe works or not, but why would you be trying to draw a contour with an empty mask?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right maybe that's not the very best idea but you could just add a stripe to one side or something. The point is to make the test as simple and self-contained as possible. And if you can reproduce the error with a small numpy array that would be easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The image is in the repo, so it is adequately self-contained. Sure, someone with a better grasp of PIL can remove this dependency in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mask = np.ones((100, 100))
mask[:, -10:] = 0
should do it, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually better
mask = np.zeros((100, 100, 3), dtype="ubyte")
mask[:, -10:] = 255
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup! Looks good. This would have taken me at least another 30' to figure out. Haven't worked with matrices and stuff for quite a long time.
test/test_wordcloud.py
Outdated
w = WordCloud(mode='RGBA', background_color=None, contour_color='blue', contour_width=2, mask=mask, | ||
max_words=50, width=800, height=800) | ||
w.generate(THIS) | ||
w.to_file(NamedTemporaryFile(suffix=".png").name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's how the previously buggy code path is triggered. If you don't write to a file the contour is not drawn. The exception happens here:
ret = np.array(img) * np.invert(contour)
ValueError: operands could not be broadcast together with shapes (900,900,4) (900,900,3)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could just do to_image()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. Fixed that.
c5966f4
to
b06b8b3
Compare
d5ef10d
to
ab85b24
Compare
can you remind me what the reason was to change the default color? |
I rebase the patches to the currently stable branch diff --git a/wordcloud/wordcloud.py b/wordcloud/wordcloud.py
index 26b0d54..93dc6b1 100644
--- a/wordcloud/wordcloud.py
+++ b/wordcloud/wordcloud.py
@@ -311,7 +311,7 @@ class WordCloud(object):
max_font_size=None, font_step=1, mode="RGB",
relative_scaling='auto', regexp=None, collocations=True,
colormap=None, normalize_plurals=True, contour_width=0,
- contour_color='black', repeat=False,
+ contour_color=None, repeat=False,
include_numbers=False, min_word_length=0, collocation_threshold=30):
if font_path is None:
font_path = FONT_PATH
@@ -1006,7 +1006,7 @@ class WordCloud(object):
def _draw_contour(self, img):
"""Draw mask contour on a pillow image."""
- if self.mask is None or self.contour_width == 0:
+ if self.mask is None or self.contour_color is None or self.contour_width == 0:
return img
mask = self._get_bolean_mask(self.mask) * 255
@@ -1024,12 +1024,14 @@ class WordCloud(object):
contour = Image.fromarray(contour)
contour = contour.filter(ImageFilter.GaussianBlur(radius=radius))
contour = np.array(contour) > 0
- contour = np.dstack((contour, contour, contour))
+ if img.mode == 'RGBA':
+ contour = np.dstack((contour, contour, contour, contour))
+ else:
+ contour = np.dstack((contour, contour, contour))
# color the contour
ret = np.array(img) * np.invert(contour)
- if self.contour_color != 'black':
- color = Image.new(img.mode, img.size, self.contour_color)
- ret += np.array(color) * contour
+ color = np.array(Image.new(img.mode, img.size, self.contour_color))
+ ret += color * contour
return Image.fromarray(ret)
diff --git a/wordcloud/wordcloud_cli.py b/wordcloud/wordcloud_cli.py
index 125a86f..03c7db6 100644
--- a/wordcloud/wordcloud_cli.py
+++ b/wordcloud/wordcloud_cli.py
@@ -126,7 +126,7 @@ def make_parser():
dest='contour_width',
help='if greater than 0, draw mask contour (default: 0)')
parser.add_argument(
- '--contour_color', metavar='color', default='black', type=str,
+ '--contour_color', metavar='color', default=None, type=str,
dest='contour_color',
help='use given color as mask contour color -'
' accepts any value from PIL.ImageColor.getcolor') |
when will this be merged? |
Just adding another bump to this bug fix :-) |
I had problems generating images with
mode='RGBA', background_color=None
. The contour used when rendering the image was lacking a transparency channel. This should fix it.