Bayer-Pattern zu RGB

C-Implementierung

//////////////////////////////////////////////////////
//
// Bayer2RGB
//
// konvertiert Bayer-Pattern zu RGB
// 
// pGray und pColor sind BYTE* der Bilddaten
// iGrayStep und iColorStep sind Anzahl Bytes pro Zeile
// width und height sind Breite/Höhe
//
// bRow gibt an, ob das Bild in einer Spalte mit rot oder grün
// oder in einer Spalte mit grün oder blau startet
//
// bCol gibt an, ob das Bild in einer Reihe mit blau oder nicht startet
//
// Bayer-Pattern
//
// RGRGRGRG
// GBGBGBGB
// RGRGRGRG
//
// Startmöglichkeiten
//
// mit R in Reihe ohne B, wie oben dargestellt
// mit G in Reihe ohne B, wie oben aber in der 2 Spalte
// mit G in Reihe mit B, wie oben aber in der zweiten Zeile
// mit B, wie oben, aber in der 2. Spalte und der 2. Zeile
//
// Möglich wäre also das Verschieben des Zeigers, anfangen
// in der 1. oder 2. Spalte, und der 1. oder 2. Zeile
//
// um keine Pixel zu verlieren, starte ich rowCount und colCount
// mit 0 oder 1, je nach bRow und bCol
//
//
void Bayer2RGB( BYTE *pGray, int iGrayStep, BYTE *pColor, int iColorStep,
                           int width, int height, BOOL bCol, BOOL bRow)
{
        int i,j;
        int rowCount, colCount;

        // mit welcher Farbmaske starten ?
        if( bCol == TRUE )
                colCount= 1;
        else
                colCount= 0;

        if( bRow == TRUE )
                rowCount= 1;
        else
                rowCount= 0;

        // und los
        for( i=1; i< height-1; i++)
        {
                // Spaltenzähler setzen
                if( (rowCount%2) == 0 )
                        colCount= 0;
                else
                        colCount= 1;

                // Zeiger holen
                BYTE *pdest= pColor+(i*iColorStep);

                // Source-Zeiger, wie Matrix
                // 11, 12, 13
                // 21, 22, 23
                // 31, 32, 33
                BYTE *psrc11= pGray+( (i-1)*iGrayStep); 
                BYTE *psrc12= pGray+( (i-1)*iGrayStep+1); 
                BYTE *psrc13= pGray+( (i-1)*iGrayStep+2); 

                BYTE *psrc21= pGray+( i*iGrayStep); 
                BYTE *psrc22= pGray+( i*iGrayStep+1); 
                BYTE *psrc23= pGray+( i*iGrayStep+2); 

                BYTE *psrc31= pGray+( (i+1)*iGrayStep); 
                BYTE *psrc32= pGray+( (i+1)*iGrayStep+1); 
                BYTE *psrc33= pGray+( (i+1)*iGrayStep+2); 

                for( j=1; j< width-1; j++)
                {
                        // Rot
                        if( (colCount%2) == 0 && (rowCount%2) == 0 )
                        {
                                // Blau. Grün, Rot im Speicher
                                *pdest= ( *psrc11+*psrc13+*psrc31+*psrc33)>>2;
                                pdest++;
                                *pdest= (*psrc12+*psrc21+*psrc23+*psrc32)>>2;
                                pdest++;
                                *pdest= *psrc22;
                                pdest++;
                        }

                        // Grünn in Reihe ohne Blau
                        if( (colCount%2) == 1 && (rowCount%2) == 0 )
                        {
                                // Blau. Grün, Rot im Speicher
                                *pdest= (*psrc12+*psrc32)>>1;
                                pdest++;
                                *pdest= *psrc22;
                                pdest++;
                                *pdest= (*psrc21+*psrc23)>>1;
                                pdest++;
                        }

                        // Grünn in Reihe mit Blau
                        if( (colCount%2) == 1 && (rowCount%2) == 1 )
                        {
                                
                                // Blau. Grün, Rot im Speicher
                                *pdest= (*psrc21+*psrc23)>>1;
                                pdest++;
                                *pdest= *psrc22;
                                pdest++;
                                *pdest= (*psrc12+*psrc32)>>1;
                                pdest++;
                        }

                        // Blau
                        if( (colCount%2) == 0 && (rowCount%2) == 1 )
                        {
                                // Blau. Grün, Rot im Speicher
                                *pdest= *psrc22;
                                pdest++;
                                *pdest= (*psrc12+*psrc21+*psrc23+*psrc32)>>2;
                                pdest++;
                                *pdest= (*psrc11+*psrc13+*psrc31+*psrc33)>>2;
                                pdest++;
                        }

                        psrc11++;
                        psrc12++;
                        psrc13++;

                        psrc21++;
                        psrc22++;
                        psrc23++;
                        
                        psrc31++;
                        psrc32++;
                        psrc33++;

                        colCount++;
                }

                // Zeilenzähler
                rowCount++;
        }
}


... zum Seiten-Anfang
Assembler-Implementierung
void Bayer2RGB( BYTE *pGray, int iGrayStep, BYTE *pColor, int iColorStep,
                           int width, int height, BOOL bCol, BOOL bRow)
{

        width -= 2;
        width >>= 1;    // an jeder 2. Stelle ein DWORD einlesen
        height -= 2;
        height >>= 1;

        // auf 1. Pixel in 2. Zeile setzen
        pColor= pColor + iColorStep;

        __asm
        {
                xor eax, eax            
                xor ebx, ebx            
                mov eax, height         ; Anzahl Zeilen
                mov ebx, width          ; Anzahl Spalten

                ; Adressen speichern
                mov ecx, pGray          ; Source in ecx
                mov edx, pColor         ; Dest in edx
                
                mov esi, ecx
                mov edi, edx

                outer_loop:

                        xor ebx, ebx
                        mov ebx, width  ; Anzahl Spalten
                        inner_loop:

                                movd mm0, [esi]         ; DWORD einlesen

                                add esi, iGrayStep      ; nächste Zeile
                                movd mm1, [esi]
                                
                                add esi, iGrayStep
                                movd mm2, [esi]

                                punpcklbw mm3, mm0      ; entpacken
                                punpcklbw mm4, mm1
                                punpcklbw mm5, mm2
                                psrlw mm3, 8            ; Bytes schieben, oberes Byte danach 0
                                psrlw mm4, 8
                                psrlw mm5, 8

                                paddw mm5, mm3          ; addieren
                                psrlw mm5, 1            ; durch 2 teilen

                                movq mm6, mm4           ; kopieren
                                psrlq mm6, 32           ;das ganze Register schieben
                                paddw mm6, mm4          ; addieren
                                psrlw mm6, 1            ; durch 2 teilen

                                movq mm7, mm5           ;mm5 holen
                                psrlq mm7, 32           ; 2 Words raus
                                paddw mm7, mm5          ; addieren
                                psrlw mm7, 1            ; teilen

                                movq mm0, mm5
                                psrlq mm0, 16
                                paddw mm0, mm6
                                psrlw mm0, 1

                                ; anordnen
                                psllq mm0, 56
                                psrlq mm0, 48
                                paddw mm4, mm0
                                psllq mm5, 48
                                psrlq mm5, 24
                                paddw mm4, mm5
                                psrlq mm6, 8
                                psllq mm6, 32
                                paddw mm4, mm6

                                psrlq mm4, 8
                                psllq mm4, 8

                                psllq mm7, 56
                                psrlq mm7, 56

                                paddw mm4, mm7

                                ; 8 Byte schreiben
                                movq [edi], mm4

                                add edi, 6

                                ; Zeiger zurück
                                sub esi, iGrayStep
                                sub esi, iGrayStep
                                add esi, 2

                                ; innere Schleife Ende?
                                dec ebx
                                cmp ebx, 0
                                jg inner_loop

                                ;Zeiger erhöhen
                                add ecx, iGrayStep
                                mov esi, ecx
                                add edx, iColorStep
                                mov edi, edx

                        ;innere Schleife für nächste Zeile nochmal      
                        xor ebx, ebx
                        mov ebx, width                  ; Anzahl Spalten
                        inner_loop2:

                                movd mm0, [esi]         ; DWORD einlesen
                                
                                add esi, iGrayStep
                                movd mm1, [esi]
        
                                add esi, iGrayStep
                                movd mm2, [esi]
                                
                                punpcklbw mm3, mm0      ; entpacken
                                punpcklbw mm4, mm1
                                punpcklbw mm5, mm2
                                psrlw mm3, 8            ; Bytes schieben, oberes Byte danach 0
                                psrlw mm4, 8
                                psrlw mm5, 8

                                paddw mm5, mm3          ; addieren
                                psrlw mm5, 1            ; durch 2 teilen

                                movq mm6, mm4           ; kopieren
                                psrlq mm6, 32           ;das ganze Register schieben
                                paddw mm6, mm4          ; addieren
                                psrlw mm6, 1            ; durch 2 teilen

                                movq mm7, mm5           ;mm5 holen
                                psrlq mm7, 32           ; 2 Words raus
                                paddw mm7, mm5          ; addieren
                                psrlw mm7, 1            ; teilen

                                movq mm0, mm5
                                psrlq mm0, 16
                                paddw mm0, mm6
                                psrlw mm0, 1

                                ; packen
                                psllq mm4, 16
                                psrlq mm4, 24
                                psrlq mm0, 8
                                psllq mm0, 24
                                psrlq mm7, 8
                                psllq mm7, 32
                                psllq mm6, 54
                                psrlq mm6, 54
                                psllq mm5, 32
                                psrlq mm5, 40
                                psllq mm5, 8

                                paddw mm4, mm7
                                paddw mm4, mm6
                                paddw mm4, mm5
                                paddw mm4, mm0

                                movq [edi], mm4

                                add edi, 6

                                ; Zeiger zurück
                                sub esi, iGrayStep
                                sub esi, iGrayStep

                                add esi, 2

                                ; zweite innere Schleife Ende?
                                dec ebx
                                cmp ebx, 0
                                jg inner_loop2

                                ;Zeiger erhöhen
                                add ecx, iGrayStep
                                mov esi, ecx
                                add edx, iColorStep
                                mov edi, edx

                        ; äußere Schleife Ende?

                        dec eax
                        cmp eax, 0
                        jg outer_loop

                ; MMX aufräumen
                emms
        }
}
... zum Seiten-Anfang
April 2002 - Dirk Schäfer - MD-Mathematische Dienste GmbH