Anyone got a great idea on how to draw the HSV color space FAST

Basically I need to make something that is sort of like the Color picker because - well I use an IDE that DOESNT have “Insert Color” as one of its tools (go figure)

So I quickly write a Xojo app (yeah yeah) and had it do RGB colors and automatically just puts whatever color you change the slider to on the clipboard so its “select color go back to other IDE & paste”

That works dandy

Then I though “Gee I should make an HSV picker as well since its a lt more visual in terms of the colors etc.”

And the ever famous “How hard can that be ?”

Well the initial code to draw the color wheel - icky but decently quick
And even after hand tweaking code & moving things out of the loops I could etc its still not fast
Even with compiling using agressive - not super fast
Fast enough to not be totally annoying but not as fast was it might be

So the quest is a way, on macOS to draw using HSV colors the color wheel
I have two sliders on the page

sliderAlphaHSV live scrolling on min = 0 max = 255
sliderValue live scrolling on min = 0 max = 100

Any takers on making this code super fast ?
the one parameter it takes is a picture created as

    p = new picture( 200, 200)

everything else should be local
tried to make it faster by drawing 8 points each pass but not sure that helped or not

Protected Sub DrawHSV(p as picture)
  #Pragma NilObjectChecking False
  #Pragma BackgroundTasks False
  #Pragma BoundsChecking False
  #Pragma StackOverflowChecking False
  
  Dim g As graphics = p.graphics
  
  g.ClearRect 0, 0, g.width, g.height
  
  Const drawLabels = False
  
  Const Pi = 3.14159
  Const maxDegrees = 45
  
  Dim toRadValue As Double = pi/180
  
  Dim maxRadius As Integer = (g.width/2) - (.1 * (g.width/2) )
  
  Dim xpos As Double = g.width / 2
  Dim ypos As Double = g.height / 2
  
  Dim alphaValue As Integer = sliderAlphaHSV.value
  Dim colorValue As Double = sliderValue.value / sliderValue.Maximum
  
  For saturation As Integer = 0 To maxRadius
    
    Dim osize As Double = Max(1, .1 * saturation)
    
    Dim satValue As Double = saturation / maxRadius
    
    For hue As Integer = 0 To maxDegrees
      
      Dim tmpHueQ1a As Double = hue
      Dim tmpHueQ1b As Double = tmpHueQ1a + 45
      Dim tmpHueQ2a As Double = tmpHueQ1b + 45
      Dim tmpHueQ2b As Double = tmpHueQ2a + 45
      Dim tmpHueQ3a As Double = tmpHueQ2b + 45
      Dim tmpHueQ3b As Double = tmpHueQ3a + 45
      Dim tmpHueQ4a As Double = tmpHueQ3b + 45
      Dim tmpHueQ4b As Double = tmpHueQ4a + 45
      
      Dim xoffs As Double
      Dim yoffs As Double
      
      xoffs = Cos(tmpHueQ1a*toRadValue) * saturation
      yoffs = Sin(tmpHueQ1a*toRadValue) * saturation
      
      '     |
      '     |
      ' ----|----
      '     |   1a
      '     | 
      g.ForeColor = HSV( tmpHueQ1a / 360 , satValue , colorValue, alphaValue )
      g.FillOval xpos + xoffs, ypos + yOffs , osize, osize
      If drawLabels And saturation = maxRadius Then
         g.forecolor = &cffffff
         g.DrawString Str(tmpHueQ1a), xpos + xoffs, ypos + yOffs
      End If
      
      '     |
      '     |
      ' ----|----
      '     |   
      '   2a| 
      g.ForeColor = HSV( tmpHueQ2a / 360 , satValue , colorValue, alphaValue )
      g.FillOval xpos - yoffs, ypos + xOffs , osize, osize
      If drawLabels And saturation = maxRadius Then
         g.forecolor = &cffffff
         g.DrawString Str(tmpHueQ2a), xpos - yoffs, ypos + xOffs
      End If
      
      '     |
      ' 3a  |
      ' ----|----
      '     |   
      '     | 
      g.ForeColor = HSV( tmpHueQ3a / 360 , satValue , colorValue, alphaValue )
      g.FillOval xpos - xoffs, ypos - yOffs , osize, osize
      If drawLabels And saturation = maxRadius Then
         g.forecolor = &cffffff
         g.DrawString Str(tmpHueQ3a), xpos - xoffs, ypos - yOffs
      End If
      
      '     |4a
      '     |
      ' ----|----
      '     |  
      '     | 
      g.ForeColor = HSV( tmpHueQ4a / 360 , satValue , colorValue, alphaValue )
      g.FillOval xpos + yoffs, ypos - xOffs , osize, osize
      If drawLabels And saturation = maxRadius Then
         g.forecolor = &cffffff
         g.DrawString Str(tmpHueQ4a), xpos + yoffs, ypos - xOffs
      End If
      
      '     |
      '     |
      ' ----|----
      '     |   
      '     |1b 
      xoffs = Cos(tmpHueQ1b*pi/180) * saturation
      yoffs = Sin(tmpHueQ1b*pi/180) * saturation
      
      
      g.ForeColor = HSV( tmpHueQ1b / 360 , satValue , colorValue, alphaValue )
      g.FillOval xpos + xoffs, ypos + yOffs , osize, osize
      If drawLabels And saturation = maxRadius Then
         g.forecolor = &cffffff
         g.DrawString Str(tmpHueQ1b), xpos + xoffs, ypos + yOffs
      End If
      
      '     |
      '     |
      ' ----|----
      ' 2b  |   
      '     |
      g.ForeColor = HSV( tmpHueQ2b / 360 , satValue , colorValue, alphaValue )
      g.FillOval  xpos - yoffs, ypos + xOffs , osize, osize
      If drawLabels And saturation = maxRadius Then
         g.forecolor = &cffffff
         g.DrawString Str(tmpHueQ2b), xpos - yoffs, ypos + xOffs
      End If
      
      '   3b|
      '     |
      ' ----|----
      '     |   
      '     |
      g.ForeColor = HSV( tmpHueQ3b / 360 , satValue , colorValue, alphaValue )
      g.FillOval xpos - xoffs, ypos - yOffs , osize, osize
      If drawLabels And saturation = maxRadius Then
         g.forecolor = &cffffff
         g.DrawString Str(tmpHueQ3b), xpos - xoffs, ypos - yOffs
      End If
      
      '     |
      '     |  4b 
      ' ----|----
      '     |   
      '     |
      g.ForeColor = HSV( tmpHueQ4b / 360 , satValue , colorValue, alphaValue )
      g.FillOval xpos + yoffs, ypos - xOffs , osize, osize
      If drawLabels And saturation = maxRadius Then
         g.forecolor = &cffffff
         g.DrawString Str(tmpHueQ4b), xpos + yoffs, ypos - xOffs
      End If
      
    Next
  Next
  
  
End Sub

I just use this one.

Yeah I looked at several before I decided to do this at all
Esp since I need something on “those other platforms” for this same damned IDE
Go figure

grafik
A Color-Picker is a needed thing for a UI Editor

Something Xojo should also have (let’s say it is a MUST have) is a multi-mode Color Picker. I didn’t get why it is only a rudimentary solution. Netbeans Matisse for example had even one like the shown in 2003. There is another functional leak for the Xojo Gang. All we need for Design would be the right way to build a Designer. Like to have Layout Manager and Color-Selection Model and so on. QT has it in it’s visual Designer, Matisse has it, JFormdesigner also. Microsoft left the path of visual GUI builders completely (why ever they have done it). But there is also a big amount of problems building a visual Designer IDE. That’s the foundation for building instead of a visual Designer a declarative UI language and let the users build their UI’s there.
So there is also a chance to use external picker solutions and paste the resulting code. As more people using declarative UI (Xaml for example) there is no visual designer provided for the languages in the future. One example for a different approach ist for example JavaFX. You have a declarative UI in JavafX with their fxml language and on top the Scenebuilder as a drag and drop WYSIWYG gui editor. So JavaFX has both approaches for GUI development. Declarative and graphical editor. I don’t get why Microsoft is not going this way also. Dotnet would be much more interesting for many users when and ih there would be a technology like this behind.

One of Xojo’s goodies is the UI editor which has a good usability. Except missed color picker feature. Something Java for example has. I didn’t get why there is no implementation in their IDE to have that. But this kind of decisions are made from the Master of enginering in austin. So there aalso never will be one.

I don’t get that one. Perhaps I’ve overlooked something. They have one (well a bad one, as they take the rudimentary OS one), but they have one. A bit freaky that you have to use again events to get the value back, but overall it works “somehow”, obviously not in the way Napalm needs it.

Having started Xojo after a couple of months, I can only shake my head. How could I possibly have worked with such a slow IDE for so long …

1 Like

that’s a colorpicker yes. a real bad one for an ide
but sure it is one
sorry for that: OjoH has one but a bad one I have to correct myself

1 Like

no prob, I wasn’t sure either (Xojo is already far away in my brain). “Bad one” is debatable (from their perspective), as it is the one built-in into the OS (and those are usually bad, even on macOS).

The way they implemented it, is definitely nuts. Plus I just noticed that the loading time is quite slow.

so you want me to sell: they use the system one. Okay, they have none by self.
That’s the conclusion. So Swing and FX are in a better shape. Both have their own

they are “native” :wink: (disclaimer: I don’t sell the idea of “native”, especially not for ColorPickers) :slight_smile:

Maybe don’t draw it? Instead insert an already rendered image???

To be VERY clear the IDE is NOT Xojo
It does have “Insert Color” that uses the system color picker
Its a different one from a different green company

yeah its the way the OS one works on macOS :frowning:
Apple moved from a synchronous one to one that sends a notification asynchronously

Live sliders for the value and alpha make that not work :frowning:

I’ll see if other tools can make me a really fast one
Maybe I’ll port this to a C# app

Do you want it circular or square?
In recent versions of Xojo you can do singular direction gradients, which would simplify the drawing. Matching the value might be a bit difficult unless you manually create the gradient yourself.

For circular, you have the angle representing the hue, and the distance from the center representing the saturation.

yeah the linear gradient brush might work if I wanted square

I might go that way JUST to make things quicker as drawing it the way I do now is a bit slow
Its effectively pixel by pixel for the entire radius :stuck_out_tongue:

Its a shame the radial brush is for radius only. You could use some math to make your own angled gradient brush and combine that with a radial brush to simulate the saturation.

Yeah a radial brush would need 360 degrees of colors to go from the centre out to the edges

I had thought maybe 360 degrees of lines drawn using a linear gradient
at least that would mean only drawing 360 lines

hmmm … I suppose I could mess with that to see

1 Like

It’s what I would try. Or you could create 1 path (representing a slice), rotate the context and fill the path 360 times :slight_smile:

OK well finally got my HSV to RGB color conversion right and it draws damned fast in C#

Screen Shot 2023-07-14 at 11.21.10 AM

Now to add the last few remaining bits ( a couple sliders & copying the selected color to the clipboard)

there’s a few pixel cracks and I’ll need to sort out how to fix those

3 Likes