Simple If and or statement - if-statement

Hello i am trying to write what i thought would be a simple if and or statement in sas but i am running into trouble. The first condition after the and statement -in this case- "Nbr = 1000" does not process and is skipped over.
data want;
set have;
if family = "Pink flag" and NBR = 1000 OR NBR = 1500
then place = PF;
if family = "Blue Flag" and NBR = 2500 OR NBR = 2000
then place = BF;
/* this logic is repeated with different family names, nbrs and places */
run;
this is the output i get
family NBR Place
Pink Flag 1000 NJ
Pink Flag 1000 NJ
Pink Flag 1000 NJ
Pink Flag 1025 NJ
Pink Flag 1025 NJ
Pink Flag 1025 NJ
Pink Flag 1500 PF
Pink Flag 1500 PF
Pink Flag 1500 PF
Blue Flag 1000 BF
Blue Flag 2000 BF
Blue Flag 2000 BF
Blue Flag 2025 NJ
Blue Flag 2025 NJ
Blue Flag 2025 NJ
Blue Flag 2500 BF
Blue Flag 2500 BF
Blue Flag 2500 BF
as you can see it works for the 1500 but not the 1000. It also works for the Blue flag too
what i want
family NBR Place
Pink Flag 1000 PF
Pink Flag 1000 PF
Pink Flag 1000 PF
Pink Flag 1025 NJ
Pink Flag 1025 NJ
Pink Flag 1025 NJ
Pink Flag 1500 PF
Pink Flag 1500 PF
Pink Flag 1500 PF
Blue Flag 1000 BF
Blue Flag 2000 BF
Blue Flag 2000 BF
Blue Flag 2025 NJ
Blue Flag 2025 NJ
Blue Flag 2025 NJ
Blue Flag 2500 BF
Blue Flag 2500 BF
Blue Flag 2500 BF
i have also tried to use a where statement.
Thanks!

Use IN instead of the OR's which are incorrectly specified:
if family = "Pink flag" and NBR in ( 1000, 1500, 2500)
then place = PF;
Your OR conditions aren't being evaluated the way you thing and you should have brackets around those conditions. You're also missing the last equal sign.
This would also work:
if family = "Pink flag" and (NBR = 1000 OR NBR = 1500 OR NBR = 2500) then place = PF;
I'm assuming you've misttyped the 1025 in your example code versus the 1500 in the code. I'll let you fix that as needed because they don't currently align.

Related

PowerBI Matrix Average instead of Subtotal and Conditional Formatting According to That Average

Hello I am just new in powerBI and it is still hard to work on for me.
I have a matrix like that
DATE Sales Refund
26 Agu 45 5
p1 10 3
p2 15 2
p3 20 0
27 Agu 60 1
p1 15 1
p2 20 0
p3 25 0
In the date parts I have subtotals as it normally does. However, I want to show the average of that day there and when I get the average I will make conditional formatting according to it. If a cell is below average I will mark it with red point and in refunds I will do it for the values above the average.
Is there a way to do that. I searched for it for awhile but could not find.
The output I want is like that. (star is for red point.)
DATE Sales Refund
26 Agu 15 1.66
p1 10* 3*
p2 15 2*
p3 20 0
27 Agu 20 0.33
p1 15* 1*
p2 20 0
p3 25 0
Thanks.
You can colour the background; For example, create this measure:
AVG =
IF( SELECTEDVALUE(RefundTab[Sale] ) < CALCULATE(AVERAGE(RefundTab[Sale]), ALL(RefundTab[Code])),0,1)
From menu -> Conditional formatting -> Background color:
And here:
OR
you can create measure where we return string instead of number where we put some unicode value:
SumSaleIf =
var _sale = sum(RefundTab[Sale])
var _IfAVG = CALCULATE(AVERAGE(RefundTab[Sale]), ALL(RefundTab[Code]))
var _check = if(_sale < _IfAVG, _sale & UNICHAR(128315), _sale &"")
return _check

INDEX and AGGREGATE FUNCTION in Power BI

I have a two tables are data and report.
In data table the following columns are Size A, Size B and Size C, Type and Rank.
In data table I created rank for each type based on the sizes. The purpose of the rank column were multiple matches for same size in this case the rank column will help to decide exact type were match more than one.
In report table the following columns are Size A, Size B and Size C.
In both table the Size A, Size B and Size C columns are common/relationship.
I am trying find out the appropriate type according to the Size A, Size B and Size C from data table into report table.
Data:
TYPE
SIZEA
SIZEB
SIZEC
RANK
A6
420
600
440
11.00
A4
640
600
480
9.00
A5
890
1100
1330
2.00
A6
1335
1100
2350
1.00
A7
890
1100
390
5.00
A8
890
1100
530
3.00
A9
670
1100
540
4.00
A10
670
1100
440
6.00
A11
320
1100
440
10.00
A12
600
400
400
12.00
A13
800
600
400
8.00
A14
1000
600
500
7.00
Report:
SIZEA
SIZEB
SIZEC
DESIRED RESULT-TYPE
400
300
140
A12
A12
250
250
160
A12
600
400
285
A12
400
300
150
A12
280
230
170
A12
320
320
320
A12
320
320
320
A12
600
400
140
A12
400
300
140
A12
400
300
140
A12
370
320
340
A12
320
240
250
A12
300
200
90
A12
400
290
140
A12
I am applying following formula in report table in order to get the appropriate type according to the Size A, Size B and Size C
=INDEX(DATA!$D$2:$D$16,AGGREGATE(15,6,(ROW(DATA!$H$2:$H$16)-1)/(DATA!$H$2:$H$16=1/(1/MAX(((DATA!$E$2:$E$16>=$B3)*(DATA!$F$2:$F$16>=$A3)+(DATA!$E$2:$E$16>=$A3)*(DATA!$F$2:$F$16>=$B3)>0)*(DATA!$G$2:$G$16>=$C3)*DATA!$H$2:$H$16))),1))
How can I apply the same logic in Power BI? Any advise please.
I am looking for new calculate column options. Herewith share the Excel file for your reference
https://www.dropbox.com/scl/fi/iq0gteeyazrg79q7a4tb1/AUTO-MODIFY-REQ.xlsx?dl=0&rlkey=nyyerjsg7if2dz30z9iqo6kdc
Here is another formula that will return the same result as per your current formula, although it is still a long formula, but more easily to understand:
=INDEX($D$2:$D$13,MATCH(MAX(IF($G$2:$G$13<$L3,0,
IF((IF($E$2:$E$13<$K3,0,1)*IF($F$2:$F$13<$J3,0,1))+(IF($E$2:$E$13<$J3,0,1)*IF($F$2:$F$13<$K3,0,1))>0,1,0))
*$H$2:$H$13),$H$2:$H$13,0),1)
So I will break it down to explain how do it working:
Part 1: This if formula is checking comparison of Size C, if your data is lower than than table, the value for the Type will be zero therefore will not be considered at all because zero times any amount will be zero
(IF($G$2:$G$13<$L3,0
Part 2: This part is will first checking comparison of Size A vs Size B, if lower than table than return 0 and apply for other comparison, at then end using If at the beginning to reset the value so than the final value will be 0 or 1
IF((IF($E$2:$E$13<$K3,0,1)*IF($F$2:$F$13<$J3,0,1))+(IF($E$2:$E$13<$J3,0,1)*IF($F$2:$F$13<$K3,0,1))>0,1,0)
Part 3: From the value you calculate, if 0 times any ranking will be zero, so from none zero ranking such as 12 or 9, it will get the max value from the list, most of them are 12
Max((.....)*$H$2:$H$13)
Part 4: Index Match - Finally it is same as your formula first part, but you are using Index row which make it difficult to understand
INDEX($D$2:$D$13,MATCH(Max(...))
A shorter version of your formula by removing unnecessary portion:
=INDEX($D$2:$D$13,MATCH(MAX(IF($G$2:$G$13<$L4,0,
IF(($E$2:$E$13>=$K4)*($F$2:$F$13>=$J4)+($E$2:$E$13>=$J4)*($F$2:$F$13>=$K4)>0,1,0))*$H$2:$H$13),
$H$2:$H$13,0),1)
You can add a colum to your report table like:
Desired = LOOKUPVALUE(DataR[TYPE],DataR[RANK], MAXX(FILTER(DataR, DataR[SIZEA] >= ReportR[SIZEA] && DataR[SIZEB] >= ReportR[SIZEB] && DataR[SIZEC] >= ReportR[SIZEC]), DataR[RANK]))
It first filters the table to find the row where the sizes are more or equal to the report row, selects the rank and then does a lookup to the type.
Result:

Solid fill of an ellipse in python dxf

I'd like to draw filled ellipse with python. This would be easy if I could use PIL oder some other libraries. The problem is I need the ellipse in a .dxf file format. Therefore I used the dxfwrite package. This allows me to draw an ellipse but I couldn't find a way to fill it with a solid color. The following code does draw an ellipse line, but does not fill it.
import dxfwrite
from dxfwrite import DXFEngine as dxf
name = 'ellipse.dxf'
dwg = dxf.drawing(name)
dwg.add(dxf.ellipse((0,0), 5., 10., segments=200))
dwg.save()
Does anybody of you guys know a solution?
The HATCH entity is not supported by dxfwrite, if you use ezdxf this is the solution:
import ezdxf
dwg = ezdxf.new('AC1015') # hatch requires the DXF R2000 (AC1015) format or later
msp = dwg.modelspace() # adding entities to the model space
# important: major axis >= minor axis (ratio <= 1.) else AutoCAD crashes
msp.add_ellipse((0, 0), major_axis=(0, 10), ratio=0.5)
hatch = msp.add_hatch(color=2)
with hatch.edit_boundary() as boundary: # edit boundary path (context manager)
edge_path = boundary.add_edge_path()
# an edge path can contain line, arc, ellipse or spline elements
edge_path.add_ellipse((0, 0), major_axis_vector=(0, 10), minor_axis_length=0.5)
# upcoming ezdxf 0.7.7:
# renamed major_axis_vector to major_axis
# renamed minor_axis_length to ratio
dwg.saveas("solid_hatch_ellipse.dxf")
You could fill an ellipse by using a solid hatch object:
For the above example, here is a snippet from the DXF file that contains the ellipse and the hatch:
AcDbEntity
8
0
100
AcDbEllipse
10
2472.192919
20
1311.37942
30
0.0
11
171.0698134145308
21
-27.61597470964863
31
0.0
210
0.0
220
0.0
230
1.0
40
0.2928953354556341
41
0.0
42
6.283185307179586
0
HATCH
5
5A
330
2
100
AcDbEntity
8
0
100
AcDbHatch
10
0.0
20
0.0
30
0.0
210
0.0
220
0.0
230
1.0
2
SOLID
70
1
71
1
91
1
92
5
93
1
72
3
10
2472.192919357234
20
1311.379420138197
11
171.0698134145308
21
-27.61597470964863
40
0.2928953354556341
50
0.0
51
360.0
73
1
97
1
330
59
75
1
76
1
47
0.794178
98
1
10
2428.34191358924
20
1317.777876434349
450
0
451
0
460
0.0
461
0.0
452
0
462
1.0
453
2
463
0.0
63
5
421
255
463
1.0
63
2
421
16776960
470
LINEAR
1001
GradientColor1ACI
1070
5
1001
GradientColor2ACI
1070
2
1001
ACAD
1010
0.0
1020
0.0
1030
0.0
There are a lot of DXF codes involved. This is the information Autodesk provide:
Hatch group codes
Group code
Description
100
Subclass marker (AcDbHatch)
10
Elevation point (in OCS)
DXF: X value = 0; APP: 3D point (X and Y always equal 0, Z represents the elevation)
20, 30
DXF: Y and Z values of elevation point (in OCS)
Y value = 0, Z represents the elevation
210
Extrusion direction (optional; default = 0, 0, 1)
DXF: X value; APP: 3D vector
220, 230
DXF: Y and Z values of extrusion direction
2
Hatch pattern name
70
Solid fill flag (solid fill = 1; pattern fill = 0); for MPolygon, the version of MPolygon
63
For MPolygon, pattern fill color as the ACI
71
Associativity flag (associative = 1; non-associative = 0); for MPolygon, solid-fill flag (has solid fill = 1; lacks solid fill = 0)
91
Number of boundary paths (loops)
varies
Boundary path data. Repeats number of times specified by code 91. See Boundary Path Data
75
Hatch style:
0 = Hatch “odd parity” area (Normal style)
1 = Hatch outermost area only (Outer style)
2 = Hatch through entire area (Ignore style)
76
Hatch pattern type:
0 = User-defined; 1 = Predefined; 2 = Custom
52
Hatch pattern angle (pattern fill only)
41
Hatch pattern scale or spacing (pattern fill only)
73
For MPolygon, boundary annotation flag (boundary is an annotated boundary = 1; boundary is not an annotated boundary = 0)
77
Hatch pattern double flag (pattern fill only):
0 = not double; 1 = double
78
Number of pattern definition lines
varies
Pattern line data. Repeats number of times specified by code 78. See Pattern Data
47
Pixel size used to determine the density to perform various intersection and ray casting operations in hatch pattern computation for associative hatches and hatches created with the Flood method of hatching
98
Number of seed points
11
For MPolygon, offset vector
99
For MPolygon, number of degenerate boundary paths (loops), where a degenerate boundary path is a border that is ignored by the hatch
10
Seed point (in OCS)
DXF: X value; APP: 2D point (multiple entries)
20
DXF: Y value of seed point (in OCS); (multiple entries)
450
Indicates solid hatch or gradient; if solid hatch, the values for the remaining codes are ignored but must be present. Optional; if code 450 is in the file, then the following codes must be in the file: 451, 452, 453, 460, 461, 462, and 470. If code 450 is not in the file, then the following codes must not be in the file: 451, 452, 453, 460, 461, 462, and 470
0 = Solid hatch
1 = Gradient
451
Zero is reserved for future use
452
Records how colors were defined and is used only by dialog code:
0 = Two-color gradient
1 = Single-color gradient
453
Number of colors:
0 = Solid hatch
2 = Gradient
460
Rotation angle in radians for gradients (default = 0, 0)
461
Gradient definition; corresponds to the Centered option on the Gradient Tab of the Boundary Hatch and Fill dialog box. Each gradient has two definitions, shifted and unshifted. A Shift value describes the blend of the two definitions that should be used. A value of 0.0 means only the unshifted version should be used, and a value of 1.0 means that only the shifted version should be used.
462
Color tint value used by dialog code (default = 0, 0; range is 0.0 to 1.0). The color tint value is a gradient color and controls the degree of tint in the dialog when the Hatch group code 452 is set to 1.
463
Reserved for future use:
0 = First value
1 = Second value
470
String (default = LINEAR)
I hope this may be of some use to you. I apologize if I missunderstood your issue.

Which color gradient is used to color mandelbrot in wikipedia?

At Wikipedia's Mandelbrot set page there are really beautiful generated images of the Mandelbrot set.
I also just implemented my own Mandelbrot algorithm. Given n is the number of iterations used to calculate each pixel, I color them pretty simple from black to green to white like that (with C++ and Qt 5.0):
QColor mapping(Qt::white);
if (n <= MAX_ITERATIONS){
double quotient = (double) n / (double) MAX_ITERATIONS;
double color = _clamp(0.f, 1.f, quotient);
if (quotient > 0.5) {
// Close to the mandelbrot set the color changes from green to white
mapping.setRgbF(color, 1.f, color);
}
else {
// Far away it changes from black to green
mapping.setRgbF(0.f, color, 0.f);
}
}
return mapping;
My result looks like that:
I like it pretty much already, but which color gradient is used for the images in Wikipedia? How to calculate that gradient with a given n of iterations?
(This question is not about smoothing.)
The gradient is probably from Ultra Fractal. It is defined by 5 control points:
Position = 0.0 Color = ( 0, 7, 100)
Position = 0.16 Color = ( 32, 107, 203)
Position = 0.42 Color = (237, 255, 255)
Position = 0.6425 Color = (255, 170, 0)
Position = 0.8575 Color = ( 0, 2, 0)
where Position is in range [0, 1) and Color is RGB in range [0, 255].
The catch is that the colors are not linearly interpolated. The interpolation of colors is likely cubic (or something similar). Following image shows the difference between linear and Monotone cubic interpolation:
As you can see the cubic interpolation results in smoother and "prettier" gradient. I used monotone cubic interpolation to avoid "overshooting" of the [0, 255] color range that can be caused by cubic interpolation. Monotone cubic ensures that interpolated values are always in the range of input points.
I use following code to compute the color based on iteration i:
double smoothed = Math.Log2(Math.Log2(re * re + im * im) / 2); // log_2(log_2(|p|))
int colorI = (int)(Math.Sqrt(i + 10 - smoothed) * gradient.Scale) % colors.Length;
Color color = colors[colorI];
where i is the diverged iteration number, re and im are diverged coordinates, gradient.Scale is 256, and the colors is and array with pre-computed gradient colors showed above. Its length is 2048 in this case.
Well, I did some reverse engineering on the colours used in wikipedia using the Photoshop eyedropper. There are 16 colours in this gradient:
R G B
66 30 15 # brown 3
25 7 26 # dark violett
9 1 47 # darkest blue
4 4 73 # blue 5
0 7 100 # blue 4
12 44 138 # blue 3
24 82 177 # blue 2
57 125 209 # blue 1
134 181 229 # blue 0
211 236 248 # lightest blue
241 233 191 # lightest yellow
248 201 95 # light yellow
255 170 0 # dirty yellow
204 128 0 # brown 0
153 87 0 # brown 1
106 52 3 # brown 2
Simply using a modulo and an QColor array allows me to iterate through all colours in the gradient:
if (n < MAX_ITERATIONS && n > 0) {
int i = n % 16;
QColor mapping[16];
mapping[0].setRgb(66, 30, 15);
mapping[1].setRgb(25, 7, 26);
mapping[2].setRgb(9, 1, 47);
mapping[3].setRgb(4, 4, 73);
mapping[4].setRgb(0, 7, 100);
mapping[5].setRgb(12, 44, 138);
mapping[6].setRgb(24, 82, 177);
mapping[7].setRgb(57, 125, 209);
mapping[8].setRgb(134, 181, 229);
mapping[9].setRgb(211, 236, 248);
mapping[10].setRgb(241, 233, 191);
mapping[11].setRgb(248, 201, 95);
mapping[12].setRgb(255, 170, 0);
mapping[13].setRgb(204, 128, 0);
mapping[14].setRgb(153, 87, 0);
mapping[15].setRgb(106, 52, 3);
return mapping[i];
}
else return Qt::black;
The result looks pretty much like what I was looking for:
:)
I believe they're the default colours in Ultra Fractal. The evaluation version comes with source for a lot of the parameters, and I think that includes that colour map (if you can't infer it from the screenshot on the front page) and possibly also the logic behind dynamically scaling that colour map appropriately for each scene.
This is an extension of NightElfik's great answer.
The python library Scipy has monotone cubic interpolation methods in version 1.5.2 with pchip_interpolate. I included the code I used to create my gradient below. I decided to include helper values less than 0 and larger than 1 to help the interpolation wrap from the end to the beginning (no sharp corners).
#set up the control points for your gradient
yR_observed = [0, 0,32,237, 255, 0, 0, 32]
yG_observed = [2, 7, 107, 255, 170, 2, 7, 107]
yB_observed = [0, 100, 203, 255, 0, 0, 100, 203]
x_observed = [-.1425, 0, .16, .42, .6425, .8575, 1, 1.16]
#Create the arrays with the interpolated values
x = np.linspace(min(x_observed), max(x_observed), num=1000)
yR = pchip_interpolate(x_observed, yR_observed, x)
yG = pchip_interpolate(x_observed, yG_observed, x)
yB = pchip_interpolate(x_observed, yB_observed, x)
#Convert them back to python lists
x = list(x)
yR = list(yR)
yG = list(yG)
yB = list(yB)
#Find the indexs where x crosses 0 and crosses 1 for slicing
start = 0
end = 0
for i in x:
if i > 0:
start = x.index(i)
break
for i in x:
if i > 1:
end = x.index(i)
break
#Slice away the helper data in the begining and end leaving just 0 to 1
x = x[start:end]
yR = yR[start:end]
yG = yG[start:end]
yB = yB[start:end]
#Plot the values if you want
#plt.plot(x, yR, color = "red")
#plt.plot(x, yG, color = "green")
#plt.plot(x, yB, color = "blue")
#plt.show()

c++ defined 16bit (high) color

I am working on a project with a TFT touch screen. With this screen there is an included library. But after some reading, I still don't get something. In the library there are some defines regarding colors:
/* some RGB color definitions */
#define Black 0x0000 /* 0, 0, 0 */
#define Navy 0x000F /* 0, 0, 128 */
#define DarkGreen 0x03E0 /* 0, 128, 0 */
#define DarkCyan 0x03EF /* 0, 128, 128 */
#define Maroon 0x7800 /* 128, 0, 0 */
#define Purple 0x780F /* 128, 0, 128 */
#define Olive 0x7BE0 /* 128, 128, 0 */
#define LightGrey 0xC618 /* 192, 192, 192 */
#define DarkGrey 0x7BEF /* 128, 128, 128 */
#define Blue 0x001F /* 0, 0, 255 */
#define Green 0x07E0 /* 0, 255, 0 */
#define Cyan 0x07FF /* 0, 255, 255 */
#define Red 0xF800 /* 255, 0, 0 */
#define Magenta 0xF81F /* 255, 0, 255 */
#define Yellow 0xFFE0 /* 255, 255, 0 */
#define White 0xFFFF /* 255, 255, 255 */
#define Orange 0xFD20 /* 255, 165, 0 */
#define GreenYellow 0xAFE5 /* 173, 255, 47 */
#define Pink 0xF81F
Those are 16-bit colors. But how do they go from: 0, 128, 128(dark cyan) to 0x03EF. I mean, how do you convert a 16-bit color to a uint16? This doesn't need to have an answer in code, because I just want to add some colors in the library. A link to a online converter (which I could not find) would be okay as well :)
Thanks
From these one can easily find out the formula:
#define Red 0xF800 /* 255, 0, 0 */
#define Magenta 0xF81F /* 255, 0, 255 */
#define Yellow 0xFFE0 /* 255, 255, 0 */
F800 has 5 MSB bits set and FFE0 has 5 LSB not set.
0xF81F has obviously both 5 LSB's and 5 MSB's set, which proves the format to be RGB565.
The formula to convert a value 173 to Red is not as straightforward as it may look -- you can't simply drop the 3 least significant bits, but have to linearly interpolate to make 255 to correspond to 31 (or green 255 to correspond to 63).
NewValue = (31 * old_value) / 255;
(And this is still just a truncating division -- proper rounding could be needed)
With proper rounding and scaling:
Uint16_value = (((31*(red+4))/255)<<11) |
(((63*(green+2))/255)<<5) |
((31*(blue+4))/255);
EDIT Added parenthesis to as helpfully suggested by JasonD.
You need to know the exact format of the display, just "16-bit" is not enough.
There's RGB555, in which each of the three components get 5 bits. This drops the total color space to just 32,768 colors, wasting one bit but it's very simple to manage since the there's the same number of shades for each component.
There's also RGB565, in which the green component is given 6 bits (since the human eye is more sensitive to green). This might be the format you're having, since the "dark green" example is 0x03e0 which in binary is 0b0000 0011 1110 0000. Since there's 6 bits set to 1 there, I guess that's the total allocation for the green component and showing it's maximum value.
It's like this, then (with spaces separating every four bits and re-using the imaginary 0b prefix):
0bRRRR RGGG GGGB BBBB
Of course, the bit ordering can differ too, in the word.
The task of converting a triplet of numbers into a bit-packed word is quite easily done in typically programming languages that have bit manipulation operators.
In C, it's often done in a macro, but we can just as well have a function:
#include <stdint.h>
uint16_t rgb565_from_triplet(uint8_t red, uint8_t green, uint8_t blue)
{
red >>= 3;
green >>= 2;
blue >>= 3;
return (red << 11) | (green << 5) | blue;
}
note that the above assumes full 8-bit precision for the components, so maximum intensity for a component is 255, not 128 as in your example. If the color space really is using 7-bit components then some additional scaling would be necessary.
It looks like you're using RGB565, first 5 bits for Red, then 6 bits for Green, then 5 bits for Blue.
You should mask with 0xF800 and shift right 11 bits to get the red component (or shift 8 bits to get a value from 0-255).
Mask with 0x07E0 and shift right 5 bits to get green component (or 3 to get a 0-255 value).
Mask with 0x001F to get the blue component (and shift left 3 bits to get 0-255).
Your colours are in 565 format. It would be more obvious if you wrote them out in binary.
Blue, (0,0,255) is 0x001f, which is 00000 000000 11111
Green, (0, 255, 0) is 0x07e0, which is 00000 111111 00000
Red, (255, 0, 0) is 0xf800, which is 11111 000000 00000
To convert a 24 bit colour to 16 bit in this format, simply mask off the upper bits needed from each component, shift into position, and OR together.
The convert back into 24 bit colour from 16 bit, mask each component, shift into position, and then duplicate the upper bits into the lower bits.
In your examples it seems that some colours have been scaled and rounded rather than shifted.
I strongly recommend using the bit-shift method rather than scaling by a factor like 31/255, because the bit-shifting is not only likely to be faster, but should give better results.
The 3-part numbers you’re showing are applicable to 24-bit color. 128 in hex is 0x7f, but in your color definitions, it's being represented as 0x0f. Likewise, 255 is 0xff, but in your color definitions, it's being represented as 0x1f. This suggests that you need to take the 3-part numbers and shift them down by 3 bits (losing 3 bits of color data for each color). Then combine them into a single 16-bit number:
uint16 color = ((red>>3)<<11) | ((green>>2)<<5) | (blue>>3);
...revised from earlier because green uses 6 bits, not 5.
You need to know how many bits there are per colour channel. So yes, there are 16 bits for a colour, but the RGB components are each some subset of those bits. In your case, red is 5 bits, green is 6, and blue is 5. The format in binary would look like so:
RRRRRGGG GGGBBBBB
There are other 16 bit colour formats, such as red, green, and blue each being 5 bits and then use the remaining bit for an alpha value.
The range of values for both the red and blue channels will be from 0 to 2^5-1 = 31, while the range for green will be 0 to 2^6-1 = 63. So to convert from colours in the form of (0->255),(0->255),(0->255) you will need to map values from one to the other. For example, a red value of 128 in the range 0->255 will be mapped to (128/255) * 31 = 15.6 in the red channel with range 0-31. If we round down, we get 15 which is represented as 01111 in five bits. Similarly, for the green channel (with six bits) you will get 011111. SO the colour (128,128,128) will map to 01111011 11101111 which is 0x7BEF in hexadecimal.
You can apply this to the other values too: 0,128,128 becomes 00000011 11101111 which is 0x03EF.
Those colours shown in your code are RGB565. As shown by
#define Blue 0x001F /* 0, 0, 255 */
#define Green 0x07E0 /* 0, 255, 0 */
#define Red 0xF800 /* 255, 0, 0 */
If you simply want to add some new colours to this #defined list, the simplest way to convert from 16bit UINT per channel is just to shift your values down to loose the the low order bits and then shift and (or) them into position in the 16bitRGB value.
This could well produce banding artefacts though, and there may well be a better conversion method.
i.e.
UINT16 blue = 0xFF;
UINT16 green = 0xFF;
UINT16 red = 0xFF;
blue >>= 11; // top 5 bits
green >>= 10; // top 6 bits
red >>= 11; // top 5 bits
UINT16 RGBvalue = blue | (green <<5) | (red << 11)
You may need to mask of any unwanted stray bits after the shifts, as I am unsure how this works, but I think the code above should work.
Building on unwind's answer, specifically for the Adafruit GFX library using the Arduino 2.8" TFT Touchscreen(v2), you can add this function to your Arduino sketch and use it inline to calculate colors from rgb:
uint16_t getColor(uint8_t red, uint8_t green, uint8_t blue)
{
red >>= 3;
green >>= 2;
blue >>= 3;
return (red << 11) | (green << 5) | blue;
}
Now you can use it inline as so, illustrated with a function that creates a 20x20 square at x0,y0:
void setup() {
tft.begin();
makeSquare(getColor(20,157,217));
}
unsigned long makeSquare(uint16_t color1) {
tft.fillRect(0, 0, 20, 20, color1);
}
Docs for the Adafruit GFX library can be found here