cancel
Showing results for 
Search instead for 
Did you mean: 

Losing color depth

contact239955_st
Associate II
Posted on February 12, 2018 at 01:45

I've been working on a simple UI library for my project.

I'm using the stm32F7 with LTDC configured to RGB888 color space.

Whilst I was writing a color gradient function, I noticed that my gradients looked 'choppy'

0690X00000604NDQAY.jpg

Left gradient: Dithered RGB888 bitmap

Middle gradient: non-dithered RGB888 bitmap

Right gradient: custom gradient function

My gradient code does a simple loop:

for

(

uint32_t

yPos = y

;

yPos < height

;

yPos++) {

   

LCD

::fillRectangle(x

,

yPos

,

width

,

1

,

LCD

::getGradientColor(yPos

,

height

,

fromColor

,

toColor

,

(

ColorFormat

)

hLtdcHandler

.

LayerCfg

[

0

].

PixelFormat

))

;

}

which calls the getGradientFunction:

uint32_t

LCD

::

getGradientColor

(

uint32_t

current

,

uint32_t

max

,

uint32_t

fromColor

,

uint32_t

toColor) {

   

float

position = (

float

) current / max

;

   

uint8_t

red = (

uint8_t

) (((

1.0

- position) * (fromColor &

0xff0000

>>

16

)) + (position * (toColor &

0xff0000

>>

16

)))

;

   

uint8_t

green = (

uint8_t

) (((

1.0

- position) * (fromColor &

0x00ff00

>>

8

)) + (position * (toColor &

0x00ff00

>>

8

)))

;

   

uint8_t

blue = (

uint8_t

) (((

1.0

- position) * (fromColor &

0x0000ff

)) + (position * (toColor &

0x0000ff

)))

;

   

switch

(

hLtdcHandler

.

LayerCfg

[

0

].

PixelFormat

) {

       

case

LTDC_PIXEL_FORMAT_ARGB8888

:

           

return

((

uint8_t

)

0xFF

<<

24

) | (red <<

16

) | (green <<

8

) | blue

;

       

default

:

       

case

LTDC_PIXEL_FORMAT_RGB565

:

       

case

LTDC_PIXEL_FORMAT_RGB888

:

           

return

(red <<

16

) | (green <<

8

) | blue

;

   

}

}

Based on my calculations, I have a 600px high display and I am drawing a full-height gradient. I expect a different color value every ~2.35 lines (600 lines / 255 grey shades). However, my display shows a color change every ~9 lines.

Does anybody have an idea where I shall start looking for the cause?

I am using DMA to draw the two bitmaps, with the appropriate input color modes for both bitmaps.

For gradient I just use a simple register to memory call for each line.

6 REPLIES 6
AvaTar
Lead
Posted on February 12, 2018 at 07:38

Assuming you have verified your gradient bar code in general, I suggest to draw larger blocks (rectangles) of different/adjacent colors side by side.

Single pixels or lines could be difficult to discern.

And don't forget, color perception is highly subjective in general.

T J
Lead
Posted on February 12, 2018 at 08:15

In this statement;

(fromColor & 0xff0000 >> 16)

I would force the issue;

((fromColor & 0xff0000) >> 16)

Also;

I thought you had to have a break; in every case statement or the code falls through...

    switch (hLtdcHandler.LayerCfg[0].PixelFormat) {

        case LTDC_PIXEL_FORMAT_ARGB8888:

            return ((uint8_t) 0xFF << 24) | (red << 16) | (green << 8) | blue;

        BREAK;

        default:

        case LTDC_PIXEL_FORMAT_RGB565:

        BREAK;

         case LTDC_PIXEL_FORMAT_RGB888:

            return (red << 16) | (green << 8) | blue;

         BREAK;

Posted on February 12, 2018 at 08:33

Thank you for your reply!

Since I am returning within my case statements, there is no need for a break, I let 'default', RGB565 and RGB888 fall through to the same return statement on purpose

Good catch on the bit shifting though! Almost thought that that might've been the cause, but unfortunately nothing changed.

Best wishes,

Posted on February 12, 2018 at 08:36

last stab

      return (uint32_t)((red << 16) | (green << 8) | blue);

or should it be:

      return ((uint32_t)red << 16) | (green << 8) | blue);

can you return within a Case statement ? 

Posted on February 12, 2018 at 08:44

You definitely can! Makes those long chained else/ifs more readable

The returned variable is already an uint32_t, so that wont do anything either

:(

Posted on February 12, 2018 at 08:53

but

red, green, blue are not uint32_t...

just trying to force it...

change the float to a double...

double position = (double) current / max;

((((double)1.0 - position) * (fromColor & 0xff0000 >> 16)) + (position * (toColor & 0xff0000 >> 16)));