#include "video.h" #include "debayer.h" #include #include #include #include #include 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; } } };