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++;
}
}
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
}
}
April
2002 - Dirk Schäfer - MD-Mathematische Dienste GmbH |