B4J Question [Solved] Wand tool

Discussion in 'B4J Questions' started by jroriz, Sep 26, 2018.

  1. jroriz

    jroriz Active Member Licensed User


    Is it possible to create something like a wand tool?

    I need to change all the yellow pixels, and then pixels "close to yellow", to black.
    Then all the rest to white.

    I was trying using BitmapCreator, and comparing pixel by pixel. But i could not figure out how to detect a range of pixels that are close to yellow.

    I think this is a hard one...
  2. Roycefer

    Roycefer Well-Known Member Licensed User

    There are a few ways to think about the "closeness" of a color to another color. A simple method that might work for you is to consider the RGB color space as a 3-dimensional euclidean space and just calculate distances using Pythagorean Theorem:
    Dim colorDist As Double = Sqrt(Power(r1-r2,2)+Power(g1-g2,2)+Power(b1-b2,2))
    Then you can select a maximum permissible distance.

    There are more sophisticated ways that involve conversion to HSB color space or treating RGB color space as a vector space and taking inner products. If the Pythagorean Theorem method doesn't suit your needs, we can explore the more sophisticated solutions.

    Note that in the example picture you posted, the non-yellow pixels are all black. If this is representative of the real images you have to use, then it will be easier to just detect black pixels and turn them white and non-black pixels to black.
    jroriz and stevel05 like this.
  3. MarkusR

    MarkusR Well-Known Member Licensed User

    i answered in your other post.
    yellow is just red+green
  4. Sandman

    Sandman Well-Known Member Licensed User

    It might help more if you described how you plan to use the resulting image. I come from a Photoshop background (GIMP nowadays) so I tend to think more in that way than a strictly mathematical way that @Roycefer described.

    So, if you plan to use the resulting image as something you just display or perhaps place on top of another image, I would do this to get a perfect result.

    1. Starting image

    2. Throw away all colour, making it grayscale

    3. Invert it

    4. Adjusting the Levels by setting the background to white (this is not same as working with brightness, the latter destroys image data, Levels ”stretches” the available data)
      (In this specific case I didn't have to set the blackpoint, the yellow was good enough to work with)

    5. And, if that's what you’re aiming for, multiplying the image into another picture:
    KMatle likes this.
  5. MarkusR

    MarkusR Well-Known Member Licensed User

    it would look better with a lossless format like png.
    grey = (r+g+b) / 3

    Sub Process_Globals
    Private xui As XUI
    Private ImageView1 As ImageView
    Private ImageView2 As ImageView

    Sub Test
    Dim Bitmap1 As B4XBitmap = xui.LoadBitmap(File.DirAssets,"clock.png")
    '< a ImageView in layout
    Dim bc As BitmapCreator
    Dim x As Int
    Dim y As Int
    Dim pixel As ARGBColor
    For x = 0 To bc.mWidth-1
    For y = 0 To bc.mHeight-1
    If pixel.r > 64 And pixel.b < 64 Then
                    pixel.r = pixel.r / 
                    pixel.g = pixel.g / 
                    pixel.b = pixel.b / 
                    pixel.r =
                    pixel.g =
                    pixel.b =
    End If
    '< a ImageView in layout
        Bitmap1 = bc.Bitmap
    Dim Out As OutputStream
        Out = 
    File.OpenOutput(File.DirTemp, "Output.png"False)
    End Sub
    Last edited: Sep 26, 2018
    peacemaker and Erel like this.
  6. jroriz

    jroriz Active Member Licensed User

    It was perfect, using the first suggestion (from Roycefer). I did not test the others, but I greatly appreciate it!
    The result was better than I expected.
    The code I got is below. If anyone can improve it, I'm grateful.
    Thank you all. This forum is simply fantastic!

    Final code:

    Sub Clean(Whichcolor As Int, bc As BitmapCreator)
    Dim x, y As Int
    Dim ProtectedColor, ARGB As ARGBColor
        bc.ColorToARGB(Whichcolor, ProtectedColor)
    For x = 0 To bc.mWidth-1
    For y = 0 To bc.mHeight-1

                bc.GetARGB(x, y, ARGB)
    Dim colorDist As Double = Sqrt(Power(ProtectedColor.r-ARGB.r,2)+Power(ProtectedColor.g-ARGB.g,2)+Power(ProtectedColor.b-ARGB.b,2))
    If colorDist > 200 Then
    End If

    End Sub
    How to call: Clean(xui.Color_white, bc), where bc is bitmapcreator.
    Last edited: Sep 28, 2018
    hibrid0, Erel and MarkusR like this.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice