summaryrefslogtreecommitdiff
path: root/avstream/avscamera/sys/RGB24Synthesizer.cpp
blob: 89c648bdc994eee57c1cac6606931330a035604a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**************************************************************************

    A/V Stream Camera Sample

    Copyright (c) 2014, Microsoft Corporation.

    File:

        RGB24Synthesizer.cpp

    Abstract:

        This file contains the implementation of CRGB24Synthesizer.
        
        CRGB24Synthesizer is derived from CRGBSynthesizer.  It uses the RGB 
        color space and defines a Commit() function that reformats pixels into 
        the RGB24 format.  RGB24 uses 8 bits per primary and 3 bytes per pixel 
        in a single plane.

    History:

        created 4/14/2014

**************************************************************************/

#include "Common.h"

/**************************************************************************

    LOCKED CODE

**************************************************************************/

#ifdef ALLOC_PRAGMA
#pragma code_seg()
#endif // ALLOC_PRAGMA

_Success_(return > 0)
ULONG
CRGB24Synthesizer::
Commit(
    _Out_writes_bytes_(Size)
    PUCHAR  Buffer,
    _In_    ULONG   Size,
    _In_    ULONG   Stride
)
/*++

Routine Description:

    Copy (and reformat, if necessary) pixels from the internal scratch
    buffer.  If the output format decimates chrominance, do it here.

Arguments:

    Buffer -
        The output buffer to fill.

    Size -
        The size of the output buffer in bytes.

    Stride -
        The length of a row in bytes.

Return Value:

    Number of bytes copied into Buffer.

--*/
{
    //  In case stride isn't initialized.
    if( Stride==0 )
    {
        Stride = m_OutputStride;
    }

    //  These are impossible conditions.
    if( !(  Buffer &&
            m_Buffer &&
            (Size&3)==0 &&      // the rows are dword aligned, so the size must be too.
            Size>3 &&           // there must be room for at least 1 pixel
            (Stride&3)==0 &&    // rows should be DWORD aligned
            Stride>3 &&         // rows should contain at least 1 pixel
            m_Height>0 &&
            m_Width>0
         ) )
    {
        NT_ASSERT(FALSE);
        return 0;
    }

    ULONG   limit = min( Size/Stride, m_Height );
    for( ULONG row=0; row<limit; row++ )
    {
        PDWORD  pSrc = (PDWORD) GetImageLocation( 0, m_FlipVertical ? (m_Height - row -1) : row );
        PUCHAR  pDst = Buffer + (row * Stride);
        ULONG   col  = min( m_Width, Stride/3 );

        while( col )
        {
            //  This optimizes the copy fairly well on most machines.
            if( col>=4 )
            {
                DWORD   P0 = pSrc[0];
                DWORD   P1 = pSrc[1];
                DWORD   P2 = pSrc[2];
                DWORD   P3 = pSrc[3];
                ((PDWORD) pDst)[0] = ((P0      ) & 0x00FFFFFF) | (P1 << 24);
#pragma warning(suppress: 6386) // TODO: Add OACR bug number once known
                ((PDWORD) pDst)[1] = ((P1 >>  8) & 0x0000FFFF) | (P2 << 16);
                ((PDWORD) pDst)[2] = ((P2 >> 16) & 0x000000FF) | (P3 <<  8);
                pDst += 4 * 3;
                pSrc += 4;
                col  -= 4;
            }
            else
            {
                DWORD   P0 = *pSrc++;
                *pDst++ = (UCHAR) (P0);
                *pDst++ = (UCHAR) (P0 >> 8);
                *pDst++ = (UCHAR) (P0 >> 16);
                col--;
            }
        }
    }

    return limit * Stride;
}