# [Pixman] [RFC] mmx: add and use expand_4xpacked565

Matt Turner mattst88 at gmail.com
Fri May 18 07:25:24 PDT 2012

```On Thu, May 17, 2012 at 8:05 PM, Bill Spitzak <spitzak at gmail.com> wrote:
> Also this original one:
>
>
>  R8 = ( R5 * 527 + 23 ) >> 6;
>
> produces the same results as the floor(i*255/31.0+.5) result.
>
> I believe almost *all* graphics software will do the bit-shifting math and
> thus the (i*33)>>2 result is the one to use.
>
>
> Bill Spitzak wrote:
>>
>>
>>
>> Søren Sandmann wrote:
>>>
>>> Søren Sandmann <sandmann at cs.au.dk> writes:
>>>
>>>>> Given a pixel with only the red component of these values, the results
>>>>> are off-by-one.
>>>>>
>>>>> 0x03 -> 0x19 (0x18)
>>>>> 0x07 -> 0x3A (0x39)
>>>>> 0x18 -> 0xC5 (0xC6)
>>>>> 0x1C -> 0xE6 (0xE7)
>>>>>
>>>>> (Same for blue, and green has many more cases)
>>>>>
>>>>> It uses
>>>>> R8 = ( R5 * 527 + 23 ) >> 6;
>>>>> G8 = ( G6 * 259 + 33 ) >> 6;
>>>>> B8 = ( B5 * 527 + 23 ) >> 6;
>>>>>
>>>>> I don't guess there's a way to tweak this to produce the same results
>>>>> we get from expand565, is there?
>>>>
>>>> Maybe I'm missing something, but this certainly produces the correct
>>>> result:
>>>>
>>>>    r8 = (r5 * 8 + r5 / 4) = r5 * (8 + 0.25) = r5 * (32 + 1) / 4        =
>>>> (r5 * 33) >> 2
>>>
>>>
>>> I should maybe expand a bit more on this: Pixman uses bit replication
>>> when it goes from lower bit depths to higher ones. That is, a five bit
>>> value:
>>>
>>>        abcdef
>>>
>>> is expanded to
>>>        abcdefabc
>>>
>>> which corresponds to a left-shifting r5 by 3 and adding r5 right-shifted
>>> by 2. This is the computation that is turned into a multiplication and a
>>> shift in the formula above.
>>>
>>> A more correct way to expand would be
>>>
>>>        floor ((r5 / 31.0) * 255.0 + 0.5)
>>>
>>> but this is fairly expensive (although it can be done with integer
>>> arithmetic and without divisions, and may actually be equivalent to your
>>> formula -- I haven't checked).
>>
>>
>> for i in range(0,32):
>>  print i,int((i*33)/4),int(i*255/31.0+.5)
>>
>> 0 0 0
>> 1 8 8
>> 2 16 16
>> 3 24 25 *
>> 4 33 33
>> 5 41 41
>> 6 49 49
>> 7 57 58 *
>> 8 66 66
>> 9 74 74
>> 10 82 82
>> 11 90 90
>> 12 99 99
>> 13 107 107
>> 14 115 115
>> 15 123 123
>> 16 132 132
>> 17 140 140
>> 18 148 148
>> 19 156 156
>> 20 165 165
>> 21 173 173
>> 22 181 181
>> 23 189 189
>> 24 198 197 *
>> 25 206 206
>> 26 214 214
>> 27 222 222
>> 28 231 230 *
>> 29 239 239
>> 30 247 247
>> 31 255 255
>>
>> Asterix marks the examples where these are unequal.

Very cool. Thanks for the analysis. Indeed, those marked with
asterisks match what I found.

Thanks,
Matt
```