Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
490 theseven 1
//
2
//
3
//    Copyright 2011 TheSeven
4
//
5
//
6
//    This file is part of emCORE.
7
//
8
//    emCORE is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emCORE is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "emcorelib.h"
25
#include "dither.h"
26
 
27
 
28
static void dither_slow(int width, int height, void* inbuf, int inx, int iny, int instride,
29
                        void* outbuf, int outx, int outy, int outstride)
30
{
31
    int bpp = lcd_get_bytes_per_pixel();
32
    int bits = lcd_get_format();
33
    int swap = bits & BIT(30);
34
    int rwidth = MAX(7, bits & BITRANGE(0, 3));
35
    int gwidth = MAX(7, bits & BITRANGE(10, 13));
36
    int bwidth = MAX(7, bits & BITRANGE(20, 23));
37
    int rshift = bits & BITRANGE(4, 9);
38
    int gshift = bits & BITRANGE(14, 19);
39
    int bshift = bits & BITRANGE(24, 29);
40
    int roffs = 1 << (6 - rwidth);
41
    int goffs = 1 << (6 - gwidth);
42
    int boffs = 1 << (6 - bwidth);
43
    int rmask = BITRANGE(7 - rwidth, 7);
44
    int gmask = BITRANGE(7 - gwidth, 7);
45
    int bmask = BITRANGE(7 - bwidth, 7);
46
    int rclip = 7 - rshift;
47
    int gclip = 7 - gshift;
48
    int bclip = 7 - bshift;
49
    char* in = ((char*)inbuf) + (instride * iny + inx) * 3;
50
    char* out = ((char*)outbuf) + (instride * iny + inx) * bpp;
51
    int x, y;
52
    for (y = 0; y < height; y++)
53
    {
54
        for (x = 0; x < width; x++)
55
        {
56
            int origb = *in++;
57
            int origg = *in++;
58
            int origr = *in++;
59
            int realr = origr >> rclip;
60
            int realg = origg >> gclip;
61
            int realb = origb >> bclip;
62
            int errr = origr - (realr << rclip) - roffs;
63
            int errg = origg - (realg << gclip) - goffs;
64
            int errb = origb - (realb << bclip) - boffs;
65
            if (x + 1 < width)
66
            {
67
                *(in + 0) = MAX(0, MIN(255, *(in + 0) + errb / 2));
68
                *(in + 1) = MAX(0, MIN(255, *(in + 1) + errg / 2));
69
                *(in + 2) = MAX(0, MIN(255, *(in + 2) + errr / 2));
70
            }
71
            if (y + 1 < height)
72
            {
73
                *(in + 3 * instride - 1) = MAX(0, MIN(255, *(in + 3 * instride - 1) + errr / 4));
74
                *(in + 3 * instride - 2) = MAX(0, MIN(255, *(in + 3 * instride - 2) + errg / 4));
75
                *(in + 3 * instride - 3) = MAX(0, MIN(255, *(in + 3 * instride - 3) + errb / 4));
76
                *(in + 3 * instride - 4) = MAX(0, MIN(255, *(in + 3 * instride - 4) + errr / 4));
77
                *(in + 3 * instride - 5) = MAX(0, MIN(255, *(in + 3 * instride - 5) + errg / 4));
78
                *(in + 3 * instride - 6) = MAX(0, MIN(255, *(in + 3 * instride - 6) + errb / 4));
79
            }
80
            int pixel = (realr << rshift) | (realg << gshift) | (realb << bshift);
81
            if (bpp == 1) *out = pixel;
82
            else if (bpp == 2)
83
            {
84
                if (swap) *((short*)out) = (pixel >> 8) | ((pixel << 8) & 0xff00);
85
                else *((short*)out) = pixel;
86
            }
87
            else if (bpp == 3)
88
            {
89
                if (swap)
90
                {
91
                    *(out + 0) = pixel & 0xff;
92
                    *(out + 1) = (pixel >> 8) & 0xff;
93
                    *(out + 2) = (pixel >> 16) & 0xff;
94
                }
95
                else
96
                {
97
                    *(out + 0) = (pixel >> 16) & 0xff;
98
                    *(out + 1) = (pixel >> 8) & 0xff;
99
                    *(out + 2) = pixel & 0xff;
100
                }
101
            }
102
            else if (bpp == 4)
103
            {
104
                if (swap) *((int*)out) = (pixel >> 24) | ((pixel >> 8) & 0xff00)
105
                                       | ((pixel << 8) & 0xff0000) | ((pixel << 24) & 0xff000000);
106
                else *((int*)out) = pixel;
107
            }
108
            out += bpp;
109
        }
110
        in += (instride - width) * 3;
111
        out += (outstride - width) * bpp;
112
    }
113
}
114
 
115
static void dither_rgb565(int width, int height, void* inbuf, int inx, int iny, int instride,
116
                          void* outbuf, int outx, int outy, int outstride)
117
{
118
    char* in = ((char*)inbuf) + (instride * iny + inx) * 3;
119
    short* out = ((short*)outbuf) + instride * iny + inx;
120
    int x, y;
121
    for (y = 0; y < height; y++)
122
    {
123
        for (x = 0; x < width; x++)
124
        {
125
            int origb = *in++;
126
            int origg = *in++;
127
            int origr = *in++;
128
            int realr = origr >> 3;
129
            int realg = origg >> 2;
130
            int realb = origb >> 3;
131
            int errr = origr - (realr << 3) - 4;
132
            int errg = origg - (realg << 2) - 2;
133
            int errb = origb - (realb << 3) - 4;
134
            if (x + 1 < width)
135
            {
136
                *(in + 0) = MAX(0, MIN(255, *(in + 0) + errb / 2));
137
                *(in + 1) = MAX(0, MIN(255, *(in + 1) + errg / 2));
138
                *(in + 2) = MAX(0, MIN(255, *(in + 2) + errr / 2));
139
            }
140
            if (y + 1 < height)
141
            {
142
                *(in + 3 * instride - 1) = MAX(0, MIN(255, *(in + 3 * instride - 1) + errr / 4));
143
                *(in + 3 * instride - 2) = MAX(0, MIN(255, *(in + 3 * instride - 2) + errg / 4));
144
                *(in + 3 * instride - 3) = MAX(0, MIN(255, *(in + 3 * instride - 3) + errb / 4));
145
                *(in + 3 * instride - 4) = MAX(0, MIN(255, *(in + 3 * instride - 4) + errr / 4));
146
                *(in + 3 * instride - 5) = MAX(0, MIN(255, *(in + 3 * instride - 5) + errg / 4));
147
                *(in + 3 * instride - 6) = MAX(0, MIN(255, *(in + 3 * instride - 6) + errb / 4));
148
            }
149
            *out++ = (realr << 11) | (realg << 5) | realb;
150
        }
151
        in += (instride - width) * 3;
152
        out += outstride - width;
153
    }
154
}
155
 
156
 
157
void dither(int width, int height, void* inbuf, int inx, int iny, int instride,
158
            void* outbuf, int outx, int outy, int outstride)
159
{
160
    int bits = lcd_get_format();
161
    if (bits == 0x004154b1)
162
        dither_rgb565(width, height, inbuf, inx, iny, instride, outbuf, outx, outy, outstride);
163
    else dither_slow(width, height, inbuf, inx, iny, instride, outbuf, outx, outy, outstride);
164
}