Bạn có chắc chắn muốn xóa bài viết này không ?

Bạn có chắc chắn muốn xóa bình luận này không ?

#
**JAVA: Image and Pixel Processing**

Chao Cac Ban

I was absent for a very long time... To my wonder that Kipalog is still alive. It's a very good news.

Today I show you a brief tutorial about **Image and Pixel Processing in JAVA**. A proverb says "a picture is more than thousand words". How true! Even Confucius had to concede:

"If you tell me about it I'll forget it,

If you show it to me I'll remember it,

If you let me do it I'll understand it"

So. I show you and let you do so that you remember and understand what Image and Color are. First, let talk about a digital Image (or picture if you so will). What is a digital image?

Pic.1

A digital image is a group of **PIXELS** (PIX for Picture and EL for Element) which are represented by a combination of 3 different colors: RED, GREEN and BLUE or **RGB** for short. If a pixel can be made opaque or transparent it is an **ARGB**, where A is the controlling element. To represent the RGB or ARGB a computer needs at least 3 bytes (RGB) or 4 bytes (ARGB). And each byte can be displayed in 2 hex digits: 0x00 - 0xFF. For examples:

```
The color ORANGE or an ORANGE Pixel:
RGB: 0xFAA500
ARGB: 0x00FAA500 (fully or 100% transparent), 0x80FFFFFF (haft or 50% transparent), 0xFFFFFFFF (fully or 100% opaque)
```

As you see, with the ALPHA byte a Color (or Pixel) has 255 variable possibilities between total opaque to total transparent. Pic.2 shows you how an ARGB looks like:

Everything looks good. BUT why I have mentioned ARGB and RGBA? Well, the world is not a simpleton, but always a YING-YANG world. IBM computers usually work with **BIG-ENDIAN** and some others work with **LITTLE ENDIAN**. What is that, the endian? It's the byte-sequence to represent a number or an address. Examples:

```
The color 0x80FAA500 (a word or 32 bits)
byte 0 byte 1 byte 2 byte 3
LITTLE ENDIAN: 80 FA A5 00
BIG ENDIAN 00 A5 FA 80
```

For human, the left digit is always higher than the next right digit and LITTLE ENDIAN is for human easier to understand than BIG ENDIAN. Luckily is that JAVA uses LITTLE ENDIAN to store its data (in files).

ARGB

RGBA

You can run this little program to see the ENDIAN of your computer:

Java:

```
public class MyEndian {
public static void main(String... args) {
System.out.println("->EndianOrder:"+java.nio.ByteOrder.nativeOrder());
}
}
```

and the output from an INTEL PC will be:

```
->EndianOrder:LITTLE_ENDIAN
```

From the RGB or ARGB/RGBA structure it's obvious that the value of RGB (or ARGB/RGBA) can only be presented by an **integer** (or 4 bytes). If you are working with another OOPL than JAVA you have to be carefully to consider the ENDIAN because the interchange between bytes and integer is dependent on the endian. As said, JAVA stores and works with LITTLE ENDIAN. The conversion between 4 bytes and an integer is a straightforward work:

```
// from integer to byte[4]
int i = 0x010203;
byte[] b = new bytes[] { (byte)((i & 0xFF000000) >> 24), (byte)((i & 0xFF0000) >> 16), (byte)((i & 0xFF00) >> 8), (byte)(i & 0xFF) };
// from byte[4] to integer
int I = (b[0]&0xFF) << 24 + (b[1] &0xFF) << 16 + (b[2] & 0xFF) << 8 + b[3] & 0xFF;
```

You may wonder why I have to **AND** a byte with **0xFF**, am I right? Well, JAVA doesn't have UNSIGNED byte, hence the term "byte & 0xFF" signifies an internal conversion of a byte to an int before the AND operation can be executed. Example:

```
byte b = 0xFF; // as - 1 from a range between -1....-127 0....127 or 0xFF....x81 x00....0x7F
int i = (int) b; // i yields -1 or 0xFFFFFFFF
int j = (int)(b & 0xFF); // j = 255 = 0xFFFFFFFF & 0x000000FF = 0x000000FF
```

**IT** or **Computer Science** (CS) without Mathematics is like a flower without water. If you don't master the most basic mathematical knowledge you wither like a flower. CS works with binary system and knows only **ONE operation: addition**. The other operations (subtract, multiplication and division) are derived from Addition. Binary means 0 (zero) or 1 (ONE). Not zero is one and vice versa. In Math an opposite of a binary number can be represented by either the FIRST Complement or the SECOND Complement:

- First Complement or 1st Complement is the reverse of each digit. Example: 15 = b1111, the 1st complement is 0000.
- Second Complement or 2nd Complement is the addition of the 1st Complement with 1. Example: 15 = b1111 +b1 = b10000.

With the complements Sub, Mul and Div can be implemented. I don't go into details with the MUL/DIV binary operation but show you how the Sub works. The algorithm is as following:

- The subtractor is converted to the 2nd-Complement,
- The 2nd-Complement is added to the subtrahend

Depend on the sign the result could exceed the digit number of subtractor and subtrahend. If so, it's an OVERFLOW and it can be ignored.

Example: 4-digit bits, the 1st digit is the sign (0: plus, 1: minus)

```
a = 0111 (+7)
b = 0010 (+2)
________________
a - b = 5 or 0101
1) b to 1st complement: 0010 becomes 1101
2) 1st complement to 2nd complement by add 1 or 1101 + 0001 = 1110
3) a + 2nd complement: 0111 + 1110 = (1)0101 = 5, overflow 1
```

- Multiplication is the addition of the multiplicand by multiplicator times.
- Division is the subtraction of the dividend to the divisor until the Subtraction result is 0 or less than the divisor. The number of subtraction is the quotient and the last subtraction result is the rest (e.g. 12 : 2 yields 6x subtraction and the last result is 0. Quotient = 6, Rest = 0).

In reality we rarely deal with binary operation, but the binary knowledge helps us to derive and to estimate an operation. Addition is the fastest, then Subtraction, then Multiplication and the slowest is Division.

**Back to an Image and Pixel**.

In the past we have to take an image on a film and develop the image into a picture. The image is the negative, and the Picture is the final result. Similar to that, a digital image can be easily "reversed" into a negative by complementing the pixels. A Pixel is an integer or a 4 bytes value. To "negative" a Pixel we have to partition it into 4 bytes as I showed you above and then complement each byte with 255 (or 0xFF):

```
int cyan = 0x00FFFF;
int red = (cyan & 0xFF0000) >> 16;
int green = (cyan & 0xFF00) >> 8;
int blue = cyan & 0xFF
// negative of cyan
int negCyan = ((0xFF - red) << 16) | ((0xFF - green) << 8) | (0xFF -blue);
```

And every image is consisted by width * height pixels (see Pic.1 of the 1st session. The width is the X axis, the height is the Y axis). The negative of an image is then:

```
BufferedImage img = ImageIO.read(new File(imgFile));
int width = img.getWidth();
int height = img.getHeight();
for(int y = 0; y < height; ++y)
for(int x = 0; x < width; ++x) {
int p = img.getRGB(x,y); // get the pixel at location x, y
// negate RGB by subtraction from 255
int a = p & 0xFF000000;
int r = 255 - (p >> 16) & 0xFF;
int g = 255 - (p >> 8) & 0xFF;
int b = 255 - p & 0xFF;
//set new RGB value
img.setRGB(x, y, a | (r << 16) | (g << 8) | b);
}
```

More Click **HERE** (Congdongjava.com)

**Note**:

It's a long tutorial and I have no interest to repeat the whole tutorial here on **Kipalog.com**. If the admins think that my blog is an **ad** then pls. delete it and remove my account from **Kipalog.com**