-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[stm32f4-ltdc] this fixes ltdc_get_rgb888_from_rgb565 return value type #682
Conversation
It does not seems to work, for example if blue is 31: (31 << 8) / 31 = 256, that's too much by 1. |
include/libopencm3/stm32/f4/ltdc.h
Outdated
return (uint16_t) ( | ||
(((((rgb888 & 0xFF0000) >> 16)*31) << (11-8)) & 0xF800) | ||
| (((((rgb888 & 0x00FF00) >> 8)*63) >> (8-5) ) & 0x07E0) | ||
| (((((rgb888 & 0x0000FF) >> 0)*31) >> (8-0) ) & 0x001F) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems a bit like you are moving the bits more than needed, have you tried something like
return (uint16_t)(
((rgb888 & 0xf80000) >> 16) | /* grab upper 5 bits of red)
((rgb888 & 0xfc00) >> 5) | /* grab 6 bits of green */
((rgb888 & 0xf8) >> 3); /* grab 5 bits of blue */
);
okay, I did some simulation for possible conversion functions in python def rgb888_from_rgb565_old(rgb565) :
return (((((rgb565) & 0xF800) >> (11-8))/31)<<16) \
| (((((rgb565) & 0x07E0) << (8-5))/63)<<8) \
| (((((rgb565) & 0x001F) << (8-0))/31)<<0)
def rgb888_from_rgb565_standard(rgb565) :
return (((((rgb565 & 0xF800) >> 11) * 255 + 15) / 31) << 16) \
| (((((rgb565 & 0x07E0) >> 5) * 255 + 31) / 63) << 8) \
| (((((rgb565 & 0x001F) >> 0) * 255 + 15) / 31) << 0)
def rgb888_from_rgb565_simplest(rgb565) :
return ((rgb565 & 0xF800) << (16 - 11 + 8 - 5)) \
| ((rgb565 & 0x07E0) << (8 - 5 + 8 - 6)) \
| ((rgb565 & 0x001F) << (0 - 0 + 8 - 5))
def rgb888_from_rgb565_old_fixed(rgb565) :
r = ((((rgb565) & 0xF800) >> (11-8))/31)
g = ((((rgb565) & 0x07E0) << (8-5))/63)
b = ((((rgb565) & 0x001F) << (8-0))/31)
if (r==256) : r = 255;
if (g==256) : g = 255;
if (b==256) : b = 255;
return (r<<16) | (g<<8) | b
def rgb565_from_rgb888_simplest(rgb888) :
return ((rgb888 & 0xf80000) >> (16 - 11 + (8-5))) \
| ((rgb888 & 0x00fc00) >> (8 - 5 + (8-6))) \
| ((rgb888 & 0x0000f8) >> (0 - 0 + (8-5)))
def test_conversion(rgb565) :
print "##################################################"
print "conversion of 0x%04X" %rgb565
print "0x%06X old" %rgb888_from_rgb565_old(rgb565)
print "0x%06X standard" %rgb888_from_rgb565_standard(rgb565)
print "0x%06X simplest" %rgb888_from_rgb565_simplest(rgb565)
print "0x%06X old fixed" %rgb888_from_rgb565_old_fixed(rgb565)
print
rgb888 = rgb888_from_rgb565_standard(rgb565)
print "conversion of 0x%06X" %rgb888
print "0x%04X simplest" %rgb565_from_rgb888_simplest(rgb888)
print
# run tests
test_conversion(0x01ad)
test_conversion(0)
test_conversion(0xffff) results :
the fixed PR uses |
include/libopencm3/stm32/f4/ltdc.h
Outdated
return (r<<16) | (g<<8) | b; | ||
} | ||
/** | ||
* widely used conversion formula for rgb888-to-rgb565 conversion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to or from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ups, i meant from
this function could be dropped to avoid confusion
Is it immediately clear to the user what they should use in all cases? Would it perhaps make more sense to drop these from the headers and include them in some example code instead? Where it can be more clear what version you're using where and why? |
Set the color key Use case 1 - Select a color-key in rgb565
Use case 2 - Select a color-key in rgb888
When a user wants to convert between color formats, he needs to use the same conversion the hardware does otherwise he will be in trouble. If there is a simpler way to do this than using the provided, I am open to suggestions :). (Drawing a single pixel buffer or so using DMA2D seems like an overkill to me, but in general a conversion done by the hardware itself would be appreciated..) |
- also added ltdc_get_rgb565_from_rgb888, conversion in other direction
was anything wrong with this? I realise it fell through the floor, I've never had any devices with screens to even try this, but it doesn't look like anythign was actually wrong with this? |
Ups.. I did some spring cleaning and did not realise this was still open.. |
... and adds ltdc_get_rgb565_from_rgb888
This small fix renames the misleading rgb888 argument to rgb565 and changes the return value type to uint32_t since 3*8 bits do not fit into 16 bits.
Additionally I added the opposite function.
(This bug was probably introduced during the conversion from macro to static inline..)