2

According to my question for RGB888 to RGB565, I would like to do RGB565 to RGB888, here is my testing code, however I got stuck on convert to RGB888 byte array.

import numpy as np
np.random.seed(42)
im = np.random.randint(0,256,(1,4,2), dtype=np.uint8)

# >>> im.nbytes
# 8
# >>> im
# array([[[102, 220],
#        [225,  95],
#        [179,  61],
#        [234, 203]]], dtype=uint8)

# Make components of RGB888
R8 = (im[...,0] & 0xF8).astype(np.uint32) << 8
G8 = (im[...,0] & 0x07).astype(np.uint32) << 5 | (im[...,1] & 0xE0).astype(np.uint32)
B8 = (im[...,1] & 0x1F).astype(np.uint32)
RGB888 = R8 | G8 | B8

# >>> RGB888.nbytes
# 16 <= here I think it should be 12 (4x3 bytes)

# >>> RGB888.reshape(1, 4, 3)
# Traceback (most recent call last):
#   File "<input>", line 1, in <module>
# ValueError: cannot reshape array of size 4 into shape (1,4,3)

When I use astype(np.uint16), some values become 0 because it need larger data type to store, that's why I use unit32 on above code.

I know unit32 will make above code's RGB888 size to be 16, so I would like to ask if any other correct way to transfer RGB565 to RGB888?

2
  • 1
    You should start from a 2-dimensional np.uint16 array where each element corresponds to a single packed pixel. Commented May 15, 2020 at 9:55
  • As @AKX says, RGB565 is naturally a uint16 type, so it would make more sense to start with that. Commented May 15, 2020 at 9:59

1 Answer 1

5

Something like this should get you from RGB565 uint16 to three uint8 channel arrays, which you can then dstack into a single 3-dimensional RGB image:

import numpy as np
np.random.seed(42)
im = np.random.randint(0,65536,(4,4), dtype=np.uint16)

MASK5 = 0b011111
MASK6 = 0b111111

# TODO: BGR or RGB? Who knows!
b = (im & MASK5) << 3
g = ((im >> 5) & MASK6) << 2
r = ((im >> (5 + 6)) & MASK5) << 3

# Compose into one 3-dimensional matrix of 8-bit integers
rgb = np.dstack((r,g,b)).astype(np.uint8)

EDIT: to convert an W x H x 2 array of uint8s into a W x H array of uint16s,

import numpy as np
np.random.seed(42)
im = np.random.randint(0,256,(4,4,2), dtype=np.uint8)

b1 = im[:,:,0].astype(np.uint16)
b2 = im[:,:,1].astype(np.uint16)
im = (b1 << 8 | b2)

You may need to swap b1 and b2 around depending on the endianness of your source array.

Sign up to request clarification or add additional context in comments.

8 Comments

You can stack with RGB = np.dstack((r,g,b)) :-)
Cheers Mark :) Adding that in. (Funny that stack's documentation doesn't link to dstack...)
OP may also need .astype(np.uint8) tacked on the end, since we started with np.uint16.
@MarkSetchell Yup, fair point (though I'm sure OP'd notice sooner rather than later! :-D )
@MarkSetchell Seeing as split already had see-alsos for the variants, I figured why not make a PR to fix the docs :) github.com/numpy/numpy/pull/16249
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.