summaryrefslogtreecommitdiff
path: root/thirdparty/etcpak/BitmapDownsampled.cpp
blob: 0eb0d8118504971d8f9ac843feac009e63f5aa81 (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
#include <string.h>
#include <utility>

#include "BitmapDownsampled.hpp"
#include "Debug.hpp"

BitmapDownsampled::BitmapDownsampled( const Bitmap& bmp, unsigned int lines )
    : Bitmap( bmp, lines )
{
    m_size.x = std::max( 1, bmp.Size().x / 2 );
    m_size.y = std::max( 1, bmp.Size().y / 2 );

    int w = std::max( m_size.x, 4 );
    int h = std::max( m_size.y, 4 );

    DBGPRINT( "Subbitmap " << m_size.x << "x" << m_size.y );

    m_block = m_data = new uint32_t[w*h];

    if( m_size.x < w || m_size.y < h )
    {
        memset( m_data, 0, w*h*sizeof( uint32_t ) );
        m_linesLeft = h / 4;
        unsigned int lines = 0;
        for( int i=0; i<h/4; i++ )
        {
            for( int j=0; j<4; j++ )
            {
                lines++;
                if( lines > m_lines )
                {
                    lines = 0;
                    m_sema.unlock();
                }
            }
        }
        if( lines != 0 )
        {
            m_sema.unlock();
        }
    }
    else
    {
        m_linesLeft = h / 4;
        m_load = std::async( std::launch::async, [this, &bmp, w, h]() mutable
        {
            auto ptr = m_data;
            auto src1 = bmp.Data();
            auto src2 = src1 + bmp.Size().x;
            unsigned int lines = 0;
            for( int i=0; i<h/4; i++ )
            {
                for( int j=0; j<4; j++ )
                {
                    for( int k=0; k<m_size.x; k++ )
                    {
                        int r = ( ( *src1 & 0x000000FF ) + ( *(src1+1) & 0x000000FF ) + ( *src2 & 0x000000FF ) + ( *(src2+1) & 0x000000FF ) ) / 4;
                        int g = ( ( ( *src1 & 0x0000FF00 ) + ( *(src1+1) & 0x0000FF00 ) + ( *src2 & 0x0000FF00 ) + ( *(src2+1) & 0x0000FF00 ) ) / 4 ) & 0x0000FF00;
                        int b = ( ( ( *src1 & 0x00FF0000 ) + ( *(src1+1) & 0x00FF0000 ) + ( *src2 & 0x00FF0000 ) + ( *(src2+1) & 0x00FF0000 ) ) / 4 ) & 0x00FF0000;
                        int a = ( ( ( ( ( *src1 & 0xFF000000 ) >> 8 ) + ( ( *(src1+1) & 0xFF000000 ) >> 8 ) + ( ( *src2 & 0xFF000000 ) >> 8 ) + ( ( *(src2+1) & 0xFF000000 ) >> 8 ) ) / 4 ) & 0x00FF0000 ) << 8;
                        *ptr++ = r | g | b | a;
                        src1 += 2;
                        src2 += 2;
                    }
                    src1 += m_size.x * 2;
                    src2 += m_size.x * 2;
                }
                lines++;
                if( lines >= m_lines )
                {
                    lines = 0;
                    m_sema.unlock();
                }
            }

            if( lines != 0 )
            {
                m_sema.unlock();
            }
        } );
    }
}

BitmapDownsampled::~BitmapDownsampled()
{
}