You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

496 lines
11 KiB

#include "video.h"
#include "debayer.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <string>
std::string toBits(unsigned int i, int maxbits);
// macros to make code better readable
#define CE (*(src))
#define UP (*(src-src_w))
#define DN (*(src+src_w))
#define LE (*(src-1))
#define RI (*(src+1))
#define UPLE (*(src-src_w-1))
#define UPRI (*(src-src_w+1))
#define DNLE (*(src+src_w-1))
#define DNRI (*(src+src_w+1))
#define BITCONV(d) ((d>>8) & 0xff)
#define STORE if (dst) { *(dst++) = BITCONV(r); *(dst++) = BITCONV(g); *(dst++) = BITCONV(b); src++; }
#define STORE8 if (dst) { *(dst++) = (r & 0xff); *(dst++) = (g & 0xff); *(dst++) = (b & 0xff); src++; }
#define STOREF16 if (dstf) { *(dstf++) = ((float)r/65535.0); *(dstf++) = ((float)g/65535.0); *(dstf++) = ((float)b/65535.0); }
#define STOREF8 if (dstf) { *(dstf++) = ((float)r/255.0); *(dstf++) = ((float)g/255.0); *(dstf++) = ((float)b/255.0); }
/*
The function converts a 16bit GRBG 2x2 CFA coded image into an 8bit
RGB image by bilinear interpolation.
*/
void debayer_grbg16 (uint16_t * src, int src_w, int src_h,
uint8_t * dst, float * dstf, int dst_w, int dst_h) {
// GG RR GG RR
// BB GG BB GG
// GG RR GG RR
// BB GG BB GG
uint32_t r, g, b;
int xs, ys;
// start with upper left pixel (green)
r = RI;
g = CE;
b = DN;
STORE;
STOREF16;
// upper first line, starts with RR GG RR ...
for (xs = 1; xs < src_w - 1; xs+=2) {
// red pixel
r = CE;
g = (LE + RI + DN) / 3;
b = (DNLE + DNRI) / 2;
STORE;
STOREF16;
// green pixel
r = (LE + RI) / 2;
g = CE;
b = DN;
STORE;
STOREF16;
}
// upper right pixel (red)
r = CE;
g = (DN + LE) / 2;
b = DNLE;
STORE;
STOREF16;
// go through the "body" of the image
for (ys = 1; ys < src_h - 1; ys+=2) {
// every second line with BB GG BB GG (start at 2nd line)
// left hand pixel (blue)
r = (UPRI + DNRI) / 2;
g = (UP + DN + RI) / 3;
b = CE;
STORE;
STOREF16;
for (xs = 1; xs < src_w - 1; xs+=2) {
// green pixel
r = (UP + DN) / 2;
g = CE;
b = (LE + RI) / 2;
STORE;
STOREF16;
// blue pixel
r = (UPLE + UPRI + DNLE + DNRI) / 4;
g = (LE + RI + UP + DN) / 4;
b = CE;
STORE;
STOREF16;
}
// last pixel in line (green)
r = (UP + DN) / 2;
g = CE;
b = LE;
STORE;
STOREF16;
// every second line with GG RR GG RR ... (start at 3rd line)
// left hand pixel (green)
r = RI;
g = CE;
b = (UP + DN) / 2;
STORE;
STOREF16;
for (xs = 1; xs < src_w - 1; xs+=2) {
// red pixel
r = CE;
g = (LE + RI + UP + DN) / 4;
b = (UPLE + UPRI + DNLE + DNRI) / 4;
STORE;
STOREF16;
// green pixel
r = (LE + RI) / 2;
g = CE;
b = (UP + DN) / 2;
STORE;
STOREF16;
}
// last pixel in line (red)
r = CE;
g = (UP + DN + LE) / 3;
b = (UPLE + DNLE) / 2;
STORE;
STOREF16;
}
// bottom left pixel
r = UPRI;
g = (UP + RI) / 2;
b = CE;
STORE;
STOREF16;
// last line starting with GG BB GG ...
for (xs = 1; xs < src_w - 1; xs+=2) {
// green pixel
r = UP;
g = CE;
b = (LE + RI) / 2;
STORE;
STOREF16;
// blue pixel
r = (UPLE + UPRI) / 2;
g = (LE + UP + RI) / 2;
b = CE;
STORE;
STOREF16;
}
// bottom right pixel (green)
r = UP;
g = CE;
b = LE;
STORE;
STOREF16;
}
/*
The function converts a 8bit GRBG 2x2 CFA coded image into an 8bit
RGB image by bilinear interpolation.
*/
void debayer_gbrg8 (uint8_t * src, int src_w, int src_h, uint8_t *dst, float *dstf, int dst_w, int dst_h) {
debayer_grbg8 (src, src_w, src_h, dst, dstf, dst_w, dst_h);
};
void debayer_rggb8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, float *dstf, int dst_w, int dst_h) {
debayer_grbg8 (src, src_w, src_h, dst, dstf, dst_w, dst_h);
};
void debayer_grbg8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, float *dstf, int dst_w, int dst_h) {
// GG RR GG RR
// BB GG BB GG
// GG RR GG RR
// BB GG BB GG
uint16_t r, g, b;
int xs, ys;
// start with upper left pixel (green)
r = RI;
g = CE;
b = DN;
STORE8;
STOREF8;
// upper first line, starts with RR GG RR ...
for (xs = 1; xs < src_w - 1; xs+=2) {
// red pixel
r = CE;
g = (LE + RI + DN) / 3;
b = (DNLE + DNRI) / 2;
STORE8;
STOREF8;
// green pixel
r = (LE + RI) / 2;
g = CE;
b = DN;
STORE8;
STOREF8;
}
// upper right pixel (red)
r = CE;
g = (DN + LE) / 2;
b = DNLE;
STORE8;
STOREF8;
// go through the "body" of the image
for (ys = 1; ys < src_h - 1; ys+=2) {
// every second line with BB GG BB GG (start at 2nd line)
// left hand pixel (blue)
r = (UPRI + DNRI) / 2;
g = (UP + DN + RI) / 3;
b = CE;
STORE8;
STOREF8;
for (xs = 1; xs < src_w - 1; xs+=2) {
// green pixel
r = (UP + DN) / 2;
g = CE;
b = (LE + RI) / 2;
STORE8;
STOREF8;
// blue pixel
r = (UPLE + UPRI + DNLE + DNRI) / 4;
g = (LE + RI + UP + DN) / 4;
b = CE;
STORE8;
STOREF8;
}
// last pixel in line (green)
r = (UP + DN) / 2;
g = CE;
b = LE;
STORE8;
STOREF8;
// every second line with GG RR GG RR ... (start at 3rd line)
// left hand pixel (green)
r = RI;
g = CE;
b = (UP + DN) / 2;
STORE8;
STOREF8;
for (xs = 1; xs < src_w - 1; xs+=2) {
// red pixel
r = CE;
g = (LE + RI + UP + DN) / 4;
b = (UPLE + UPRI + DNLE + DNRI) / 4;
STORE8;
STOREF8;
// green pixel
r = (LE + RI) / 2;
g = CE;
b = (UP + DN) / 2;
STORE8;
STOREF8;
}
// last pixel in line (red)
r = CE;
g = (UP + DN + LE) / 3;
b = (UPLE + DNLE) / 2;
STORE8;
STOREF8;
}
// bottom left pixel
r = UPRI;
g = (UP + RI) / 2;
b = CE;
STORE8;
STOREF8;
// last line starting with GG BB GG ...
for (xs = 1; xs < src_w - 1; xs+=2) {
// green pixel
r = UP;
g = CE;
b = (LE + RI) / 2;
STORE8;
STOREF8;
// blue pixel
r = (UPLE + UPRI) / 2;
g = (LE + UP + RI) / 2;
b = CE;
STORE8;
STOREF8;
}
// bottom right pixel (green)
r = UP;
g = CE;
b = LE;
STORE8;
STOREF8;
}
#define MAX(_a_,_m_) ( _a_ > _m_ ? _m_ : _a_)
#define PRGGB10P_U ((uint16_t)(*(psrc-src_w*2*10/8)))
#define PRGGB10P_D ((uint16_t)(*(psrc+src_w*2*10/8)))
#define PRGGB10P_L ((uint16_t)(*(psrc-2)*10/8))
#define PRGGB10P_R ((uint16_t)(*(psrc+2)*10/8))
#define PRGGB10P_UL ((uint16_t)(*(psrc-2-src_w*2*10/8)))
#define PRGGB10P_UR ((uint16_t)(*(psrc+2-src_w*2*10/8)))
#define PRGGB10P_DL ((uint16_t)(*(psrc-2-src_w*2*10/8)))
#define PRGGB10P_DR ((uint16_t)(*(psrc+2+src_w*2*10/8)))
void debayer_rggb10packet (uint8_t *src, int src_w, int src_h,
uint8_t *dst, float *dstf, int dst_w, int dst_h) {
debug ("not yep implemented");
debug ("src size:%dx%d dst size:%dx%d", src_w, src_h, dst_w, dst_h);
};
std::string toBits(unsigned int i, int maxbits) {
int b;
std::string out = "";
for (b = 0; b < maxbits; b++) {
if (b % 8 == 0 && b) out = ":" + out;
if (i % 2) out = "1" + out;
else out = "0" + out;
i = i >> 1;
}
return out;
}
inline int swap16(uint16_t i) {
uint16_t r;
*(((unsigned char *)&r)) = *(((unsigned char *)&i)+1);
*(((unsigned char *)&r)+1) = *(((unsigned char *)&i));
return r;
}
#define PRGGB10_U (unsigned int)(*(psrc-src_w))
#define PRGGB10_D (unsigned int)(*(psrc+src_w))
#define PRGGB10_L (unsigned int)(*(psrc-1))
#define PRGGB10_R (unsigned int)(*(psrc+1))
#define PRGGB10_UL (unsigned int)(*(psrc-1-src_w))
#define PRGGB10_UR (unsigned int)(*(psrc+1-src_w))
#define PRGGB10_DL (unsigned int)(*(psrc-1+src_w))
#define PRGGB10_DR (unsigned int)(*(psrc+1+src_w))
void debayer_gbrg10 (uint8_t * src, int src_w, int src_h, uint8_t * dst, float * dstf, int dst_w, int dst_h) {
// GG BB GG BB
// RR GG RR GG
// GG BB GG BB
// RR GG RR GG
int xs, ys, xd, yd;
uint32_t r, g, b, data;
int max = dst_w * dst_h * 3;
uint8_t *pdst = NULL;
float *pdstf = NULL;
uint16_t *psrc = NULL;
int max_r = 0;
int max_g = 0;
int max_b = 0;
pdst = dst;
pdstf = dstf;
for (ys = 0, yd = 0, psrc = (uint16_t*)src; ys < dst_h; ys++, yd++) {
r = 0;
g = 0;
b = 0;
for (xs = 0, xd = 0; xd < dst_w; xs++, xd++) {
if (ys > 0 && ys < src_h-1 && xs > 0 && xs < src_w-1) {
r = 0; b = 0; g = 0;
if (ys&1) {
if (xs&1) {
b = (unsigned int)(PRGGB10_U + PRGGB10_D) >> 1;
g = *psrc;
r = (unsigned int)(PRGGB10_L + PRGGB10_R) >> 1;
}
else {
b = (unsigned int)(PRGGB10_UL + PRGGB10_DL + PRGGB10_UR + PRGGB10_UL) >> 2;
g = (unsigned int)(PRGGB10_L + PRGGB10_R + PRGGB10_U + PRGGB10_D) >> 2;
r = *psrc;
}
}
else {
if (xs&1) {
b = *psrc;
g = (unsigned int)(PRGGB10_L + PRGGB10_R + PRGGB10_U + PRGGB10_D) >> 2;
r = (unsigned int)(PRGGB10_UL + PRGGB10_DL + PRGGB10_UR + PRGGB10_UL) >> 2;
}
else {
b = (unsigned int)(PRGGB10_L + PRGGB10_R) >> 1;
g = *psrc;
r = (unsigned int)(PRGGB10_U + PRGGB10_D) >> 1;
}
}
}
// copy pixel to destination 24RGB
if (pdst) {
pdst[0] = (r >> 2);
pdst[1] = (g >> 2);
pdst[2] = (b >> 2);
pdst += 3;
}
// copy pixel to destination float
if (pdstf) {
pdstf[0] = ((float)r / 1023.0);
pdstf[1] = ((float)g / 1023.0);
pdstf[2] = ((float)b / 1023.0);
pdstf += 3;
}
psrc += 1;
}
}
};
void debayer_rggb10 (uint8_t *src, int src_w, int src_h, uint8_t *dst, float *dstf, int dst_w, int dst_h) {
// RR GG RR GG
// GG BB GG BB
// RR GG RR GG
// GG BB GG BB
int xs, ys, xd, yd;
uint32_t r, g, b, data;
int max = dst_w * dst_h * 3;
uint8_t *pdst = NULL;
float *pdstf = NULL;
uint16_t *psrc;
int max_r = 0;
int max_g = 0;
int max_b = 0;
pdst = dst;
pdstf = dstf;
for (ys = 0, yd = 0, psrc = (uint16_t*)src; ys < dst_h; ys++, yd++) {
r = 0;
g = 0;
b = 0;
for (xs = 0, xd = 0; xd < dst_w; xs++, xd++) {
r = 0; b = 0; g = 0;
if (ys > 0 && ys < src_h-1 && xs > 0 && xs < src_w-1) {
if (ys&1) {
if (xs&1) {
b = *psrc;
g = (unsigned int)(PRGGB10_L + PRGGB10_R + PRGGB10_U + PRGGB10_D) >> 2;
r = (unsigned int)(PRGGB10_UL + PRGGB10_DL + PRGGB10_UR + PRGGB10_UL) >> 2;
}
else {
b = (unsigned int)(PRGGB10_L + PRGGB10_R) >> 1;
g = *psrc;
r = (unsigned int)(PRGGB10_U + PRGGB10_D) >> 1;
}
}
else {
if (xs&1) {
b = (unsigned int)(PRGGB10_U + PRGGB10_D) >> 1;
g = *psrc;
r = (unsigned int)(PRGGB10_L + PRGGB10_R) >> 1;
}
else {
g = (unsigned int)(PRGGB10_L + PRGGB10_R + PRGGB10_U + PRGGB10_D) >> 2;
b = (unsigned int)(PRGGB10_UL + PRGGB10_DL + PRGGB10_UR + PRGGB10_UL) >> 2;
r = *psrc;
}
}
}
// copy pixel to destination 24RGB
if (pdst) {
pdst[0] = (r >> 2);
pdst[1] = (g >> 2);
pdst[2] = (b >> 2);
pdst += 3;
}
// copy pixel to destination float
if (pdstf) {
pdstf[0] = ((float)r / 1023.0);
pdstf[1] = ((float)g / 1023.0);
pdstf[2] = ((float)b / 1023.0);
pdstf += 3;
}
psrc += 1;
}
}
};