Color wheel: Difference between revisions

From Rosetta Code
Content added Content deleted
(Applesoft BASIC)
Line 8: Line 8:




=={{header|Applesoft BASIC}}==
The lo-resolution GRaphics screen is limited to 16 colors. Ordered dithering is used for the saturation. Pink is mixed with violet and magenta, and aqua is mixed with light blue and green. These lighter colors are randomly mixed with the saturation dither. Note that the four Apple II colors can be seen at the 90 degree marks: orange at 30 degrees, green at 120 degrees, cyan (blue) at 120 degrees, and violet at 300 degrees.
<lang gwbasic> 100 LET R = 3.1415926535 / 180
110 LET YO = 20
120 LET XO = YO
130 LET MS = INT (YO * 7 / 8)
140 LET O$ = "1111111111.1111111110.1111011110.1101110110.1101010110.1010101010.0010101001.0010001001.0000100001.0000000001.0000000000"
150 GR
160 FOR S = 0 TO MS
170 LET D = S / MS
180 LET P$ = MID$ (O$, INT (D * 10) * 11 + 1,11)
190 LET SY = S
200 LET SX = S * 4 / 7
210 LET P = 0
220 FOR I = 0 TO 360
230 LET X = XO + SIN (I * R) * SX
240 LET Y = YO + COS (I * R) * SY
250 LET W = 15
260 IF I > = 30 - 22.4 AND I < 30 + 22.5 THEN COLOR= 9
270 IF I > = 75 - 22.5 AND I < 75 + 22.5 THEN COLOR= 13
280 IF I > = 120 - 22.5 AND I < 120 + 22.5 THEN COLOR= 12:W = 14
290 IF I > = 165 - 22.5 AND I < 165 + 22.5 THEN COLOR= 7:W = 14
300 IF I > = 210 - 22.5 AND I < 210 + 22.5 THEN COLOR= 6
310 IF I > = 255 - 22.5 AND I < 255 + 22.5 THEN COLOR= 2
320 IF I > = 300 - 22.5 AND I < 300 + 22.5 THEN COLOR= 3:W = 11
330 IF I > = 345 - 22.5 OR I < 345 + 22.5 - 360 THEN COLOR= 1:W = 11
340 IF D < .2 THEN W = 15
350 IF RND (1) < D THEN W = 15
360 IF VAL ( MID$ (P$,P + 1,1)) THEN COLOR= W
370 IF SCRN( X,Y) = 0 THEN PLOT X,Y:P = P + 1: IF P > = 9 THEN P = 0
380 NEXT I,S</lang>
=={{header|AppleScript}}==
=={{header|AppleScript}}==



Revision as of 20:00, 24 July 2022

Task
Color wheel
You are encouraged to solve this task according to the task description, using any language you may know.
Task

Write a function to draw a HSV color wheel completely with code.

This is strictly for learning purposes only. It's highly recommended that you use an image in an actual application to actually draw the color wheel   (as procedurally drawing is super slow). This does help you understand how color wheels work and this can easily be used to determine a color value based on a position within a circle.


Applesoft BASIC

The lo-resolution GRaphics screen is limited to 16 colors. Ordered dithering is used for the saturation. Pink is mixed with violet and magenta, and aqua is mixed with light blue and green. These lighter colors are randomly mixed with the saturation dither. Note that the four Apple II colors can be seen at the 90 degree marks: orange at 30 degrees, green at 120 degrees, cyan (blue) at 120 degrees, and violet at 300 degrees. <lang gwbasic> 100 LET R = 3.1415926535 / 180

110  LET YO = 20
120  LET XO = YO
130  LET MS =  INT (YO * 7 / 8)
140  LET O$ = "1111111111.1111111110.1111011110.1101110110.1101010110.1010101010.0010101001.0010001001.0000100001.0000000001.0000000000"
150  GR 
160  FOR S = 0 TO MS
170      LET D = S / MS
180      LET P$ =  MID$ (O$, INT (D * 10) * 11 + 1,11)
190      LET SY = S
200      LET SX = S * 4 / 7
210      LET P = 0
220      FOR I = 0 TO 360
230          LET X = XO +  SIN (I * R) * SX
240          LET Y = YO +  COS (I * R) * SY
250          LET W = 15
260          IF I >  = 30 - 22.4 AND I < 30 + 22.5 THEN  COLOR= 9
270          IF I >  = 75 - 22.5 AND I < 75 + 22.5 THEN  COLOR= 13
280          IF I >  = 120 - 22.5 AND I < 120 + 22.5 THEN  COLOR= 12:W = 14
290          IF I >  = 165 - 22.5 AND I < 165 + 22.5 THEN  COLOR= 7:W = 14
300          IF I >  = 210 - 22.5 AND I < 210 + 22.5 THEN  COLOR= 6
310          IF I >  = 255 - 22.5 AND I < 255 + 22.5 THEN  COLOR= 2
320          IF I >  = 300 - 22.5 AND I < 300 + 22.5 THEN  COLOR= 3:W = 11
330          IF I >  = 345 - 22.5 OR I < 345 + 22.5 - 360 THEN  COLOR= 1:W = 11
340          IF D < .2 THEN W = 15
350          IF  RND (1) < D THEN W = 15
360          IF  VAL ( MID$ (P$,P + 1,1)) THEN  COLOR= W
370          IF  SCRN( X,Y) = 0 THEN  PLOT X,Y:P = P + 1: IF P >  = 9 THEN P = 0
380  NEXT I,S</lang>

AppleScript

<lang AppleScript> choose color default color {0, 0, 0, 0} </lang>

C++

Library: Qt

This program draws an HSV color wheel in a window. <lang cpp>// colorwheelwidget.cpp

  1. include "colorwheelwidget.h"
  2. include <QPainter>
  3. include <QPaintEvent>
  4. include <cmath>

namespace {

QColor hsvToRgb(int h, double s, double v) {

   double hp = h/60.0;
   double c = s * v;
   double x = c * (1 - std::abs(std::fmod(hp, 2) - 1));
   double m = v - c;
   double r = 0, g = 0, b = 0;
   if (hp <= 1) {
       r = c;
       g = x;
   } else if (hp <= 2) {
       r = x;
       g = c;
   } else if (hp <= 3) {
       g = c;
       b = x;
   } else if (hp <= 4) {
       g = x;
       b = c;
   } else if (hp <= 5) {
       r = x;
       b = c;
   } else {
       r = c;
       b = x;
   }
   r += m;
   g += m;
   b += m;
   return QColor(r * 255, g * 255, b * 255);

}

}

ColorWheelWidget::ColorWheelWidget(QWidget *parent)

   : QWidget(parent) {
   setWindowTitle(tr("Color Wheel"));
   resize(400, 400);

}

void ColorWheelWidget::paintEvent(QPaintEvent *event) {

   QPainter painter(this);
   painter.setRenderHint(QPainter::Antialiasing);
   const QColor backgroundColor(0, 0, 0);
   const QColor white(255, 255, 255);
   painter.fillRect(event->rect(), backgroundColor);
   const int margin = 10;
   const double diameter = std::min(width(), height()) - 2*margin;
   QPointF center(width()/2.0, height()/2.0);
   QRectF rect(center.x() - diameter/2.0, center.y() - diameter/2.0,
               diameter, diameter);
   for (int angle = 0; angle < 360; ++angle) {
       QColor color(hsvToRgb(angle, 1.0, 1.0));
       QRadialGradient gradient(center, diameter/2.0);
       gradient.setColorAt(0, white);
       gradient.setColorAt(1, color);
       QBrush brush(gradient);
       QPen pen(brush, 1.0);
       painter.setPen(pen);
       painter.setBrush(brush);
       painter.drawPie(rect, angle * 16, 16);
   }

}</lang>

<lang cpp>// colorwheelwidget.h

  1. ifndef COLORWHEELWIDGET_H
  2. define COLORWHEELWIDGET_H
  1. include <QWidget>

class ColorWheelWidget : public QWidget {

   Q_OBJECT

public:

   ColorWheelWidget(QWidget *parent = nullptr);

protected:

   void paintEvent(QPaintEvent *event) override;

};

  1. endif // COLORWHEELWIDGET_H</lang>

<lang cpp>// main.cpp

  1. include "colorwheelwidget.h"
  2. include <QApplication>

int main(int argc, char *argv[]) {

   QApplication app(argc, argv);
   ColorWheelWidget widget;
   widget.show();
   return app.exec();

}</lang>

Output:

Screenshot: colorwheel.png (offsite PNG image)

Delphi

Library: System.Math
Translation of: Kotlin

<lang Delphi> program Color_wheel;

{$APPTYPE CONSOLE}

uses

 Winapi.Windows,
 System.SysUtils,
 Vcl.Graphics,
 System.Math,
 Vcl.Imaging.pngimage;

const

 TAU = 2 * PI;

function HSBtoColor(hue, sat, bri: Double): TColor; var

 f, h: Double;
 u, p, q, t: Byte;

begin

 u := Trunc(bri * 255 + 0.5);
 if sat = 0 then
   Exit(rgb(u, u, u));
 h := (hue - Floor(hue)) * 6;
 f := h - Floor(h);
 p := Trunc(bri * (1 - sat) * 255 + 0.5);
 q := Trunc(bri * (1 - sat * f) * 255 + 0.5);
 t := Trunc(bri * (1 - sat * (1 - f)) * 255 + 0.5);
 case Trunc(h) of
   0:
     result := rgb(u, t, p);
   1:
     result := rgb(q, u, p);
   2:
     result := rgb(p, u, t);
   3:
     result := rgb(p, q, u);
   4:
     result := rgb(t, p, u);
   5:
     result := rgb(u, p, q);
 else
   result := clwhite;
 end;

end;

function ColorWheel(Width, Height: Integer): TPngImage; var

 Center: TPoint;
 Radius: Integer;
 x, y: Integer;
 Hue, dy, dx, dist, theta: Double;
 Bmp: TBitmap;

begin

 Bmp := TBitmap.Create;
 Bmp.SetSize(Width, Height);
 with Bmp.Canvas do
 begin
   Brush.Color := clWhite;
   FillRect(ClipRect);
   Center := ClipRect.CenterPoint;
   Radius := Center.X;
   if Center.Y < Radius then
     Radius := Center.Y;
   for y := 0 to Height - 1 do
   begin
     dy := y - Center.y;
     for x := 0 to Width - 1 do
     begin
       dx := x - Center.x;
       dist := Sqrt(Sqr(dx) + Sqr(dy));
       if dist <= Radius then
       begin
         theta := ArcTan2(dy, dx);
         Hue := (theta + PI) / TAU;
         Pixels[x, y] := HSBtoColor(Hue, 1, 1);
       end;
     end;
   end;
 end;
 Result := TPngImage.Create;
 Result.Assign(Bmp);
 Bmp.Free;

end;

begin

 with ColorWheel(500, 500) do
 begin
   SaveToFile('ColorWheel.png');
   Free;
 end;

end.</lang>

Output:

Png Image [1].

Fōrmulæ

Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition.

Programs in Fōrmulæ are created/edited online in its website, However they run on execution servers. By default remote servers are used, but they are limited in memory and processing power, since they are intended for demonstration and casual use. A local server can be downloaded and installed, it has no limitations (it runs in your own computer). Because of that, example programs can be fully visualized and edited, but some of them will not run if they require a moderate or heavy computation/memory resources, and no local server is being used.

In this page you can see the program(s) related to this task and their results.


FreeBASIC

<lang freebasic>#include "fbgfx.bi"

Sub HSVtoRGB(h As Single, s As Integer, v As Integer, Byref r As Integer, Byref g As Integer, Byref b As Integer)

   If s = 0 Then
       r = v
       g = v
       b = v
       Return
   End If
   
   h = h Mod 360
   Dim As Single hue = h
   
   Select Case h
   Case 0f To 51.5f
       hue = ((hue         ) * (30f / (51.5f          )))
   Case 51.5f To 122f
       hue = ((hue -  51.5f) * (30f / (122f   -  51.5f))) + 30
   Case 122f To 142.5f
       hue = ((hue -   122f) * (30f / (142.5f -   122f))) + 60
   Case 142.5f To 165.5f
       hue = ((hue - 142.5f) * (30f / (165.5f - 142.5f))) + 90
   Case 165.5f To 192f
       hue = ((hue - 165.5f) * (30f / (192f   - 165.5f))) + 120
   Case 192f To 218.5f
       hue = ((hue -   192f) * (30f / (218.5f -   192f))) + 150
   Case 218.5f To 247f
       hue = ((hue - 218.5f) * (30f / (247f   - 218.5f))) + 180
   Case 247f To 275.5f
       hue = ((hue -   247f) * (30f / (275.5f -   247f))) + 210
   Case 275.5f To 302.5f
       hue = ((hue - 275.5f) * (30f / (302.5f - 275.5f))) + 240
   Case 302.5f To 330f
       hue = ((hue - 302.5f) * (30f / (330f   - 302.5f))) + 270
   Case 330f To 344.5f
       hue = ((hue -   330f) * (30f / (344.5f -   330f))) + 300
   Case 344.5f To 360f
       hue = ((hue - 344.5f) * (30f / (360f   - 344.5f))) + 330
   End Select
   h = hue
   
   h = h Mod 360
   
   Dim As Single h1 = h / 60         
   Dim As Integer i = Int(h1)
   Dim As Single f = h1 - i
   Dim As Integer p = v * (255 - s) / 256
   Dim As Integer q = v * (255 - f * s) / 256
   Dim As Integer t = v * (255 - (1 - f) * s) / 256
   
   Select Case As Const i
   Case 0
       r = v
       g = t
       b = p
       Return
   Case 1
       r = q
       g = v
       b = p
       Return
   Case 2
       r = p
       g = v
       b = t
       Return
   Case 3
       r = p
       g = q
       b = v
       Return
   Case 4
       r = t
       g = p
       b = v
       Return
   Case 5
       r = v
       g = p
       b = q
       Return
   End Select

End Sub

Const pi As Single = 4 * Atn(1) Const radius = 160 Const xres = (radius * 2) + 1, yres = xres

Screenres xres, yres, 32 Windowtitle "Color wheel"

Dim As Integer r,g,b Dim As Single dx, dy, dist, angle

Do

   Screenlock
   Cls
   For x As Integer = 0 To (radius * 2) - 1
       For y As Integer = 0 To (radius * 2) - 1
           dx = x - radius
           dy = radius - y
           dist = Sqr(dx * dx + dy * dy)
           If dist < radius Then
               angle = Atan2(dy, dx) * (180/pi)
               If angle <   0 Then angle += 360
               If angle > 360 Then angle -= 360
               HSVtoRGB(angle, (dist / radius) * 255, 255, r, g, b)
               Pset(x, y), Rgb(r, g, b)
           End If
       Next y
   Next x
   
   Screenunlock

Loop Until Inkey = Chr(27)</lang>


GML

<lang GML> for (var i = 1; i <= 360; i++) {

   for (var j = 0; j < 255; j++) {
       var hue = 255*(i/360);
       var saturation = j;
       var value = 255;
       var c = make_colour_hsv(hue,saturation,value);
       
       //size of circle determined by how far from the center it is
       //if you just draw them too small the circle won't be full. 
       //it will have patches inside it that didn't get filled in with color
       var r = max(1,3*(j/255));
       //Math for built-in GMS functions
       //lengthdir_x(len,dir) = +cos(degtorad(direction))*length;
       //lengthdir_y(len,dir) = -sin(degtorad(direction))*length;
       draw_circle_colour(x+lengthdir_x(m_radius*(j/255),i),y+lengthdir_y(m_radius*(j/255),i),r,c,c,false);
   }

} </lang>

Go

Library: Go Graphics
Translation of: Kotlin

<lang go>package main

import (

   "github.com/fogleman/gg"
   "math"

)

const tau = 2 * math.Pi

func hsb2rgb(hue, sat, bri float64) (r, g, b int) {

   u := int(bri*255 + 0.5)
   if sat == 0 {
       r, g, b = u, u, u
   } else {
       h := (hue - math.Floor(hue)) * 6
       f := h - math.Floor(h)
       p := int(bri*(1-sat)*255 + 0.5)
       q := int(bri*(1-sat*f)*255 + 0.5)
       t := int(bri*(1-sat*(1-f))*255 + 0.5)
       switch int(h) {
       case 0:
           r, g, b = u, t, p
       case 1:
           r, g, b = q, u, p
       case 2:
           r, g, b = p, u, t
       case 3:
           r, g, b = p, q, u
       case 4:
           r, g, b = t, p, u
       case 5:
           r, g, b = u, p, q
       }
   }
   return

}

func colorWheel(dc *gg.Context) {

   width, height := dc.Width(), dc.Height()
   centerX, centerY := width/2, height/2
   radius := centerX
   if centerY < radius {
       radius = centerY
   }
   for y := 0; y < height; y++ {
       dy := float64(y - centerY)
       for x := 0; x < width; x++ {
           dx := float64(x - centerX)
           dist := math.Sqrt(dx*dx + dy*dy)
           if dist <= float64(radius) {
               theta := math.Atan2(dy, dx)
               hue := (theta + math.Pi) / tau
               r, g, b := hsb2rgb(hue, 1, 1)
               dc.SetRGB255(r, g, b)
               dc.SetPixel(x, y)
           }
       }
   }

}

func main() {

   const width, height = 480, 480
   dc := gg.NewContext(width, height)
   dc.SetRGB(1, 1, 1) // set background color to white
   dc.Clear()
   colorWheel(dc)
   dc.SavePNG("color_wheel.png")

}</lang>

Output:
Image is same as Kotlin entry

J

<lang J>rgbc=: {{1-x*0>.1<.(<.4&-)6|m+y%60}} hsv=: 5 rgbc(,"0 1) 3 rgbc(,"0) 1 rgbc degrees=: {{180p_1*{:"1+.^.y}} wheel=: {{((1>:|)*|hsv degrees)j./~y%~i:y}} require'viewmat' 'rgb' viewmat 256#.<.255*wheel 400</lang>

The right argument to wheel determines the radius (in pixels) of the color wheel (with a white pixel in the center), so the diameter of the above color wheel is 801 pixels.

Here's a representation of wheel 5:


           
           
           
           
           
           
           
           
           
           
           
           

Java

This program draws a color wheel in a window. <lang java>import java.awt.*; import javax.swing.*;

public class ColorWheel {

   public static void main(String[] args) {
       SwingUtilities.invokeLater(new Runnable() {
           public void run() {
               ColorWheelFrame frame = new ColorWheelFrame();
               frame.setVisible(true);
           }
       });
   }
   private static class ColorWheelFrame extends JFrame {
       private ColorWheelFrame() {
           super("Color Wheel");
           setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           getContentPane().add(new ColorWheelPanel());
           pack();
       }
   }
   private static class ColorWheelPanel extends JComponent {
       private ColorWheelPanel() {
           setPreferredSize(new Dimension(400, 400));
       }
       public void paint(Graphics g) {
           Graphics2D g2 = (Graphics2D)g;
           int w = getWidth();
           int h = getHeight();
           int margin = 10;
           int radius = (Math.min(w, h) - 2 * margin)/2;
           int cx = w/2;
           int cy = h/2;
           float[] dist = {0.F, 1.0F};
           g2.setColor(Color.BLACK);
           g2.fillRect(0, 0, w, h);
           for (int angle = 0; angle < 360; ++angle) {
               Color color = hsvToRgb(angle, 1.0, 1.0);
               Color[] colors = {Color.WHITE, color};
               RadialGradientPaint paint = new RadialGradientPaint(cx, cy,
                       radius, dist, colors);
               g2.setPaint(paint);
               g2.fillArc(cx - radius, cy - radius, radius*2, radius*2,
                       angle, 1);
           }
       }
   }
   private static Color hsvToRgb(int h, double s, double v) {
       double hp = h/60.0;
       double c = s * v;
       double x = c * (1 - Math.abs(hp % 2.0 - 1));
       double m = v - c;
       double r = 0, g = 0, b = 0;
       if (hp <= 1) {
           r = c;
           g = x;
       } else if (hp <= 2) {
           r = x;
           g = c;
       } else if (hp <= 3) {
           g = c;
           b = x;
       } else if (hp <= 4) {
           g = x;
           b = c;
       } else if (hp <= 5) {
           r = x;
           b = c;
       } else {
           r = c;
           b = x;
       }
       r += m;
       g += m;
       b += m;
       return new Color((int)(r * 255), (int)(g * 255), (int)(b * 255));
   }

}</lang>

Output:

Screenshot: color_wheel_java.png (offsite PNG image)

Julia

<lang julia>using Gtk, Graphics, Colors

const win = GtkWindow("Color Wheel", 450, 450) |> (const can = @GtkCanvas()) set_gtk_property!(can, :expand, true)

@guarded draw(can) do widget

   ctx = getgc(can)
   h = height(can)
   w = width(can)
   center = (x = w / 2, y = h / 2)
   anglestep = 1/w
   for θ in 0:0.1:360
       rgb = RGB(HSV(θ, 1, 1))
       set_source_rgb(ctx, rgb.r, rgb.g, rgb.b)
       line_to(ctx, center...)
       arc(ctx, center.x, center.y, w/2.2, 2π * θ / 360, anglestep)
       line_to(ctx, center...)
       stroke(ctx)
   end

end

show(can) const condition = Condition() endit(w) = notify(condition) signal_connect(endit, win, :destroy) wait(condition) </lang>

Kotlin

We reuse the class in the Bitmap task for this and add a member function to draw the color wheel. To give a more 'wheel-like' image, a constant 'saturation' of 1.0 has been used rather than one which varies in line with distance from the center. <lang scala>// Version 1.2.41

import java.awt.Color import java.awt.Graphics import java.awt.image.BufferedImage import java.io.File import javax.imageio.ImageIO import kotlin.math.*

class BasicBitmapStorage(width: Int, height: Int) {

   val image = BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR)
   fun fill(c: Color) {
       val g = image.graphics
       g.color = c
       g.fillRect(0, 0, image.width, image.height)
   }
   fun setPixel(x: Int, y: Int, c: Color) = image.setRGB(x, y, c.getRGB())
   fun getPixel(x: Int, y: Int) = Color(image.getRGB(x, y))
   fun colorWheel() {
       val centerX = image.width / 2
       val centerY = image.height / 2
       val radius = minOf(centerX, centerY)
       for (y in 0 until image.height) {
           val dy = (y - centerY).toDouble()
           for (x in 0 until image.width) {
               val dx = (x - centerX).toDouble()
               val dist = sqrt(dx * dx + dy * dy)
               if (dist <= radius) {
                   val theta = atan2(dy, dx)
                   val hue = (theta + PI) / (2.0 * PI)
                   val rgb = Color.HSBtoRGB(hue.toFloat(), 1.0f, 1.0f)
                   setPixel(x, y, Color(rgb))
               }
           }
       }
   }

}

fun main(args: Array<String>) {

   val bbs = BasicBitmapStorage(480, 480)
   with (bbs) {
       fill(Color.white)
       colorWheel()
       val cwFile = File("Color_wheel.png")
       ImageIO.write(image, "png", cwFile)
   }

} </lang>

Output:
Looks like mirror image of Smart BASIC entry 


Lua

Library: LÖVE

<lang Lua> local function hsv_to_rgb (h, s, v) -- values in ranges: [0, 360], [0, 1], [0, 1] local r = math.min (math.max (3*math.abs (((h )/180)%2-1)-1, 0), 1) local g = math.min (math.max (3*math.abs (((h -120)/180)%2-1)-1, 0), 1) local b = math.min (math.max (3*math.abs (((h +120)/180)%2-1)-1, 0), 1) local k1 = v*(1-s) local k2 = v - k1 return k1+k2*r, k1+k2*g, k1+k2*b -- values in ranges: [0, 1], [0, 1], [0, 1] end

function love.load() local w, h, r = 256, 256, 128-0.5 local cx, cy = w/2, h/2 canvas = love.graphics.newCanvas () love.graphics.setCanvas(canvas) for x = 0, w do for y = 0, h do local dx, dy = x-cx, y-cy if dx*dx + dy*dy <= r*r then local h = math.deg(math.atan2(dy, dx)) local s = (dx*dx + dy*dy)^0.5/r local v = 1 love.graphics.setColor (hsv_to_rgb (h, s, v)) love.graphics.points (x, y) end end end love.graphics.setCanvas() end

function love.draw() love.graphics.setColor (1,1,1) love.graphics.draw (canvas) end </lang>

M2000 Interpreter

<lang M2000 Interpreter> Module Check {

     \\ we use an internal object for Math functions (here for Atan2)
     Declare Math Math
     Const tau=2*Pi, Center=2
     \\ change console size,  and center it ( using ;) to current monitor      
     Window 12, 800*twipsX,600*twipsY;
     \\ actual size maybe less (so can fit text exactly)
     Double  ' Double height characters
     Report Center, "Color wheel"
     Normal  ' restore to normal
     Atan2=Lambda Math (a, b) ->{
           Method Math, "Atan2", a, b As ret
           =ret
     }
     \\ brightness=1 for this program
     hsb2rgb=Lambda (hue, sat) ->{
           If sat == 0 Then {
               = 255, 255, 255
          } Else {
                 h=frac(hue+1)*6
                 f = frac(h)  
                 p = Int((1-sat)*255 + 0.5)
                 q = Int((1-sat*f)*255 + 0.5)
                 t = Int((1-sat*(1-f))*255 + 0.5)
                 Select Case Int(h)
                 Case 1
                     = q, 255, p
                 Case 2
                     = p, 255, t
                 Case 3
                    = p, q, 255
                 Case 4
                     = t, p, 255
                 Case 5
                     = 255, p, q
                 Else Case
                     = 255, t, p
                 End Select
         }
     }
     Let OffsetX=X.twips/2-128*TwipsX, OffsetY=Y.twips/2-128*TwipsY
     \\ a pixel has a size of TwipsX x TwipsY
     OffsetX=(OffsetX div TwipsX)*TwipsX
     OffsetY=(OffsetY div TwipsY)*TwipsY
     \\ We set hsb2rgb, OffsetX, OffsetY as closures to PrintPixel
     \\ We send to stack the R G B values using Stack ! array
     \\ hsb2rgb() return an array of values
     \\ we pop these values using Number
     PrintPixel = Lambda  hsb2rgb, OffsetX, OffsetY (x,y, theta, sat)  -> {
           Stack ! hsb2rgb(theta,sat)  
           PSet Color(number, number, number), x*TwipsX+offsetX, y*TwipsY+offsetY
     }
     \\ set Atan2, tau as closures to HueCircle
     \\ we can rotate/flip the wheel by changing signs in Atan2() and
     \\ by changing order of arguments (dx,dy) or (dy,dx). 8 combinations
     HueCircle= Lambda Atan2, tau (PrintPixel) -> {
           Let  c_width=256, c_height=256
           Let  cx=c_width/2, cy=c_height/2
           Let  radius=If(cx<=cy->cx, cy)
           c_width--
           c_height--
           dy=-cy
           For y=0 To c_height {
                 dy++ : dy2=dy*dy : dx=-cx
                 For x=0 To c_width {
                       dx++ : dist=Sqrt(dx^2+dy2)
                       If dist>radius Then continue
                       Call PrintPixel(x,y, Atan2(dx, -dy)/tau, dist/radius)
                 }
           }
     }
     Call HueCircle(PrintPixel)
     Scr$=""  ' we use this string  to load an image
     Move 0,0
     \\ scale.x, scale.y are twips height and width, of current layer
     Copy scale.x, scale.y to Scr$
     Clipboard Scr$  ' save window to clipboard

} Check </lang>

Output:

see this image

Mathematica/Wolfram Language

<lang Mathematica>r = 100; Image[Table[

 If[x^2 + y^2 <= r^2,
  angle = Mod[ArcTan[N@x, y]/(2 Pi), 1];
  List @@ RGBColor[Hue[angle, Sqrt[x^2 + y^2]/N[r], 1.0]]
  ,
  {1, 1, 1}
  ], {x, -r, r}, {y, -r, r}]
]</lang>
Output:

Outputs an image.

Nim

Translation of: Rust
Library: imageman

As Rust code does, we store the color wheel in a PNG image.

<lang Nim>import math

import imageman

  1. ---------------------------------------------------------------------------------------------------

func hsvToRgb(h, s, v: float): ColorRGBU =

 ## Convert HSV values to RGB values.
 let hp = h / 60
 let c = s * v
 let x = c * (1 - abs(hp mod 2 - 1))
 let m = v - c
 var r, g, b = 0.0
 if hp <= 1:
   r = c
   g = x
 elif hp <= 2:
   r = x
   g = c
 elif hp <= 3:
   g = c
   b = x
 elif hp <= 4:
   g = x
   b= c
 elif hp <= 5:
   r = x
   b = c
 else:
   r = c
   b = x
 r += m
 g += m
 b += m
 result = ColorRGBU [byte(r * 255), byte(g * 255), byte(b * 255)]
  1. ---------------------------------------------------------------------------------------------------

func buildColorWheel(image: var Image) =

 ## Build a color wheel into the image.
 const Margin = 10
 let diameter = min(image.w, image.h) - 2 * Margin
 let xOffset = (image.w - diameter) div 2
 let yOffset = (image.h - diameter) div 2
 let radius = diameter / 2
 for x in 0..diameter:
   let rx = x.toFloat - radius
   for y in 0..diameter:
     let ry = y.toFloat - radius
     let r = hypot(rx, ry) / radius
     if r > 1: continue
     let a = 180 + arctan2(ry, -rx).radToDeg()
     image[x + xOffset, y + yOffset] = hsvToRgb(a, r, 1)
  1. ———————————————————————————————————————————————————————————————————————————————————————————————————

const

 Side = 400
 Output = "color_wheel.png"

var image = initImage[ColorRGBU](Side, Side) image.buildColorWheel()

image.savePNG(Output, compression = 9)</lang>

Perl

Translation of: Sidef

<lang perl>use Imager; use Math::Complex qw(cplx i pi);

my ($width, $height) = (300, 300); my $center = cplx($width/2, $height/2);

my $img = Imager->new(xsize => $width,

                     ysize => $height);

foreach my $y (0 .. $height - 1) {

   foreach my $x (0 .. $width - 1) {
       my $vec = $center - $x - $y * i;
       my $mag = 2 * abs($vec) / $width;
       my $dir = (pi + atan2($vec->Re, $vec->Im)) / (2 * pi);
       $img->setpixel(x => $x, y => $y,
           color => {hsv => [360 * $dir, $mag, $mag < 1 ? 1 : 0]});
   }

}

$img->write(file => 'color_wheel.png');</lang>

Phix

Library: Phix/pGUI
Library: Phix/online

You can run this online here.

--
-- demo\rosetta\Colour_wheel.exw
-- =============================
--
--  Note: Made non-resizeable since maximising this is far too slow.
--
with javascript_semantics
include pGUI.e

constant title = "Colour wheel"
Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/)
    integer {w, h} = IupGetIntInt(canvas, "DRAWSIZE")
    cdCanvasActivate(cddbuffer)
    integer radius = floor(min(w,h)/2)
    integer cx = floor(w/2),
            cy = floor(h/2)

    for x=1 to w do
        for y=1 to h do
            integer rx = x - cx,
                    ry = y - cy
            atom s = sqrt(rx*rx+ry*ry) / radius
            if s <= 1.0 then
                atom hue = ((atan2(ry, rx) / PI) + 1.0) / 2.0
                cdCanvasPixel(cddbuffer, x, h-y, hsv_to_rgb(hue, s, 1)) 
            end if 
        end for
    end for
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

function map_cb(Ihandle ih)
    cdcanvas = cdCreateCanvas(CD_IUP, ih)
    cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
    cdCanvasSetBackground(cddbuffer, CD_WHITE)
    cdCanvasSetForeground(cddbuffer, CD_MAGENTA)
    return IUP_DEFAULT
end function

procedure main()
    IupOpen()
    canvas = IupCanvas(NULL)
    IupSetAttribute(canvas, "RASTERSIZE", "300x300")
    IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
    dlg = IupDialog(canvas,`TITLE="%s",RESIZE=NO`,{title})
    IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))
    IupShowXY(dlg,IUP_CENTER,IUP_CENTER)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()

Processing

<lang java>size(300, 300); background(0); float radius = min(width, height) / 2.0; float cx = width / 2; float cy = width / 2; for (int x = 0; x < width; x++) {

 for (int y = 0; y < width; y++) {
   float rx = x - cx;
   float ry = y - cy;
   float s = sqrt(sq(rx) + sq(ry)) / radius;
   if (s <= 1.0) {
     float h = ((atan2(ry, rx) / PI) + 1.0) / 2.0;
     colorMode(HSB);
     color c = color(int(h * 255), int(s * 255), 255);
     set(x, y, c);
   }
 }

}</lang>

Processing Python mode

<lang python>size(300, 300) background(0) radius = min(width, height) / 2.0 cx, cy = width / 2, width / 2 for x in range(width):

       for y in range(height):
           rx = x - cx
           ry = y - cy
           s = sqrt(rx ** 2 + ry ** 2) / radius
           if s <= 1.0:
               h = ((atan2(ry, rx) / PI) + 1.0) / 2.0
               colorMode(HSB)
               c = color(int(h * 255), int(s * 255), 255)
               set(x, y, c) # note set() used as Processing set() not as Python set()</lang>

Python

<lang python>from PIL import Image import colorsys import math

if __name__ == "__main__":

   im = Image.new("RGB", (300,300))
   radius = min(im.size)/2.0
   cx, cy = im.size[0]/2, im.size[1]/2
   pix = im.load()

   for x in range(im.width):
       for y in range(im.height):
           rx = x - cx
           ry = y - cy
           s = (rx ** 2.0 + ry ** 2.0) ** 0.5 / radius
           if s <= 1.0:
               h = ((math.atan2(ry, rx) / math.pi) + 1.0) / 2.0
               rgb = colorsys.hsv_to_rgb(h, s, 1.0)
               pix[x,y] = tuple([int(round(c*255.0)) for c in rgb])
   im.show()</lang>

Racket

With the colors package

<lang racket>#lang racket

(require racket/draw

        colors)

(define DIM 500) (define target (make-bitmap DIM DIM)) (define dc (new bitmap-dc% [bitmap target])) (define radius 200) (define center (/ DIM 2))

(define (atan2 y x) (if (= 0 y x) 0 (atan y x)))

(for* ([x (in-range DIM)]

      [y (in-range DIM)]
      [rx (in-value (- x center))]
      [ry (in-value (- y center))]
      [s (in-value (/ (sqrt (+ (sqr rx) (sqr ry))) radius))]
      #:when (<= s 1))
 (define h (* 0.5 (+ 1 (/ (atan2 ry rx) pi))))
 (send dc set-pen (hsv->color (hsv (if (= 1 h) 0 h) s 1)) 1 'solid)
 (send dc draw-point x y))

target</lang>

Raku

(formerly Perl 6)

Works with: Rakudo version 2016.08

<lang perl6>use Image::PNG::Portable;

my ($w, $h) = 300, 300;

my $out = Image::PNG::Portable.new: :width($w), :height($h);

my $center = $w/2 + $h/2*i;

color-wheel($out);

$out.write: 'Color-wheel-perl6.png';

sub color-wheel ( $png ) {

   ^$w .race.map: -> $x {
       for ^$h -> $y {
           my $vector    = $center - $x - $y*i;
           my $magnitude = $vector.abs * 2 / $w;
           my $direction = ( π + atan2( |$vector.reals ) ) / τ;
           $png.set: $x, $y, |hsv2rgb( $direction, $magnitude, $magnitude < 1 );
       }
   }

}

sub hsv2rgb ( $h, $s, $v ){

   my $c = $v * $s;
   my $x = $c * (1 - abs( (($h*6) % 2) - 1 ) );
   my $m = $v - $c;
   (do given $h {
       when   0..^1/6 { $c, $x, 0 }
       when 1/6..^1/3 { $x, $c, 0 }
       when 1/3..^1/2 { 0, $c, $x }
       when 1/2..^2/3 { 0, $x, $c }
       when 2/3..^5/6 { $x, 0, $c }
       when 5/6..1    { $c, 0, $x }
   } ).map: ((*+$m) * 255).Int

}</lang>

Until local image uploading is re-enabled, see Color-wheel-perl6.png

Ring

Color wheel - image

<lang ring>

  1. ===================================================================#
  2. Sample: Color Wheel
  3. Author: Gal Zsolt, Bert Mariani, Ilir Liburn & Mahmoud Fayed
  4. ===================================================================#

load "guilib.ring"

xWidth = 400 yHeight = 400

MyApp = new qapp {

  win1 = new qwidget() 
  {  setwindowtitle("ColorWheel-FastDraw")
     setgeometry(500,150,xWidth,yHeight)
     
     Canvas = new qlabel(win1)
     {  ### daVinci paints the MonaLisa on the Canvas
        MonaLisa  = new qPixMap2( xWidth, yHeight)
            color = new qcolor(){ setrgb(255,255,255,0) }
             pen  = new qpen()  { setwidth(1) }  
        MonaLisa.fill(color)
        daVinci = new qpainter()
        {  begin(MonaLisa)
           #endpaint()           ### This will Stop the Painting. For Animation comment it out
        }
        
        setPixMap(MonaLisa)
     }
     
     show()
  }
        
  ColorWheel()
  exec()

}

//=====================

Func colorWheel

  #=====================================================================#
  ? "Start Processing..."
  t1 = clock()
  ? "Clock : " + t1
  #=====================================================================#
  aList = []
  pi       = 3.14159265359
  diameter = pi * 2
  radius   = yHeight / 2
  v        = 1                    // value/brightness  1 to 100  1=bright 0=dark
  for i = 1 to xWidth
     iradius = i - radius
           p = pow( iradius, 2)
     for j = 1 to yHeight
         h = (atan2( iradius, j-radius ) + pi ) / diameter   // hue/color  1 to 360 
         s =   sqrt( p + pow( j-radius, 2)) / radius         // saturation/intensity 1 to 100
       
        if s <= 1 and h <= 1 
           aList + [i,j,h,s,v,1]
        ok
        
     next 
  next  
  #=====================================================================#
  ? "Start drawing..." 
  t2 = clock()
  ? "Clock : " + t2
  #=====================================================================#
  daVinci.drawHSVFList(aList)
  Canvas.setPixMap(MonaLisa)
  #=====================================================================#
  ? "Done..."
  t3 = clock()
  ? "Clock : " + t3
  #=====================================================================#
  ? "Processing Time: " + ( (t2-t1)/ClocksPerSecond() ) + " seconds "
  ? "Drawing Time: " + ( (t3-t2)/ClocksPerSecond() ) + " seconds "
  ? "Total Time: " + ( (t3-t1)/ClocksPerSecond() ) + " seconds "
  #=====================================================================#
  
return  
  

//================== </lang>

Ruby

Library: RubyGems
Library: JRubyArt

<lang ruby> def settings

 size(300, 300)

end

def setup

 sketch_title 'Color Wheel'
 background(0)
 radius = width / 2.0
 center = width / 2
 grid(width, height) do |x, y|
   rx = x - center
   ry = y - center
   sat = Math.hypot(rx, ry) / radius
   if sat <= 1.0
     hue = ((Math.atan2(ry, rx) / PI) + 1) / 2.0
     color_mode(HSB)
     col = color((hue * 255).to_i, (sat * 255).to_i, 255)
     set(x, y, col)
   end
 end

end </lang>

Run BASIC

<lang Runbasic>' ----------------------------------- ' color wheel ' ----------------------------------- global pi pi = 22 / 7 steps = 1

graphic #g, 525, 525


for x =0 to 525 step steps for y =0 to 525 step steps angle = atan2(y - 250, x - 250) * 360 / 2 / pi ' full degrees.... sector = int(angle / 60) ' 60 degree sectors (0 to 5) slope = (angle mod 60) /60 * 255 ' 1 degree sectors.

if sector = 0 then col$ = "255 "; str$( int( slope)); " 0" if sector = 1 then col$ = str$(int(256 - slope)); " 255 0" if sector = 2 then col$ = "0 255 "; str$( int( slope)) if sector = 3 then col$ = "0 "; str$( int( 256 -slope)); " 255" if sector = 4 then col$ = str$(int(slope)); " 0 255" if sector = 5 then col$ = "255 0 "; str$( int( 256 -slope))

red = val( word$( col$, 1)) grn = val( word$( col$, 2)) blu = val( word$( col$, 3)) p = ((x -270)^2 +(y -270)^2)^0.5 / 250 r = min(255,p * red) g = min(255,p * grn) b = min(255,p * blu) if p > 1 then #g "color white" else #g color(r,g,b) #g "set "; x; " "; y next y next x render #g end

function atan2(y,x) if (x = 0) and (y <> 0) then r$ = "Y" if y > 0 then atan2 = pi /2 if y < 0 then atan2 = 3 * pi /2 end if

if y = 0 and (x <> 0) then r$ = "Y" if x > 0 then atan2 = 0 if x < 0 then atan2 = pi end if

If r$ <> "Y" then if x = 0 and y = 0 then atan2 = 0 else baseAngle = atn(abs(y) / abs(x)) if x > 0 then if y > 0 then atan2 = baseAngle If y < 0 then atan2 = 2 * pi - baseAngle end if if x < 0 then If y > 0 then atan2 = pi - baseAngle If y < 0 then atan2 = pi + baseAngle end if end if end if end function</lang>

Rust

Output is a file in PNG format. <lang rust>// [dependencies] // image = "0.23"

use image::error::ImageResult; use image::{Rgb, RgbImage};

fn hsv_to_rgb(h: f64, s: f64, v: f64) -> Rgb<u8> {

   let hp = h / 60.0;
   let c = s * v;
   let x = c * (1.0 - (hp % 2.0 - 1.0).abs());
   let m = v - c;
   let mut r = 0.0;
   let mut g = 0.0;
   let mut b = 0.0;
   if hp <= 1.0 {
       r = c;
       g = x;
   } else if hp <= 2.0 {
       r = x;
       g = c;
   } else if hp <= 3.0 {
       g = c;
       b = x;
   } else if hp <= 4.0 {
       g = x;
       b = c;
   } else if hp <= 5.0 {
       r = x;
       b = c;
   } else {
       r = c;
       b = x;
   }
   r += m;
   g += m;
   b += m;
   Rgb([(r * 255.0) as u8, (g * 255.0) as u8, (b * 255.0) as u8])

}

fn write_color_wheel(filename: &str, width: u32, height: u32) -> ImageResult<()> {

   let mut image = RgbImage::new(width, height);
   let margin = 10;
   let diameter = std::cmp::min(width, height) - 2 * margin;
   let xoffset = (width - diameter) / 2;
   let yoffset = (height - diameter) / 2;
   let radius = diameter as f64 / 2.0;
   for x in 0..=diameter {
       let rx = x as f64 - radius;
       for y in 0..=diameter {
           let ry = y as f64 - radius;
           let r = ry.hypot(rx) / radius;
           if r > 1.0 {
               continue;
           }
           let a = 180.0 + ry.atan2(-rx).to_degrees();
           image.put_pixel(x + xoffset, y + yoffset, hsv_to_rgb(a, r, 1.0));
       }
   }
   image.save(filename)

}

fn main() {

   match write_color_wheel("color_wheel.png", 400, 400) {
       Ok(()) => {}
       Err(error) => eprintln!("{}", error),
   }

}</lang>

Output:

See: color_wheel.png (offsite PNG image)

Sidef

Translation of: Raku

<lang ruby>require('Imager')

var (width, height) = (300, 300) var center = Complex(width/2 , height/2)

var img = %O<Imager>.new(xsize => width, ysize => height)

for y=(^height), x=(^width) {

   var vector    = (center - x - y.i)
   var magnitude = (vector.abs * 2 / width)
   var direction = ((Num.pi + atan2(vector.real, vector.imag)) / Num.tau)
   img.setpixel(x => x, y => y,
       color => Hash(hsv => [360*direction, magnitude, magnitude < 1 ? 1 : 0])
   )

}

img.write(file => 'color_wheel.png')</lang> Output image: Color wheel

Smart BASIC

<lang smart basic>' Runs on iOS GET SCREEN SIZE sw,sh xmax=0.45*3/7*(sw+sh) x0=sw/2!y0=sh/2 twopi=2*3.1415926 GRAPHICS GRAPHICS CLEAR DIM triX(1000), triY(1000) triX(0)=x0 ! triY(0)=y0 steps=INT(1^2*360)+1 dAngle=twopi/steps dAngle2=dAngle/2 REFRESH OFF FOR i=0 TO steps-1

 pal(i/steps+TintOffset)
 ANGLE=i*dAngle
 FILL COLOR pal.r,pal.g,pal.b
 DRAW COLOR pal.r,pal.g,pal.b
 x=x0+(xmax-radius)*COS(ANGLE)
 y=y0-(xmax-radius)*SIN(ANGLE)
 k=0
 FOR j=-dAngle2 TO dAngle2 STEP 0.02
   k+=1
   triX(k)=x0+xmax*COS(ANGLE+j)
   triY(k)=y0-xmax*SIN(ANGLE+j)
 NEXT j
 k+=1
 triX(k)=x0+xmax*COS(ANGLE+dAngle2)
 triY(k)=y0-xmax*SIN(ANGLE+dAngle2)
 DRAW POLY triX,triY COUNT k+1
 FILL POLY triX,triY COUNT k+1

NEXT i REFRESH ON END

DEF pal(tint) tint=tint*360 h=(tint%360)/60 ! f=FRACT(h) ! z=1-f ! ic=FLOOR(h)+1 ON ic GOTO s1,s2,s3,s4,s5,s6

 s1: r=1 ! g=f ! b=0 ! GOTO done
 s2: r=z ! g=1 ! b=0 ! GOTO done
 s3: r=0 ! g=1 ! b=f ! GOTO done
 s4: r=0 ! g=z ! b=1 ! GOTO done
 s5: r=f ! g=0 ! b=1 ! GOTO done
 s6: r=1 ! g=0 ! b=z ! done:

END DEF</lang> View the output on Dropbox https://www.dropbox.com/s/g3l5rbywo34bnp6/IMG_4600.PNG?dl=0 This file is no longer there!!! 10 Sep 2021

VBScript

Building a BMP file and opening it with the default viewer. It takes 5 seconds in my 5 years old notebook. Run with Cscript if you don want to be clicking at annoying message boxes. <lang vb> option explicit



Class ImgClass

 Private ImgL,ImgH,ImgDepth,bkclr
 private xmini,xmaxi,ymini,ymaxi
 dim ImgArray()  'rgb in 24 bit mode, indexes to palette in 8 bits
 private filename   
 private Palette
 

public property get xmin():xmin=xmini:end property public property get ymin():ymin=ymini:end property public property get xmax():xmax=xmaxi:end property public property get ymax():ymax=ymaxi:end property


 public sub set0 (x0,y0) 'sets the new origin (default tlc)
   if x0<0 or x0>=imgl or y0<0 or y0>imgh then err.raise 9 
   xmini=-x0
   ymini=-y0
   xmaxi=xmini+imgl-1
   ymaxi=ymini+imgh-1    
 end sub
 
 'constructor
 Public Default Function Init(name,w,h,dep,bkg,pal)
    dim i,j
    ImgL=w
    ImgH=h
    set0 0,0  'tlc
    redim imgArray(ImgL-1,ImgH-1)
    bkclr=bkg
    if bkg<>0 then 
      for i=0 to ImgL-1 
        for j=0 to ImgH-1 
           imgarray(i,j)=bkg
        next
      next  
   end if   
    filename=name
    ImgDepth =dep
    'load user palette if provided  
    if imgdepth=8 then 
      if isarray(pal) then
       if ubound(pal)=255 then
           palette=pal
       else
          mypalette          
       end if
     else
       mypalette
     end if 
    end if       
    set init=me
 end function


 'class termination writes it to a BMP file and displays it 
 'if an error happens VBS terminates the class before exiting so the BMP is displayed the same
 Private Sub Class_Terminate
 
   if err<>0 then wscript.echo "Error " & err.number
   wscript.echo "copying image to bmp file"
   savebmp
   wscript.echo "opening " & filename & "with uour default viewer"
   CreateObject("Shell.Application").ShellExecute filename
 End Sub
 'writes a 32bit integr value as binary to a string
 Sub WriteLong(ByRef Fic,ByVal k)
   Dim x
   For x=1 To 4
       Fic.Write chr(k and &hFF)
       k=k\256
   Next
 End Sub
 Public Sub SaveBMP
   'Save the picture to a bmp file
   Const ForReading = 1 
   Const ForWriting = 2
   Const ForAppending = 8
   Dim Fic
   Dim i,r,g,b
   Dim k,x,y,padding
   dim bpp:bpp=imgdepth\8
    
   Set Fic = WScript.CreateObject("scripting.Filesystemobject").OpenTextFile(filename, ForWriting, True)
   if fic is nothing then wscript.echo "error creating file" & filename :wscript.quit
   
   dim bms:bms=ImgH* 4*(((ImgL*bpp)+3)\4)  'bitmap size including padding
   dim pals:if (imgdepth=8) then pals=(ubound(Palette)+1)*4 else pals=0
   
   'FileHeader
   Fic.Write "BM" 'Type
   WriteLong Fic, 14+40+ pals + bms    'Size of entire file in bytes
   fic.write string(4,0)
   WriteLong Fic,54+pals   '2 words: offset of BITMAPFILEHEADER (access to the beginning of the bitmap) 54=14+40 (fileheader+infoheader)
   'InfoHeader
   WriteLong Fic,40    'Size of Info Header(40 bytes)
   WriteLong Fic,ImgL
   WriteLong Fic,ImgH
   Fic.Write chr(1) & chr(0) 'Planes : 1
   Fic.Write chr(ImgDepth) & chr(0) 'Bitcount : 1,4,8,16,24,32 = bitsperpixel
   fic.write string(8,0)&chr(&Hec)&chr(4)& string(2,0)&chr(&Hec)&chr(4)& string(2,0)& string(8,0) 
   
   'palette
   If (imgdepth=8) Then
     For i=0 to ubound(palette)
       writelong fic ,Palette(i)
     Next
   End If
   
   'write bitmap
   dim xx:xx=(ImgL*bpp) mod 4
   if xx<>0 then padding=Space(4-xx) else padding=""
   
   Select Case ImgDepth
   
   Case 24
   'wscript.echo imgdepth
     For y=ImgH-1 to 0 step-1  'Origin of bitmap: bottom left
       For x=0 To ImgL-1
        'writelong fic, Pixel(x,y) 
         k=ImgArray(x,y)    
         Fic.Write chr(k and &hff)
         k=k\256
         Fic.Write chr(k and &hff)
         k=k\256
         Fic.Write chr(k and &hff)
       Next
       Fic.Write padding
     Next
   Case 8
     For y=ImgH-1 to 0 step-1
       For x=0 To ImgL-1
           Fic.Write chr(ImgArray(x,y) and &hff)
       Next
       Fic.Write padding
     Next
   Case Else
       WScript.Echo "ColorDepth unknown : " & ImgDepth & " bits"
   End Select
   Fic.Close
   Set Fic=Nothing
 End Sub

end class



function hsv2rgb( Hue, Sat, Value) 'hue 0-360 0-ro 120-ver 240-az ,sat 0-100,value 0-100

 dim Angle, Radius,Ur,Vr,Wr,Rdim
 dim r,g,b, rgb
 Angle = (Hue-150) *0.01745329251994329576923690768489
 Ur = Value * 2.55
 Radius = Ur * tan(Sat *0.01183199)
 Vr = Radius * cos(Angle) *0.70710678  'sqrt(1/2)
 Wr = Radius * sin(Angle) *0.40824829  'sqrt(1/6)
 r = (Ur - Vr - Wr)  
 g = (Ur + Vr - Wr) 
 b = (Ur + Wr + Wr) 
 
 'clamp values 
if r >255 then 
  Rdim = (Ur - 255) / (Vr + Wr)
  r = 255
  g = Ur + (Vr - Wr) * Rdim
  b = Ur + 2 * Wr * Rdim 
elseif r < 0 then
  Rdim = Ur / (Vr + Wr)
  r = 0
  g = Ur + (Vr - Wr) * Rdim
  b = Ur + 2 * Wr * Rdim 
end if 
if g >255 then 
  Rdim = (255 - Ur) / (Vr - Wr)
  r = Ur - (Vr + Wr) * Rdim
  g = 255
  b = Ur + 2 * Wr * Rdim
elseif g<0 then   
  Rdim = -Ur / (Vr - Wr)
  r = Ur - (Vr + Wr) * Rdim
  g = 0
  b = Ur + 2 * Wr * Rdim   
end if 
if b>255 then
  Rdim = (255 - Ur) / (Wr + Wr)
  r = Ur - (Vr + Wr) * Rdim
  g = Ur + (Vr - Wr) * Rdim
  b = 255
elseif b<0 then
  Rdim = -Ur / (Wr + Wr)
  r = Ur - (Vr + Wr) * Rdim
  g = Ur + (Vr - Wr) * Rdim
  b = 0
end if
hsv2rgb= (b and &hff)+256*((g and &hff)+256*(r and &hff))

end function

function ang(col,row)

   'if col =0 then  if row>0 then ang=0 else ang=180:exit function 
   if col =0 then  
     if row<0 then ang=90 else ang=270 end if
   else  
  if col>0 then
     ang=atn(-row/col)*57.2957795130
  else
    ang=(atn(row/-col)*57.2957795130)+180
 end if
 end if
  ang=(ang+360) mod 360  
 

end function


Dim X,row,col,fn,tt,hr,sat,row2 const h=160 const w=160 const rad=159 const r2=25500 tt=timer fn=CreateObject("Scripting.FileSystemObject").GetSpecialFolder(2)& "\test.bmp" Set X = (New ImgClass)(fn,w*2,h*2,24,0,0)

x.set0 w,h 'wscript.echo x.xmax, x.xmin

for row=x.xmin+1 to x.xmax

  row2=row*row
  hr=int(sqr(r2-row2))
  for col=-hr to hr
    sat=100-sqr(row2+col*col)/rad *50
   ' wscript.echo c,r
    x.imgArray(col+160,row+160)=hsv2rgb(ang(row,col)+90,100,sat)
   next
   'script.echo row
 next  

Set X = Nothing wscript.echo "Time " & (timer-tt) & " ms"

</lang>

Wren

Library: DOME

<lang ecmascript>import "graphics" for Canvas, Color import "dome" for Window import "random" for Random

class Game {

   static init() {
       Window.title = "Color Wheel"
       __width = 640
       __height = 640
       Window.resize(__width, __height)
       Canvas.resize(__width, __height)
       colorWheel()
   }
   static colorWheel() {
       var cx = (__width/2).floor
       var cy = (__height/2).floor
       var r = (cx < cy) ? cx : cy
       for (y in 0...__height) {
           var dy = y - cy
           for (x in 0...__width) {
               var dx = x - cx
               var dist = (dx*dx + dy*dy).sqrt
               if (dist <= r) {
                   var theta = dy.atan(dx)
                   var h = (theta + Num.pi) / Num.pi * 180
                   var col = Color.hsv(h, dist/r, 1)
                   Canvas.pset(x, y, col)
               }
           }
       }
   }
   static update() {}
   static draw(alpha) {}

}</lang>

XPL0

Algorithm is from "Computer Graphics ..." by Foley et al. The output is the same as Zkl. <lang XPL0>def Radius = 480/2; real Hue, Sat, Dist, I, F, P, Q, T; real XX, YY, RR, GG, BB; int X, Y, R, G, B; def Pi = 3.141592654; def V = 1.; \Value [SetVid($112); \640x480x24 graphics for Y:= -Radius to Radius do

   for X:= -Radius to Radius do
       [XX:= float(X);
        YY:= float(Y);
        Dist:= sqrt(XX*XX + YY*YY);
        if Dist <= float(Radius) then
               [Sat:= Dist/float(Radius);      \0 >= Sat <= 1
               Hue:= ATan2(YY, XX);            \-Pi >= Hue <= Pi
               if Hue < 0. then Hue:= Hue + 2.*Pi;
               Hue:= Hue * 180./Pi;            \radians to degrees
               Hue:= Hue / 60.;                \0 >= Hue < 6
               I:= Floor(Hue);                 \integer part of Hue
               F:= Hue - I;                    \fractional part of Hue
               P:= 1. - Sat;
               Q:= 1. - Sat*F;
               T:= 1. - Sat*(1.-F);
               case fix(I) of
                 0:    [RR:= V;  GG:= T;  BB:= P];
                 1:    [RR:= Q;  GG:= V;  BB:= P];
                 2:    [RR:= P;  GG:= V;  BB:= T];
                 3:    [RR:= P;  GG:= Q;  BB:= V];
                 4:    [RR:= T;  GG:= P;  BB:= V];
                 5:    [RR:= V;  GG:= P;  BB:= Q]
               other   [exit 1];
               R:= fix(RR*255.);
               G:= fix(GG*255.);
               B:= fix(BB*255.);
               Point(X+Radius, Radius-Y, R<<16+G<<8+B);
               ];
       ];

]</lang>

zkl

Uses Image Magick and the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl <lang zkl>var w=300,h=300,out=PPM(w,h); colorWheel(out); out.writeJPGFile("colorWheel.zkl.jpg");

fcn colorWheel(ppm){

  zero,R:=ppm.w/2, zero;
  foreach x,y in (w,h){
     v,hue:=(x - zero).toFloat().toPolar(y - zero); 
     if(v<=R){    // only render in the circle

if((hue = hue.toDeg())<0) hue+=360; // (-pi..pi] to [0..2pi) s:=v/R; // scale saturation zero at center to 1 at edge ppm[x,y]=hsv2rgb(hue,1.0,s);

     }
  }

}

fcn hsv2rgb(hue,v,s){ // 0<=H<360, 0<=v(brightness)<=1, 0<=saturation<=1 // --> 24 bit RGB each R,G,B in [0..255]

  to24bit:=fcn(r,g,b,m){
     r,g,b=((r+m)*255).toInt(),((g+m)*255).toInt(),((b+m)*255).toInt();
     r*0x10000 + g*0x100 + b
  };
  c:=v*s;
  x:=c*(1.0 - (hue.toFloat()/60%2 - 1).abs());
  m:=v - c;
  if     (0  <=hue< 60) return(to24bit(c,  x,  0.0,m));
  else if(60 <=hue<120) return(to24bit(x,  c,  0.0,m));
  else if(120<=hue<180) return(to24bit(0.0,c,  x,  m));
  else if(180<=hue<240) return(to24bit(0.0,x,  c,  m));
  else if(240<=hue<300) return(to24bit(x,  0.0,c,  m));
  else			 return(to24bit(c,  0.0,x,  m));

}</lang>

Output:

See this image