Thanks to the methods of the class ImageProcessor [see Post], it is possible to read and write pixels in an image.
Updated for ECMAScript2015+, it requires at least version ImageJ 1.51r and Java 9. See this post for update [Link].
1. Reading pixels in a RGB image
As shown in a previous post [see Post], you can use the method (or function)getPixel(x,y)
to read a pixel of an image. As a refresher, if you load the sample image entitled Clown
and copy the following script for reading the pixel of X,Y-coordinates (60,100), the value -5432564
is displayed in the Log window. // File > Open Samples > Clown let imp = IJ.getImage(); let ip = imp.getProcessor(); let pixel = ip.getPixel(60,100); IJ.log(pixel); // -5432564
Now, if we convert this signed integer number in an unsigned number using the bitwise operator
>>>
, we get...let uint = pixel >>> 0; IJ.log(uint); // 4289534732
Because this huge unsigned number
4289534732
is not really useful, it is more convenient — from a computer viewpoint — to display it using the hexadecimal notation...IJ.log(uint.toString(16) ); // Hexadecimal: ffad1b0c IJ.log(uint.toString(2) ); // Binary: 11111111101011010001101100001100
Here we go!! this 32-bit unsigned number contains the red, green and blue components encoded as 8-bit unsigned numbers (0 up to 255) .
Note: Lost? Read the second section of this post [Link].
The 32-bit number is structured as shown in the table below.
- | Byte#3 | Byte#2 | Byte#1 | Byte#0 |
Binary | 11111111 | 10101101 | 00011011 | 00001100 |
HexaDec. | ff | ad | 1b | 0c |
Dec. | 255 | 173 | 27 | 12 |
Color | Unknown | Red | Green | Blue |
Note: The byte #3 is unused in ImageJ but in other image processing softwares may be used to store the transparency or alpha channel.
To read the red, green, and blue components of this pixel, we need to extract them. For this, we use the bitwise operators: and (&) and shift (>>).
The blue is located at Byte #0 in the unsigned number. If we mask all the other bytes (and by extension, the corresponding bits), we will only extract the byte #0.
uint (base 2) 11111111101011010001101100001100
and (&)
mask 00000000000000000000000011111111
result 00000000000000000000000000001100 = 12 (base 10)
In JavaScript, this is written like that...let blue = uint & 0xff;
For the red and green components, we have to shift the number to the right before ANDing with the mask 0xff.
With green, we need to shift the number to the right of 8 bits to place the byte #1 in the position of the byte #0.
uint (base 2) 11111111101011010001101100001100 unint shifted 00000000111111111010110100011011The shift operator >> pushes all the bits to the right and the outside extra-bits (in blue) are removed.00001100(>> 8) and (&) mask 00000000000000000000000011111111 result 00000000000000000000000000011011 = 27 (base 10)
In JavaScript, this is written like that...
let green = uint >> 8 & 0xff; let red = uint >> 16 & 0xff;
2. Writing pixels
We can use the same methods as those for grayscale image available in class ImageProcessor:-
putPixel(int x, int y, int value)
: Stores the specified value at (x,y). set(int x, int y, int value)
: Faster version of putPixel() that does not clip out of range values and does not do bounds checking.set(index)
: Same as above but with index rather coordinates
However, we need to transform the red, green, and blue components in one single 32-bit number. Thus, we have to make the reverse operation, we need to shift the 8-bit numbers to the a certain amount of bits but now to the left and ORed all the shifted components.
For example, create a black RGB image of 100x100 pixels, then try to set the central pixel of coordinates (50,50) with the orange RGB color (250,105,30).
// Set the pixel (50,50) a value of (250,105,30 (orange). let imp = IJ.createImage("RGB", "RGB black", 100, 100, 1); let red = 250; let green = 105; let blue = 30; let pixel = red << 16 | green << 8 | blue; imp.getProcessor().putPixel(50,50,pixel); imp.show();
Thank you for reading.
<< Previous: Read/Write Pixels Next: TODO >>
5. Other crazybiocomputing posts
Further readings are available in ...
No comments:
Post a Comment