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
Related
I'm learning C++ through a website - learncpp.com
and I encountered a line of code that confuses me and I'm not sure how to research it. I went back looking for an explanation on what it is and couldn't find it and I would simply like to know what to look up or what it's called so I could learn more about it.
Here's the code:
unsigned char option_viewed = 0x01;
It's referring to a bit flag. What i'm confused about is the 0x01; part. I'm assuming it's hexadecimal for one, but I'm not sure.
Thanks
When creating bit flags, people often write the literal values in hex because they are easier to read:
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
Instead of:
1, 2, 4, 8, 16, 32, 64, 128
In C++ you can represent an integer literal in 3 different bases: decimal (base 10), octal (base 8), or hexidecimal (base 16). Numbers written the "normal" way (1, 13, 405, ...) are interpreted by the compiler as base 10. Numbers starting with a 0 (01, 040, 0800, ...) are interpreted as base 8. Numbers starting with a 0x (0x1, 0x01, 0x800, ...) are interpreted as base 16.
Note that with base 16 numbers, you can have as many leading 0's after the 0x as you want. That is, 0x1, 0x01, and 0x00000001 are all just 1. The reason you might want to include more leading 0's is for alignment of the code to help with readability. As John Zwinck pointed out it's common for people to use hexidecimal to represent bit flags because every power of 2 can be written with either a 1, 2, 4, or 8 in one of the digits. So you might see something like
unsigned char red = 0x01; // 1 base 10, 00000001 base 2
unsigned char green = 0x02; // 2 base 10, 00000010 base 2
unsigned char blue = 0x04; // 4 base 10, 00000100 base 2
unsigned char yellow = 0x08; // 8 base 10, 00001000 base 2
unsigned char magenta = 0x10; // 16 base 10, 00010000 base 2
unsigned char cyan = 0x20; // 32 base 10, 00100000 base 2
unsigned char white = 0x40; // 64 base 10, 01000000 base 2
unsigned char black = 0x80; // 128 base 10, 10000000 base 2
Really each variable stores a numeric value, but because we're using powers of 2 then each value is represented by a different bit being set to 1. Since the type is an unsigned char which is only 8-bits, you'll never encounter a power larger than 255, or 0xFF hexidecimal, so two digits after the 0x is enough. If you were storing an unsigned short then you might want to write it as 0x0001 which is still just 1, but you're making it obvious that it's a 16-bit integer rather than 8-bit.
You can read more about the different numerical bases in C++ here.
First of all, I realize there are existing questions about converting an RGB image to an HSV image out there; I used one of those questions to help me write my code. However, I am getting values for HSV that don't make sense to me.
What I know about HSV I have gotten from this website. From this colorpicker, I have inferred that H is a number ranging from 0-360 degrees, S is a number ranging from 0-100%, and V is a number ranging from 0-100%. Therefore, I had assumed that my code (as follows) would return an H value between 0 and 360, and S/V values between 0 and 100. However, this is not the case.
I plugged my program's output into the above color picker, which all S/V values down to 100 when they exceeded 100. As you can see, the output is close to what it should be, but is not accurate. I feel like this is because I am interpreting the HSV values incorrectly.
For contex, I am going to establish a range for each color on the cube and from there look at the other faces and fill out the current setup of the cube in another program I have.
My code:
void get_color(Mat img, int x_offset, int y_offset)
{
Rect outline(x_offset - 2, y_offset - 2, 5, 5);
rectangle(img, outline, Scalar(255, 0, 0), 2);
Rect sample(x_offset, y_offset, 1, 1);
Mat rgb_image = img(sample);
Mat hsv_image;
cvtColor(rgb_image, hsv_image, CV_BGR2HSV);
Vec3b hsv = hsv_image.at<Vec3b>(0, 0);
int hue = hsv.val[0];
int saturation = hsv.val[1];
int value = hsv.val[2];
printf("H: %d, S: %d, V: %d \n", hue, saturation, value);
}
Output of the program:
H: 21, S: 120, V: 191 // top left cubie
H: 1, S: 180, V: 159 // top center cubie
H: 150, S: 2, V: 142 // top right cubie
H: 86, S: 11, V: 159 // middle left cubie
H: 75, S: 12, V: 133 // middle center cubie
H: 5, S: 182, V: 233 // middle right cubie
H: 68, S: 7, V: 156 // bottom left cubie
H: 25, S: 102, V: 137 // bottom center cubie
H: 107, S: 155, V: 69 // bottom right cubie
Starting image (pixel being extracted # center of each blue square):
Resulting colors (as the above color picker gave):
As you can see, the red and white is fairly accurate, but the orange and yellow are not correct and the blue is blatantly wrong; it is impossible for the pixel I looked at to actually be that color. What am I doing wrong? Any help would be greatly appreciated.
OpenCV has a funny way of representing its colors.
Hue - Represented as a number from 0-179 instead of 0-360. Therefore, multiply the H value by two before plugging it into a traditional color picker.
Saturation/Value - Represented as a number from 0-255. To get a percentage, divide given answer by 255 and multiply by 100 to get a percentage.
Everything works much more sensibly now. See this website for more details on OpenCV and HSV.
I read the IP RFC and in there it says the 4 first bits of the IP header is the version. In the drawing it also shows that bits 0 to 3 are the version.
https://www.rfc-editor.org/rfc/rfc791#section-3.1
But when I look at the first byte of the header (as captured using pcap lib) I see this byte:
0x45
This is a version 4 IP header but obviously bits 4 to 7 are equal to 4 and not bits 0 to 3 as I expected.
I expected doing a bitwise and on first byte and 0x0F will get me the version but it seems that I need to and with 0xF0.
Am I missing something? Understanding something incorrectly?
You should read Appendix B of the RFC:
Whenever an octet represents a numeric quantity the left most bit in the
diagram is the high order or most significant bit. That is, the bit
labeled 0 is the most significant bit. For example, the following
diagram represents the value 170 (decimal).
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|1 0 1 0 1 0 1 0|
+-+-+-+-+-+-+-+-+
Which means everything is correct except for your assumption that the “first four bits” are the least-significant, while those are the most-significant.
E.g. in the 7th and 8th bytes, containing the flags and the fragment offset, you can separate those as follows (consider that pseudocode, even though it is working C#):
byte flagsAndFragmentHi = packet[6];
byte fragmentLo = packet[7];
bool flagReserved0 = (flagsAndFragmentHi & 0x80) != 0;
bool flagDontFragment = (flagsAndFragmentHi & 0x40) != 0;
bool flagMoreFragments = (flagsAndFragmentHi & 0x20) != 0;
int fragmentOffset = ((flagsAndFragmentHi & 0x1F) << 8) | (fragmentLo);
Note that the more significant (left-shifted 8 bits) portion of the fragment offset is in the first byte (because IP works in big endian). Generally: bits on the left in the diagram are always more significant.
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()
for(unsigned int h=0; h<ImageBits.iHeight; h++)
{
for(unsigned int w=0; w<ImageBits.iWidth; w++)
{
// So in this loop - if our data isn't aligned to 4 bytes, then its been padded
// in the file so it aligns...so we check for this and skip over the padded 0's
// Note here, that the data is read in as b,g,r and not rgb as you'd think!
unsigned char r,g,b;
fread(&b, 1, 1, fp);
fread(&g, 1, 1, fp);
fread(&r, 1, 1, fp);
ImageBits.pARGB[ w + h*ImageBits.iWidth ] = (r<<16 | g<<8 | b);
}// End of for loop w
//If there are any padded bytes - we skip over them here
if( iNumPaddedBytes != 0 )
{
unsigned char skip[4];
fread(skip, 1, 4 - iNumPaddedBytes, fp);
}// End of if reading padded bytes
}// End of for loop h
I do not understand this statement and how does it store the rgb value of the pixel
ImageBits.pARGB[ w + h*ImageBits.iWidth ] = (r<<16 | g<<8 | b);
i did a read up on the << bitwise shift operator but i still do not understand how it works.Can someone help me out here.
You need to convert separate values for Red, Green and Blue into a single variable, so you push them 16 and 8 bits to the "left" respectively, so they align 8 bits for Red (begin - 16), then you get 8 bits for Green (begin - 8) and the remaining color.
Consider the following:
Red -> 00001111
Green -> 11110000
Blue -> 10101010
Then RGB -> that has 24 bits capacity would look like this initially ->
-> 00000000 00000000 00000000
(there would actually be some random rubbish but it's easier to
demonstrate like this)
Shift the Red byte 16 places to the left, so we get 00001111 00000000 00000000.
Shift the Green byte 8 places to the left, so we have 00001111 11110000 00000000.
Don't shift the Blue byte, so we have 00001111 11110000 10101010.
You could achieve a similar result with unions. Here's an ellaboration as to why we do it like this. The only way for you to access a variable is to have it's address (usually bound to a variable name, or an alias).
That means that we have an address of the first byte only and also a guarantee that if it's a variable that is 3 bytes wide, the following two bytes that are next to our addressed byte belong to us. So we can literally "push the bits" to the left (shift them) so they "flow" into the remaining bytes of the variable. We could also pointer-arithmetic a pointer there or as I've mentioned already, use a union.
Bit shifting moves the bits that make up the value along by the number you specify.
In this case it's done with colour values so that you can store multiple 1 byte components (such as RGBA which are in the range 0-255) in a single 4 byte structure such as an int
Take this byte:
00000011
which is equal to 3 in decimal. If we wanted to store the value 3 for the RGB and A channel, we would need to store this value in the int (the int being 32 bits)
R G B A
00000011 00000011 00000011 00000011
As you can see the bits are set in 4 groups of 8, and all equal the value 3, but how do you tell what the R value is when it's stored this way?
If you got rid of the G/B/A values, you'd be left with
00000011 00000000 00000000 00000000
Which still doesn't equal 3 - (in fact it's some massive number - 12884901888 I think)
In order to get this value into the last byte of the int, you need to shift the bits 24 places to the right. e.g.
12884901888 >> 24
Then the bits would look like this:
00000000 00000000 00000000 00000011
And you would have your value '3'
Basically it's just a way of moving bits around in a storage structure so that you can better manipulate the values. Putting the RGBA values into a single value is usually called stuffing the bits
let's visualize this and break it into several steps, and you'll see how simple it is.
let's say we have the ARGB 32 bit variable, that can be viewed as
int rgb = {a: 00, r: 00, g: 00, b: 00} (this is not valid code, of course, and let's leave the A out of this for now).
the value in each of these colors is 8 bit of course.
now we want to place a new value, and we have three 8 bit variables for each color:
unsigned char r = 0xff, g=0xff, b=0xff.
what we're essentially doing is taking a 32 bit variable, and then doing this:
rgb |= r << 16 (shifting the red 16 bit left. everything to right of it will remain 0)
so now we have
rgb = [a: 00, r: ff, g: 00, b: 00]
and now we do:
rgb = rgb | (g << 8) (meaning taking the existing value and OR'ing it with green shifted to its place)
so we have [a: 00, r: ff, g: ff, b: 00]
and finally...
rgb = rgb | b (meaning taking the value and ORing it with the blue 8 bits. the rest remains unchanged)
leaving us with [a: 00, r: ff, g: f, b: ff]
which represents a 32 bit (24 actually since the Alpha is irrelevant to this example) color.