Pixel aus Bitmap auslesen



  • Ich versuche, aus einem monochromen Bitmap einzelne Pixel auszulesen.
    Das Bitmap ist dabei kein "echtes" Bitmap, sondern ein "PegBitmap" (Bestandteil eines SDKs).

    struct PegBitmap
    {
        UCHAR uFlags;         // combination of flags listed below
        UCHAR uBitsPix;       // 1, 2, 4, or 8 NOTE: Only 1 is supported in the ClassPad
        WORD  wWidth;         // in pixels
        WORD  wHeight;        // in pixels
        DWORD dTransColor;    // transparent color for >= 8bpp bitmaps
        UCHAR PEGFAR *pStart; // Pointer to bitmap data
    };
    

    Beim SDK liegt ein Programm bei, das mir normale Bitmaps in Code für PegBitmaps umwandelt. Der sieht bei einem 16x2px Bitmap dann z.B. so aus:

    ROMDATA UCHAR uctestBitmap[4] = {
    0x80,0x00,0x00,0x00,};
    PegBitmap gbtestBitmap = { 0x00, 1, 16, 2, 0x000000ff, (UCHAR *) uctestBitmap};
    

    Die Pixel werden anscheinend von oben links aus Zeilenweise eingelesen.

    Mein Versuch, einzelne Pixel auszulesen, sieht so aus:

    bool IsBlack(SIGNED x, SIGNED y, PegBitmap* pbmp)
    {
        WORD width = pbmp->wWidth;
        WORD height = pbmp->wHeight;
        int bpl = (int)ceil(width/8.0);
        if(x>0&&x<width&&y>0&&y<height)
        {
            int ind = y*bpl+(int)ceil(x/8.0);
            if(pbmp->pStart[ind]&(UINT)pow(2,8-(x/8.0-floor(x/8.0))*8.0)!=0)
                  return true;
        }   
        return false; 
    }
    

    Leider funktioniert der nicht so, wie er sollte. An einigen Positionen wird zwar "true" zurückgegeben, aber nicht an den richtigen...

    Sieht da jemand den Fehler? Oder ist das totaler Quatsch, was ich da mache?



  • Also zuerst einmal eine kleine Fehlerkorrektur:

    if(x>=0 && x<width && y>=0 && y<height)
    

    Und für die Indexberechnung benötigt man auch keine float-Umrechnungen:

    int bpl = width/8;
    int ind = y*bpl+x/8;
    
    return (pbmp->pStart[ind] & (1 << (7 - x%8))) != 0;
    

    Die Berechnung ist jetzt ohne Garantie, aber die Herangehensweise ist so richtig...
    Beachte auch die Operatorprioritäten: bei (a & b) != 0 !!!

    Zu den Bitoperationen (&, <<, etc. ) si. http://de.wikipedia.org/wiki/Bitweiser_Operator



  • Danke erstmal!

    Das hat mir schon sehr weitergeholfen, eine Umrechnung brauche ich aber, da das Bild auch eine nicht durch 8 teilbare Breite haben kann.

    So klappts:

    bool IsBlack(SIGNED x, SIGNED y, PegBitmap* pbmp)
    {
        WORD width = pbmp->wWidth;
        WORD height = pbmp->wHeight;
        if(x>=0&&x<width&&y>=0&&y<height)
        {
            int bpl = ceil(width/8.0);
            int ind = y*bpl+x/8;
            if((pbmp->pStart[ind]&(1<<(7-x%8)))!=0)
                  return true;
        }   
        return false; 
    }
    

    Danke!



  • Dann nimm besser

    int bpl = (width+7)/8;
    

    int nach float und dann wieder zurück nach int ist unnötig!

    Edit: hier noch ein Link auf wikipedia (http://de.wikipedia.org/wiki/IEEE_754) wo der Aufbau der Gleitkommatypen beschrieben ist (und warum die Umwandlung nach int nicht ganz trivial ist - auch wenn das der Mathe-Coprozessor übernimmt -)


Anmelden zum Antworten