summaryrefslogtreecommitdiff
path: root/image.c
blob: 0fb684da1e3fd6aad74263fceba68e89e460f964 (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
/* Camicro - Microscope camera viewer.
 *
 * Copyright (C) 2019 Nicolas Schodet
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Contact :
 *        Web: http://ni.fr.eu.org/
 *      Email: <nico at ni.fr.eu.org>
 */
#include "image.h"

#include <string.h>

void
image_bayer2argb(const uint8_t *bayer, uint32_t *rgb, int width, int height)
{
    /*
     * Compute missing value using an average of its neighbours.
     * Input pattern:
     * G R G R G R
     * B G B G B G
     * G R G R G R
     * B G B G B G
     */
    const int in_stride = width;
    const int out_stride = width * 4;
    /* Skip first line and column. */
    const uint8_t *in = bayer + in_stride + 1;
    uint8_t *out = (uint8_t *) rgb + out_stride + 4;
    /* Loop over lines. */
    for (int i = 1; i < height - 1; i += 2) {
	/* Even lines. */
	const uint8_t *in_stop = in + (width - 2);
	while (in != in_stop) {
	    *out++ = (in[-1] + in[+1] + 1) >> 1;                 /* B */
	    *out++ = in[0];                                      /* G */
	    *out++ = (in[-in_stride] + in[+in_stride] + 1) >> 1; /* R */
	    *out++ = 255;                                        /* A */
	    in++;
	    *out++ = in[0];                                      /* B */
	    *out++ = (in[-in_stride] + in[+in_stride]            /* G */
		    + in[-1] + in[+1] + 2) >> 2;
	    *out++ = (in[-in_stride - 1] + in[-in_stride + 1]    /* R */
		    + in[+in_stride - 1] + in[+in_stride + 1] + 2) >> 2;
	    *out++ = 255;                                        /* A */
	    in++;
	}
	/* Fill first and last pixels. */
	out[-(width - 1) * 4 + 0] = out[-(width - 2) * 4 + 0];
	out[-(width - 1) * 4 + 1] = out[-(width - 2) * 4 + 1];
	out[-(width - 1) * 4 + 2] = out[-(width - 2) * 4 + 2];
	out[-(width - 1) * 4 + 3] = out[-(width - 2) * 4 + 3];
	out[0] = out[-4];
	out[1] = out[-3];
	out[2] = out[-2];
	out[3] = out[-1];
	out += out_stride - (width - 2) * 4;
	in += in_stride - (width - 2);
	/* Odd lines. */
	in_stop = in + (width - 2);
	while (in != in_stop) {
	    *out++ = (in[-in_stride - 1] + in[-in_stride + 1]    /* B */
		    + in[+in_stride - 1] + in[+in_stride + 1] + 2) >> 2;
	    *out++ = (in[-in_stride] + in[+in_stride]            /* G */
		    + in[-1] + in[+1] + 2) >> 2;
	    *out++ = in[0];                                      /* R */
	    *out++ = 255;                                        /* A */
	    in++;
	    *out++ = (in[-in_stride] + in[+in_stride] + 1) >> 1; /* B */
	    *out++ = in[0];                                      /* G */
	    *out++ = (in[-1] + in[+1] + 1) >> 1;                 /* R */
	    *out++ = 255;                                        /* A */
	    in++;
	}
	/* Fill first and last pixels. */
	out[-(width - 1) * 4 + 0] = out[-(width - 2) * 4 + 0];
	out[-(width - 1) * 4 + 1] = out[-(width - 2) * 4 + 1];
	out[-(width - 1) * 4 + 2] = out[-(width - 2) * 4 + 2];
	out[-(width - 1) * 4 + 3] = out[-(width - 2) * 4 + 3];
	out[0] = out[-4];
	out[1] = out[-3];
	out[2] = out[-2];
	out[3] = out[-1];
	out += out_stride - (width - 2) * 4;
	in += in_stride - (width - 2);
    }
    /* Last line. */
    out -= 4;
    memcpy(out, out - out_stride, width * 4);
    /* First line. */
    out -= (height - 1) * out_stride;
    memcpy(out, out + out_stride, width * 4);
}