Avatar billede krismort Nybegynder
28. april 2007 - 00:14 Der er 11 kommentarer

fra 5bit til 8bit farve ?

Hej,
Hvordan konveteres en 5 bit farveværdi tal præsist og hurtigst til en 8 bit farveværdi ?

Indvil viderer laver jeg om til float ala  :
unsigned char farve8bit = ( float(farve5bit) / 32.0f ) * 256.0f;

Jeg har dog på fornemmelsen at denne metode hverken er hurtig eller præsis :/
Avatar billede arne_v Ekspert
28. april 2007 - 01:16 #1
Hvad indeholder de 8 og 5 bit ?
Avatar billede bertelbrander Novice
28. april 2007 - 01:49 #2
Det hurtigste må være:
unsigned char farve8bit = farve5bit << 3;
Avatar billede _on_ Nybegynder
10. maj 2007 - 19:58 #3
Det må være sådan at i et 5 bit system, at alle 5 bit sat betyder fyld styrke på en given grundfarve. Det må så betyde at de 5 bit sat skal være lig med 8 bit sat ved konvertering. Det der må skulle gøres er lineær interpolation mellem disse 2 værdier sådan at regnestykket må være 8bit / 5bit => 255 / 31. Det giver så et decimaltal, som skal afrundes efter udregning for precision, men det tror jeg ikke bliver det store problem idet vore dages computere er hurtige :)
Prøv dette:

unsigned char farve8bit = (float(farve5bit) / 31.0) * 255.0;
Jeg kan ikke huske om der en kommando i C for afrunding, andre end ceil og floor, som enten runder op eller ned, altid.
Go' vind

ON
Avatar billede krismort Nybegynder
10. maj 2007 - 21:19 #4
problemet med at bruge floats er bare floating point præsitions fejl så jeg tror faktisk at det bedste man kan gøre er at benytte det som bertelbrandler har foreslået. Det er osse det jeg er endtlig.
Avatar billede _on_ Nybegynder
10. maj 2007 - 21:32 #5
Ok, det er selvfølgelig rigtigt at en bitskifte operation er hurtigere (i vore dage, vel ikke mere end 1 clockcycle) til gengæld mister du noget præcision i det 5 satte bit skiftet op og lagt i en 8 bit variabel, er stadig kun 5 satte bit, så resultatet vil være 11111000, og det er ikke fuld styrke på en given grundfarve :)
Så jeg forstår ikke helt hvad du mener med præcisionsfejl.

Mvh
ON
Avatar billede krismort Nybegynder
11. maj 2007 - 08:08 #6
floating points er mere eller mindre utilregnelige så de egner sig ikke til noget som skal være præsist. Når du deler 2 tal der ikke går op vil du på forskellige systemer kunne opleve at du for forskellige tal. Og så er der problematikken om der skal rundes op eller ned. Hvis man vælger at runde op så har du problemstillingen omkring 0.5 hvor floating point errors kunne betyde forskellige mellem 0.4999999999 og 0.5.
Avatar billede krismort Nybegynder
11. maj 2007 - 08:12 #7
Du har self. ret i det du skriver og det var osse den første løsning jeg har prøvet mig med. Lurer på om man kunne dele de binære tal med en algoritme.
Avatar billede _on_ Nybegynder
11. maj 2007 - 12:00 #8
Det er muligt, men hvis du er igang med at skrive programmet, tror jeg da nok jeg ville teste begge muligheder, idet min løsning i teorien, og din :), vil kunne gi' en fejl på max. 1(decimal) hvorimod bitskifte 3 pladser altid vil gi' en fejl på 7(decimal).
Li'som dig, har jeg også tænkt på om det var muligt at finde en algoritme hvor resultatet kunne findes ved "bitpilleri", men det går nok hen og blir' en forholdsvis kompliceret algoritme, og så er det spørgsmålet ikke det vil kunne svare sig at anvende floatingpoint. De mest simple floatingpoint instruktioner er hurtige idag (FADD, FSUB, FMUL, FDIV) tager typisk også kun 1 clockcycle. Hvis det er meningen programmet altid skal køre på en maskine med X86 processor (Intel ell. AMD), så var det måske en mulighed at optimere den del af routinen med inline assembler.
Avatar billede _on_ Nybegynder
11. maj 2007 - 15:01 #9
Ups, der er lige indsneget sig en mindre fejl. Fejlen ved bitskifte er ikke ALTID 7, men mellem 0 og 7, ligefrem propertionalt med værdien i din 5bit værdi og forskellen mellem, faktoren 8 og faktoren (255 / 31). I øvrigt, så gir' din formel og bertelbrander's udtryk det samme resultat :)
Men hvis hastighed er det største kriterie, så er bertelbranders udlægning den hurtigste, men faktoren (255 / 31) gir' den største farve nøjagtighed, så det vil selvfølgelig afhænge af hvad kriteriet er for konverteringen, hastighed eller farvenøjagtighed.

Mvh
ON
Avatar billede bertelbrander Novice
11. maj 2007 - 20:43 #10
Man kan måske forbedre "min" metode med:
unsigned char farve8bit = (farve5bit << 3) + 4;
For at "afrunde" i stedet for at trunkere.

Eller lave _on_'s i fixed point:
unsigned char farve8bit = farve5bit * 255 / 31;
Der giver næsten samme resultat, men bør være hurtigere.

Om det har nogen reel betydning er nok tvivlsomt.
Avatar billede arne_v Ekspert
12. maj 2007 - 04:57 #11
med hensyn til "nøjagtighed" så:

#include <stdio.h>
#include <stdlib.h>

int f1(int v)
{
    return (int)(v/32.0f*256.0f);
}

int f2(int v)
{
    return (v << 3);
}

int f3(int v)
{
    return (int)(v/31.0f*255.0f);
}

int f4(int v)
{
    return ((v << 3) + 4);
}

int f5(int v)
{
    return (v*255)/31;
}

void test(char *txt,int (*f)(int v))
{
    int i,v,sum;
    sum = 0;
    for(i=0;i<255;i++)
    {
        v = f(i >> 3);
        if(v < 0 || v > 255)
        {
            printf("error in %s\n",txt);
            return;
        }
        sum += (v-i)*(v-i);
    }
    printf("method=%s var=%d\n",txt,sum);
}

int main()
{
    test("float *32/256",f1);
    test("int >> 3    ",f2);
    test("float *31/255",f3);
    test("int >> 3 + 4 ",f4);
    test("int *255/31  ",f5);
    return 0;
}

method=float *32/256 var=4431
method=int >> 3      var=4431
method=float *31/255 var=2512
method=int >> 3 + 4  var=1399
method=int *255/31  var=2512
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester