0

Can anyone see what the issue is when I try to convert my 8 bit image into an 4 bit image?

I am testing using the 8 bit image found here: http://laurashoe.com/2011/08/09/8-versus-16-bit-what-does-it-really-mean/

You can tell how the 4 bit image should look like but mine is almost purely black.

        // get color of the image and convert to grayscale
        for(int x = 0; x <img.getWidth(); x++) {
            for(int y = 0; y < img.getHeight(); y++) {
                int rgb = img.getRGB(x, y);
                int r = (rgb >> 16) & 0xF;
                int g = (rgb >> 8) & 0xF;
                int b = (rgb & 0xF);

                int grayLevel = (int) (0.299*r+0.587*g+0.114*b);
                int gray = (grayLevel << 16) + (grayLevel << 8) + grayLevel;
                img.setRGB(x,y,gray);
            }
        }
Gimby
  • 5,095
  • 2
  • 35
  • 47
QQCompi
  • 225
  • 4
  • 14
  • Sorry it is rather late and I'm been coding for awhile. Meant to say 8 bit to 4 bit. I changed the title – QQCompi Oct 14 '15 at 11:30
  • Okay but if I see the code then the RGB values you're fetching from the source image are fetched as a regular 24 bits RGB integer anyway. As such I do believe what is shown here is what you're after: http://stackoverflow.com/questions/4801366/convert-rgb-values-into-integer-pixel (the answers also show how to turn an RGB int into individual components, notice the difference with your code). – Gimby Oct 14 '15 at 11:39
  • Did you mean `& 0xFF` instead of `& 0xF`? Your code only gets the lower 4 bits from each component. – Cinnam Oct 14 '15 at 11:41
  • Right so if I have the full 24 bits, wouldnt i want to truncate it so I only get the last 4 bits? – QQCompi Oct 14 '15 at 11:46
  • If you get the last 4 bits, then `0xF0` becomes `0x0`, which I assume is not what you want. You could take the upper 4 bits by shifting by another 4: `int r = (rgb >> 20) & 0xF;` etc. – Cinnam Oct 14 '15 at 11:52
  • @Cinnam Brilliant! Works like a charm! – QQCompi Oct 14 '15 at 12:02
  • Why did you edit out the code? Now the question is completely useless... – Harald K Oct 14 '15 at 12:29
  • I went ahead and rolled back the last edit so the code is back. – Gimby Oct 14 '15 at 20:56

3 Answers3

0

You should use 0xFF not 0xF,as 0xF means only last four bits, wchich will tell you almost nothing about the color, since in RGB an color is 8 bit.

try if this work:

 // get color of the image and convert to grayscale
        for(int x = 0; x <img.getWidth(); x++) {
            for(int y = 0; y < img.getHeight(); y++) {
                int rgb = img.getRGB(x, y);
                int r = (rgb >> 16) & 0xFF;
                int g = (rgb >> 8) & 0xFF;
                int b = (rgb & 0xFF);

                int grayLevel = (int) (0.299*r+0.587*g+0.114*b);
                int gray = (grayLevel << 16) + (grayLevel << 8) + grayLevel;
                img.setRGB(x,y,gray);
            }
        }
Krzysztof Cichocki
  • 6,294
  • 1
  • 16
  • 32
0

Since the code has been edited out from the question, here it is with the confirmed solution from the comments:

// get color of the image and convert to grayscale
for(int x = 0; x <img.getWidth(); x++) {
    for(int y = 0; y < img.getHeight(); y++) {
        int rgb = img.getRGB(x, y);

        // get the upper 4 bits from each color component
        int r = (rgb >> 20) & 0xF;
        int g = (rgb >> 12) & 0xF;
        int b = (rgb >> 4) & 0xF;

        int grayLevel = (int) (0.299*r+0.587*g+0.114*b);

        // use grayLevel value as the upper 4 bits of each color component of the new color
        int gray = (grayLevel << 20) + (grayLevel << 12) + (grayLevel << 4);
        img.setRGB(x,y,gray);
    }
}

Note that the resulting image only looks like 4-bit grayscale, but still uses int as the RGB value.

Cinnam
  • 1,892
  • 1
  • 15
  • 23
0

8 bit image values are in range [0, 255] because pow(2, 8) = 256

To get 4 bit image values which will be in range [0, 15] as pow(2, 4) = 16, we need to divide each pixel value by 16 -> range [0, 255] / 16 = range [0, 15].

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("crowd.jpeg")
#Convert the image to grayscale
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.imshow(gray_img, cmap='gray')

Grayscale image

bit_4 = np.divide(gray_img, 16).astype('uint8')
plt.imshow(bit_4, cmap='gray')

Bit4 image

CVRP_2021
  • 31
  • 3