14
$\begingroup$

Bug introduced in 11 or earlier and persisting through 11.3

CASE:4076121


I'm having a hard time to understand how I can use HighlightImage and only draw the boundary of a binary image with a thickness of exactly one pixel. The documentation suggests that I can use

HighlightImage[
 img,
 {{"Boundary", thickness}, Binarize[img]}
]

but that doesn't work properly. Here is a small example that shows the behavior on Mathematica 11.3 on OS X

img = Import["https://i.sstatic.net/DLGJC.png"];
Manipulate[
 With[{img = ImageResize[img, size]},
  Show[HighlightImage[
    img,
    {{"Boundary", thickness}, Binarize[img]}
    ], ImageSize -> 1024
   ]
  ], {size, 100, 500, 1}, {thickness, .1, 10}
 ]

As you will see, the thickness setting has no influence and if you scale the image up with the size slider, then the boundary thickness covers many pixels

Mathematica graphics

$\endgroup$
6
  • $\begingroup$ I noticed this too, but didn't complain to WRI. It changed in some recent version. It seemed intentional ... $\endgroup$
    – Szabolcs
    Commented Jun 6, 2018 at 14:05
  • 1
    $\begingroup$ @Szabolcs It seems like they broke this functionality when refactoring the code (see my answer below) - no idea why they did it in the first place though $\endgroup$
    – Lukas Lang
    Commented Jun 6, 2018 at 14:11
  • 1
    $\begingroup$ @Szabolcs always complain. It may get fixed )) $\endgroup$
    – Batracos
    Commented Jun 19, 2018 at 18:38
  • $\begingroup$ @LukasLang it is indeed a bug that slipped through the testing. I just committed a fix. As you where wondering, the reason is that directives like "Boundary" should change the behaviour of all the subsequent primitives, resetting other custom scopes like "Blur". $\endgroup$
    – Batracos
    Commented Jun 19, 2018 at 18:43
  • $\begingroup$ @Batracos That's great to hear! Regarding the reasoning: Thanks for the insight. I was also wondering why some definitions are only loaded by toGraphicsPrimitiveDefinitions - is this something entirely related to other internals or is there some reason behind it that could also be relevant for custom code? $\endgroup$
    – Lukas Lang
    Commented Jun 19, 2018 at 18:49

1 Answer 1

11
$\begingroup$

The following fixes the issue:

If[$VersionNumber>=11.3,
  Begin["Image`InteractiveDump`"],
  Begin["Image`ColorOperationsDump`"]
];
HighlightImage;
DownValues[toGraphicsPrimitive] = DownValues[toGraphicsPrimitive] /. 
  {HoldPattern[pre_; Sequence[s__]] :> ((pre; {s}) /. {res__} :> res)};
End[];

enter image description here

Why does this work

It appears that at some point, every definition of Image`InteractiveDump`toGraphicsPrimitive (toGP in the following) was prepended with `toGraphicsPrimitiveDefinitions (so toGP[args]:=rhs became toGP[args]:=(toGPD;rhs)). It looks like this loads some more definitions for toGP, but no idea what the purpose of doing it this way is...

The issue is that the signature of toGP that handles {"Boundary", thickness_} returned a Sequence, which is evaluated prematurely by the CompoundExpression that got wrapped around. The above fix resolves this issue by only introducing the Sequence head after the CompundExpression is done evaluating. (please leave a comment if you find a more straightforward solution to protect the Sequence head)

$\endgroup$
10
  • $\begingroup$ Thanks for spelunking for me. I was really worried I simply use it wrong somehow. I'm looking at it in detail later. +1 $\endgroup$
    – halirutan
    Commented Jun 6, 2018 at 15:09
  • 1
    $\begingroup$ @Mathe172 - Please how to use the fix, where to put the Begin-End sequence? Is it a procedure, shall I call it before HighligtImage? Thanks in advance $\endgroup$
    – CJoe
    Commented Jun 10, 2018 at 13:33
  • 1
    $\begingroup$ @CJoe Yes, just execute it once before you call HighlightImage. For example, you can add it as first line to your notebook $\endgroup$
    – Lukas Lang
    Commented Jun 10, 2018 at 13:36
  • $\begingroup$ @Mathe172 - Im sorry, I cant make it working. Either it does not have influence or the Mathematica crashes (on Pi3). Would you be so kind and put the working code of that your example above? $\endgroup$
    – CJoe
    Commented Jun 10, 2018 at 15:43
  • 1
    $\begingroup$ A simpler fix that however requires changing existing code is to use ... , FaceForm[], EdgeForm[AbsoluteThickness[n]], ... in place of {"Boundary", n}. $\endgroup$
    – Batracos
    Commented Jun 19, 2018 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.