English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 10 February 2021, 01:08   #1
DanScott
Lemon. / Core Design
 
DanScott's Avatar
 
Join Date: Mar 2016
Location: Tier 5
Posts: 1,213
Converting 8bit colour components to 4bit

How do YOU do it?

I guess the simplest way is to >> 4

But... then $EF as an 8 bit component is closer to $F (as a 4bit) than it is to $E

I know that when converying from 4bit to 8bit, the general concensus is to use $xyz -> $xxyyzz (ie. $4C3 would become $44CC33), but going back the other way there are issues perhaps ?
DanScott is offline  
Old 10 February 2021, 01:15   #2
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,430
I've done this in code just once so far, but I did indeed just do >> 4 in my script. But reading your post, I'm now thinking about using a floating point divide and rounding that instead. This would be more accurate, after all.

However, there may be better ways yet. Perhaps some sort of perceptual conversion where the conversion keeps in mind that human eyes don't really do linear colour might even be a neat trick. Don't have an algorithm at the ready, but common wisdom has it that our eyes are more sensitive to green than any other colour so perhaps rounding green up and the rest down might do the trick?

Then again, perhaps a simple linear conversion is best after all. Might test that out for fun.
roondar is offline  
Old 10 February 2021, 01:19   #3
DanScott
Lemon. / Core Design
 
DanScott's Avatar
 
Join Date: Mar 2016
Location: Tier 5
Posts: 1,213
Yes, probably rounding each component up or down to the nearest $X0 value?

So $E7 would round to $E0, and $E8 to $F0


I know some people swear by dividing each component by 17 (as going from 4bit to 8bit, you do the equivalent of a multiply by 17).. but then this has issues where (for example) $FFFFFF is the only 8bit RGB value that would generate $FFF as a 4bit colour value
DanScott is offline  
Old 10 February 2021, 01:31   #4
Jobbo
Registered User
 
Jobbo's Avatar
 
Join Date: Jun 2020
Location: Druidia
Posts: 389
I'm sure you've though of this but you could go with:

fourbit = (eightbit + 8) / 17
Jobbo is offline  
Old 10 February 2021, 02:25   #5
orangespider
Registered User
 
Join Date: Feb 2021
Location: Becej / Serbia
Posts: 120
This really depends on what you want to accomplish.

The mathematically most perfect solution is the one written above (y = (x + 8) div 17), however in that solution you will get less white and black pixels than any other color. You will end up with 9 8bit colors being remapped to black and white and 17 colors being remapped to the rest.

The fastest approach with >> 4 will give you less precise colors, but every single 4bit value will have 16 corresponding 8bit values so the actual output might look better.

Alternatively you can use pattern dithering with (x+d) div 17 where the d values can be taken from this table:
1, 9, 3, 11
13, 5, 15, 7
4, 12, 2, 10
16, 8, 14, 6
It's pretty straightforward since you can just use (x and 3) and (y and 3) to get the values from the dither table. note: The dither table starts from 1 instead of 0 because this way the average we get is 8.5 which is pretty good for average rounding.

If you don't want the div, you can go with y = ((x << 4) - x + d) >> 8, just need to scale the dither table up (or just use a constant d=128 for rounding).
orangespider is offline  
Old 10 February 2021, 23:27   #6
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,483
Quote:
Originally Posted by DanScott View Post
Yes, probably rounding each component up or down to the nearest $X0 value?

So $E7 would round to $E0, and $E8 to $F0


I know some people swear by dividing each component by 17 (as going from 4bit to 8bit, you do the equivalent of a multiply by 17).. but then this has issues where (for example) $FFFFFF is the only 8bit RGB value that would generate $FFF as a 4bit colour value
Hi Dan, I faced a similar problem (an effect in ham for 'vertical copper').
And my reasoning was to use code that would allow me to reverse the duplication of the nibble when doing RGB4 to RGB8.

So I used the central RGB8 color and 'draw around' it an area using it as a pivot.
This give me usually 8+1+8 values (excluding the reduced extremes and a different negligible point at 8).

Visually:
Code:
      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00   00 00 00 00 00 00 00 00  01 01 01 01 01 01 01 01                   
10   01 01 01 01 01 01 01 01  01 02 02 02 02 02 02 02                   
20   02 02 02 02 02 02 02 02  02 02 03 03 03 03 03 03                   
30   03 03 03 03 03 03 03 03  03 03 03 04 04 04 04 04                   
40   04 04 04 04 04 04 04 04  04 04 04 04 05 05 05 05                   
50   05 05 05 05 05 05 05 05  05 05 05 05 05 06 06 06                   
60   06 06 06 06 06 06 06 06  06 06 06 06 06 06 07 07                   
70   07 07 07 07 07 07 07 07  07 07 07 07 07 07 07 08                   
80   08 08 08 08 08 08 08 08  08 08 08 08 08 08 08 08                   
90   08 09 09 09 09 09 09 09  09 09 09 09 09 09 09 09                   
A0   09 09 0A 0A 0A 0A 0A 0A  0A 0A 0A 0A 0A 0A 0A 0A                   
B0   0A 0A 0A 0B 0B 0B 0B 0B  0B 0B 0B 0B 0B 0B 0B 0B                   
C0   0B 0B 0B 0B 0C 0C 0C 0C  0C 0C 0C 0C 0C 0C 0C 0C                   
D0   0C 0C 0C 0C 0C 0D 0D 0D  0D 0D 0D 0D 0D 0D 0D 0D                   
E0   0D 0D 0D 0D 0D 0D 0E 0E  0E 0E 0E 0E 0E 0E 0E 0E                   
F0   0E 0E 0E 0E 0E 0E 0E 0F  0F 0F 0F 0F 0F 0F 0F 0F
Code (input and output in d0):
Code:
    move.b  d0,d1
    lsr.b   #4,d1
    sub.b   d1,d0
    addq.b  #8,d0
    lsr.b   #4,d0
In this way I don't preclude myself or crush too much on the black and white colors like other methods.

I have no idea if there is a similar accepted algorithm in the literature, but it is as simple, fast and correct (for me) .
ross is offline  
Old 10 February 2021, 23:44   #7
DanScott
Lemon. / Core Design
 
DanScott's Avatar
 
Join Date: Mar 2016
Location: Tier 5
Posts: 1,213
Yeah, I like that one Ross!! Remaps a good range of pure black and pure white

it's a conundrum that's plagued my mind for a long time

So simple from 4bit -> 8bit, but so many ways going back the other way, which to all intents and purposes, will never be entirely correct. I guess it's how it looks visually, that's the only way to determine what method will give the best results.
DanScott is offline  
Old 19 February 2021, 15:08   #8
Photon
Moderator
 
Photon's Avatar
 
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,647
Range is 15 vs 255, not 16 vs 256, so just shifting will make all colors but 255 darker. (E.g. $1f -> $1)

Rounding will make bright colors darker, dark colors brighter, and be kind of randomly all right in the middle. (E.g. $12 -> $2)

$11, $22, and so on compensates for 15/16 by multiplying by 17. It's pretty close (99.61%). This spreads out the range of 15 evenly across 255.

So the correct color going the other way for $1 is $11, not $18 or $17 (rounding). It must be spread out. (Rounding must be done w/r to 17, not 16.)

So the correct color reduction is divide (rounded) by 17. This can be done with a 256-byte LUT (or a 128 byte one if you want to shuffle nibbles around ) generated with addq.w #8,d0;divu #17,d0.

Last edited by Photon; 19 February 2021 at 15:14.
Photon is offline  
Old 19 February 2021, 20:13   #9
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 3,292
You don't need a division. As posted earlier, y = ((x << 4) - x + d) >> 8 for all 8 bit numbers. Try to proof this (Hint: Neumann series).
Thomas Richter is offline  
Old 19 February 2021, 20:49   #10
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,050
These are not equal in all 3 cases (columns are i, round(i/17.0), (i-(i>>4)+8)>>4, ((i<<4)-i+128)>>8):
Code:
08: 00 01 00 *
19: 01 02 01 *
2a: 02 03 02 *
3b: 03 04 03 *
4c: 04 05 04 *
5d: 05 06 05 *
6e: 06 07 06 *
7f: 07 08 07 *
91: 09 09 08 *
a2: 0a 0a 09 *
b3: 0b 0b 0a *
c4: 0c 0c 0b *
d5: 0d 0d 0c *
e6: 0e 0e 0d *
f7: 0f 0f 0e *
a/b is offline  
Old 19 February 2021, 21:18   #11
Photon
Moderator
 
Photon's Avatar
 
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,647
Well, I have answered the question asked.
Photon is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Painting components for Amiga Signman support.Other 0 10 October 2019 02:39
A4000 components slk486 support.Hardware 26 04 May 2010 20:09
Wanted: A500 components Specksynder MarketPlace 0 30 October 2009 16:18
wanted minimig components jimbob005 MarketPlace 1 20 June 2008 17:17
Help converting an 8bit ISA slot to 16bit ISA slot Smiley support.Hardware 4 25 April 2006 11:20

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 17:28.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.14804 seconds with 15 queries