diff --git a/convert.cc b/convert.cc index aab5c6e..950e071 100644 --- a/convert.cc +++ b/convert.cc @@ -91,6 +91,7 @@ int ConvertStart(ConvertData *cdata, uint32_t pixelformat) { return 1; }; + int ConvertStop(ConvertData *cdata, uint32_t pixelformat) { dumpframe_close(); @@ -104,14 +105,15 @@ int ConvertStop(ConvertData *cdata, uint32_t pixelformat) { /* * converts the video from input type to RGB24 type - 24Bit */ -int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int srcsize, uint32_t pixelformat, int srcw, int srch) { +int Convert (ConvertData *cdata, VideoFrame *dest, VideoFrameFloat *destf, unsigned char *ptrsrc, int srcsize, uint32_t pixelformat, int srcw, int srch) { int xs, ys; int xd, yd; unsigned char r,g,b; unsigned char cb, cr, y1; unsigned char *ptrdst = NULL; + float *ptrdstf = NULL; // for float data scaled to 0...1.0 - debug ("srcsize:%d pixfmt:%s size: %dx%d", srcsize, convert_from_pixelformat(pixelformat).c_str(), srcw, srch); + // debug ("srcsize:%d pixfmt:%s size: %dx%d", srcsize, convert_from_pixelformat(pixelformat).c_str(), srcw, srch); if (config.vdev_dumppath.length() > 0) dumpframe(ptrsrc, srcsize, pixelformat, srcw, srch); struct jpg_error_mgr jerr; @@ -119,11 +121,18 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr // check if there is a destination and that the destination is large to keep // the full image - if (dest == NULL || ptrsrc == NULL) + if ((dest == NULL && destf == NULL) || ptrsrc == NULL) return 0; - dest->SetSize(srcw, srch); - ptrdst = dest->GetPixBuf(); + if (dest) { + dest->SetSize(srcw, srch); + ptrdst = dest->GetPixBuf(); + } + if (destf) { + destf->SetSize(srcw, srch); + ptrdstf = destf->GetPixBuf(); + } + switch (pixelformat) { case (V4L2_PIX_FMT_RGB32): @@ -139,16 +148,25 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr /* only paint the image if the source is within the destination */ if (xd < srcw) { /* set the pixel */ - *(ptrdst++) = r; - *(ptrdst++) = g; - *(ptrdst++) = b; + if (ptrdst) { + *(ptrdst++) = r; + *(ptrdst++) = g; + *(ptrdst++) = b; + } + else { + *(ptrdstf++) = (float)r/255.0; + *(ptrdstf++) = (float)g/255.0; + *(ptrdstf++) = (float)b/255.0; + } xd++; } } /* if the source image is too small ignore the other places.. */ - if (xd < srcw) - ptrdst += 3 * (srcw - xd); + if (xd < srcw) { + if (ptrdst) ptrdst += 3 * (srcw - xd); + if (ptrdstf) ptrdstf += 3 *(srcw - xd); + } yd++; } break; @@ -165,17 +183,25 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr /* only paint the image if the source is within the destination */ if (xd < srcw) { - /* set the pixel */ - *(ptrdst++) = r; - *(ptrdst++) = g; - *(ptrdst++) = b; + if (ptrdst) { + *(ptrdst++) = r; + *(ptrdst++) = g; + *(ptrdst++) = b; + } + else { + *(ptrdstf++) = (float)r/255.0; + *(ptrdstf++) = (float)g/255.0; + *(ptrdstf++) = (float)b/255.0; + } xd++; } } /* if the source image is too small ignore the other places.. */ - if (xd < srcw) - ptrdst += 3 * (srcw - xd); + if (xd < srcw) { + if (ptrdst) ptrdst += 3 * (srcw - xd); + if (ptrdstf) ptrdstf += 3 *(srcw - xd); + } yd++; } break; @@ -190,17 +216,25 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr /* only paint the image if the source is within the destination */ if (xd < srcw) { - /* set the pixel */ - *(ptrdst++) = r; - *(ptrdst++) = g; - *(ptrdst++) = b; + if (ptrdst) { + *(ptrdst++) = r; + *(ptrdst++) = g; + *(ptrdst++) = b; + } + else { + *(ptrdstf++) = (float)r/255.0; + *(ptrdstf++) = (float)g/255.0; + *(ptrdstf++) = (float)b/255.0; + } xd++; } } /* if the source image is too small ignore the other places.. */ - if (xd < srcw) - ptrdst += 3 * (srcw - xd); + if (xd < srcw) { + if (ptrdst) ptrdst += 3 * (srcw - xd); + if (ptrdstf) ptrdstf += 3 *(srcw - xd); + } yd++; } break; @@ -216,43 +250,51 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr /* only paint the image if the source is within the destination */ if (xd < srcw) { - /* set the pixel */ - *(ptrdst++) = r; - *(ptrdst++) = g; - *(ptrdst++) = b; + if (ptrdst) { + *(ptrdst++) = r; + *(ptrdst++) = g; + *(ptrdst++) = b; + } + else { + *(ptrdstf++) = (float)r/255.0; + *(ptrdstf++) = (float)g/255.0; + *(ptrdstf++) = (float)b/255.0; + } xd++; } } /* if the source image is too small ignore the other places.. */ - if (xd < srcw) - ptrdst += 3 * (srcw - xd); + if (xd < srcw) { + if (ptrdst) ptrdst += 3 * (srcw - xd); + if (ptrdstf) ptrdstf += 3 *(srcw - xd); + } yd++; } break; case (V4L2_PIX_FMT_SGRBG16): - debayer_grbg16 ((uint16_t *)ptrsrc, srcw, srch, ptrdst, srcw, srch); + debayer_grbg16 ((uint16_t *)ptrsrc, srcw, srch, ptrdst, ptrdstf, srcw, srch); break; case (V4L2_PIX_FMT_SRGGB10P): - debayer_rggb10packet ((uint8_t *)ptrsrc, srcw, srch, ptrdst, srcw, srch); + debayer_rggb10packet ((uint8_t *)ptrsrc, srcw, srch, ptrdst, ptrdstf, srcw, srch); break; case (V4L2_PIX_FMT_SGBRG10): - debayer_gbrg10 ((uint8_t *)ptrsrc, srcw, srch, ptrdst, srcw, srch); + debayer_gbrg10 ((uint8_t *)ptrsrc, srcw, srch, ptrdst, ptrdstf, srcw, srch); break; case (V4L2_PIX_FMT_SRGGB10): - debayer_rggb10 ((uint8_t *)ptrsrc, srcw, srch, ptrdst, srcw, srch); + debayer_rggb10 ((uint8_t *)ptrsrc, srcw, srch, ptrdst, ptrdstf, srcw, srch); break; case (V4L2_PIX_FMT_SRGGB8): - debayer_rggb8 ((uint8_t *)ptrsrc, srcw, srch, ptrdst, srcw, srch); + debayer_rggb8 ((uint8_t *)ptrsrc, srcw, srch, ptrdst, ptrdstf, srcw, srch); break; case (V4L2_PIX_FMT_SGRBG8): - debayer_grbg8 ((uint8_t *)ptrsrc, srcw, srch, ptrdst, srcw, srch); + debayer_grbg8 ((uint8_t *)ptrsrc, srcw, srch, ptrdst, ptrdstf, srcw, srch); break; case (V4L2_PIX_FMT_UYVY): @@ -275,17 +317,25 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr /* only paint the image if the source is within the destination */ if (xd < srcw) { - /* set the pixel */ - *(ptrdst++) = r; - *(ptrdst++) = g; - *(ptrdst++) = b; + if (ptrdst) { + *(ptrdst++) = r; + *(ptrdst++) = g; + *(ptrdst++) = b; + } + else { + *(ptrdstf++) = (float)r/255.0; + *(ptrdstf++) = (float)g/255.0; + *(ptrdstf++) = (float)b/255.0; + } xd++; } } /* if the source image is too small ignore the other places.. */ - if (xd < srcw) - ptrdst += 3 * (srcw - xd); + if (xd < srcw) { + if (ptrdst) ptrdst += 3 * (srcw - xd); + if (ptrdstf) ptrdstf += 3 *(srcw - xd); + } yd++; } break; @@ -308,19 +358,27 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr convert2rgb (y1, cr, cb, &r, &g, &b); ptrsrc += 2; - /* only paint the image if the source is within the destination */ - if (xd < srcw) { - /* set the pixel */ + /* only paint the image if the source is within the destination */ + if (xd < srcw) { + if (ptrdst) { *(ptrdst++) = r; *(ptrdst++) = g; *(ptrdst++) = b; - xd++; } + else { + *(ptrdstf++) = (float)r/255.0; + *(ptrdstf++) = (float)g/255.0; + *(ptrdstf++) = (float)b/255.0; + } + xd++; + } } /* if the source image is too small ignore the other places.. */ - if (xd < srcw) - ptrdst += 3 * (srcw - xd); + if (xd < srcw) { + if (ptrdst) ptrdst += 3 * (srcw - xd); + if (ptrdstf) ptrdstf += 3 *(srcw - xd); + } yd++; } } diff --git a/convert.h b/convert.h index f1bb80d..f198470 100644 --- a/convert.h +++ b/convert.h @@ -18,7 +18,7 @@ struct { } typedef ConvertData; -int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int srcsize, uint32_t pixelformat, int srcw, int srch); +int Convert (ConvertData *cdata, VideoFrame *dest, VideoFrameFloat *destf, unsigned char *ptrsrc, int srcsize, uint32_t pixelformat, int srcw, int srch); int ConvertStart(ConvertData *cdata, uint32_t pixelformat); int ConvertStop(ConvertData *cdata, uint32_t pixelformat); diff --git a/debayer.cc b/debayer.cc index bd4e3bf..3a6386c 100644 --- a/debayer.cc +++ b/debayer.cc @@ -22,8 +22,10 @@ std::string toBits(unsigned int i, int maxbits); #define DNRI (*(src+src_w+1)) #define BITCONV(d) ((d>>8) & 0xff) -#define STORE *(dst++) = BITCONV(r); *(dst++) = BITCONV(g); *(dst++) = BITCONV(b); src++; -#define STORE8 *(dst++) = (r & 0xff); *(dst++) = (g & 0xff); *(dst++) = (b & 0xff); src++; +#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); } /* @@ -31,7 +33,7 @@ std::string toBits(unsigned int i, int maxbits); RGB image by bilinear interpolation. */ void debayer_grbg16 (uint16_t * src, int src_w, int src_h, - uint8_t * dst, int dst_w, int dst_h) { + uint8_t * dst, float * dstf, int dst_w, int dst_h) { // GG RR GG RR // BB GG BB GG @@ -45,6 +47,7 @@ void debayer_grbg16 (uint16_t * src, int src_w, int src_h, g = CE; b = DN; STORE; + STOREF16; // upper first line, starts with RR GG RR ... for (xs = 1; xs < src_w - 1; xs+=2) { @@ -53,11 +56,13 @@ void debayer_grbg16 (uint16_t * src, int src_w, int src_h, 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) @@ -65,6 +70,7 @@ void debayer_grbg16 (uint16_t * src, int src_w, int src_h, g = (DN + LE) / 2; b = DNLE; STORE; + STOREF16; // go through the "body" of the image for (ys = 1; ys < src_h - 1; ys+=2) { @@ -76,23 +82,27 @@ void debayer_grbg16 (uint16_t * src, int src_w, int src_h, 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) @@ -101,23 +111,27 @@ void debayer_grbg16 (uint16_t * src, int src_w, int src_h, 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 @@ -125,6 +139,7 @@ void debayer_grbg16 (uint16_t * src, int src_w, int src_h, g = (UP + RI) / 2; b = CE; STORE; + STOREF16; // last line starting with GG BB GG ... for (xs = 1; xs < src_w - 1; xs+=2) { @@ -133,11 +148,13 @@ void debayer_grbg16 (uint16_t * src, int src_w, int src_h, 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) @@ -145,21 +162,22 @@ void debayer_grbg16 (uint16_t * src, int src_w, int src_h, 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, int dst_w, int dst_h) { - debayer_grbg8 (src, src_w, src_h, dst, dst_w, dst_h); +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, int dst_w, int dst_h) { - debayer_grbg8 (src, src_w, src_h, dst, 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, int dst_w, int 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 @@ -173,6 +191,7 @@ void debayer_grbg8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_ g = CE; b = DN; STORE8; + STOREF8; // upper first line, starts with RR GG RR ... for (xs = 1; xs < src_w - 1; xs+=2) { @@ -181,11 +200,13 @@ void debayer_grbg8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_ 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) @@ -193,6 +214,7 @@ void debayer_grbg8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_ g = (DN + LE) / 2; b = DNLE; STORE8; + STOREF8; // go through the "body" of the image for (ys = 1; ys < src_h - 1; ys+=2) { @@ -204,23 +226,27 @@ void debayer_grbg8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_ 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) @@ -229,23 +255,27 @@ void debayer_grbg8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_ 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 @@ -253,6 +283,7 @@ void debayer_grbg8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_ g = (UP + RI) / 2; b = CE; STORE8; + STOREF8; // last line starting with GG BB GG ... for (xs = 1; xs < src_w - 1; xs+=2) { @@ -261,11 +292,13 @@ void debayer_grbg8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_ 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) @@ -273,9 +306,10 @@ void debayer_grbg8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_ g = CE; b = LE; STORE8; + STOREF8; } -int MAX(int a, int m) { if (a > m) return m; else return a; }; +#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)) @@ -284,75 +318,11 @@ int MAX(int a, int m) { if (a > m) return m; else return a; }; #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, int dst_w, int dst_h) { - int s, d; - int xs, ys, xd, yd; - unsigned char r, g, b; - int max = dst_w * dst_h * 3; - unsigned char *pdst; - unsigned char *psrc; - int shift; - - printf ("%s:%d src size:%dx%d dst size:%dx%d\n", __FILE__, __LINE__, src_w, src_h, dst_w, dst_h); - - // RR GG RR GG HH RR - // GG BB GG BB HH GG - // RR GG RR GG HH RR - // GG BB GG BB HH GG +void debayer_rggb10packet (uint8_t *src, int src_w, int src_h, + uint8_t *dst, float *dstf, int dst_w, int dst_h) { - - for (ys = 0, yd = 0, psrc = src, pdst = dst; 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 = (PRGGB10P_L + PRGGB10P_R + PRGGB10P_U + PRGGB10P_D)/4; - r = (PRGGB10P_UL + PRGGB10P_DL + PRGGB10P_UR + PRGGB10P_UL)/4; - } - else { - b = (PRGGB10P_L + PRGGB10P_R)/2; - g = *psrc; - r = (PRGGB10P_U + PRGGB10P_D)/2; - } - } - else { - if (xs&1) { - b = (PRGGB10P_U + PRGGB10P_D)/2; - g = *psrc; - r = (PRGGB10P_L + PRGGB10P_R)/2; - } - else { - g = (PRGGB10P_L + PRGGB10P_R + PRGGB10P_U + PRGGB10P_D)/4; - b = (PRGGB10P_UL + PRGGB10P_DL + PRGGB10P_UR + PRGGB10P_UL)/4; - r = *psrc; - } - } - } - if (pdst - dst > max) { - printf ("debayer error. dpst out of bounds size:%dx%d pos:%dx%d \n", dst_w, dst_h, xd, yd); - } - if ((ys == 10 || ys == 11) && xs < 10) printf ("%dx%d - %d, %d, %d\n", xs, ys, r, g, b); - pdst[0] = MAX(r, 0xff); - pdst[1] = MAX(g, 0xff); - pdst[2] = MAX(b, 0xff); - - if (yd < 100 && xd < 300) { - pdst[0] = 0; if (xd < 100) pdst[0] = 255; - pdst[1] = 0; if (xd > 100 && xd < 200) pdst[1] = 255; - pdst[2] = 0; if (xd > 200 && xd < 300) pdst[2] = 255; - } - - pdst += 3; - psrc++; - if (xs && (xs % 4 == 0)) psrc++; - } - } + debug ("not yep implemented"); + debug ("src size:%dx%d dst size:%dx%d", src_w, src_h, dst_w, dst_h); }; @@ -385,7 +355,7 @@ inline int swap16(uint16_t i) { #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, int dst_w, int dst_h) { +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 @@ -393,13 +363,16 @@ void debayer_gbrg10 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int ds int xs, ys, xd, yd; uint32_t r, g, b, data; int max = dst_w * dst_h * 3; - uint8_t *pdst; - uint16_t *psrc; + uint8_t *pdst = NULL; + float *pdstf = NULL; + uint16_t *psrc = NULL; int max_r = 0; int max_g = 0; int max_b = 0; - for (ys = 0, yd = 0, psrc = (uint16_t*)src, pdst = dst; ys < dst_h; ys++, yd++) { + pdst = dst; + pdstf = dstf; + for (ys = 0, yd = 0, psrc = (uint16_t*)src; ys < dst_h; ys++, yd++) { r = 0; g = 0; b = 0; @@ -431,21 +404,28 @@ void debayer_gbrg10 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int ds } } } - pdst[0] = (r >> 2); - pdst[1] = (g >> 2); - pdst[2] = (b >> 2); -// if (yd < 100 && xd < 300) { -// pdst[0] = 0; if (xd < 100) pdst[0] = 255; -// pdst[1] = 0; if (xd > 100 && xd < 200) pdst[1] = 255; -// pdst[2] = 0; if (xd > 200 && xd < 300) pdst[2] = 255; -// } - pdst += 3; + + // 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, int dst_w, int dst_h) { +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 @@ -453,13 +433,16 @@ void debayer_rggb10 (uint8_t *src, int src_w, int src_h, uint8_t * dst, int dst_ int xs, ys, xd, yd; uint32_t r, g, b, data; int max = dst_w * dst_h * 3; - uint8_t *pdst; + uint8_t *pdst = NULL; + float *pdstf = NULL; uint16_t *psrc; int max_r = 0; int max_g = 0; int max_b = 0; - for (ys = 0, yd = 0, psrc = (uint16_t*)src, pdst = dst; ys < dst_h; ys++, yd++) { + pdst = dst; + pdstf = dstf; + for (ys = 0, yd = 0, psrc = (uint16_t*)src; ys < dst_h; ys++, yd++) { r = 0; g = 0; b = 0; @@ -491,15 +474,21 @@ void debayer_rggb10 (uint8_t *src, int src_w, int src_h, uint8_t * dst, int dst_ } } } - pdst[0] = (r >> 2); - pdst[1] = (g >> 2); - pdst[2] = (b >> 2); -// if (yd < 100 && xd < 300) { -// pdst[0] = 0; if (xd < 100) pdst[0] = 255; -// pdst[1] = 0; if (xd > 100 && xd < 200) pdst[1] = 255; -// pdst[2] = 0; if (xd > 200 && xd < 300) pdst[2] = 255; -// } - pdst += 3; + // 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; } } diff --git a/debayer.h b/debayer.h index 613ed35..98803b8 100644 --- a/debayer.h +++ b/debayer.h @@ -3,14 +3,14 @@ #include -void debayer_grbg16 (uint16_t * src, int src_w, int src_h, uint8_t * dst, int dst_w, int dst_h); +void debayer_grbg16 (uint16_t *src, int src_w, int src_h, uint8_t *dst, float*dstf, int dst_w, int dst_h); -void debayer_grbg8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_w, int dst_h); -void debayer_gbrg8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_w, int dst_h); -void debayer_rggb8 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_w, int 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); +void debayer_gbrg8 (uint8_t *src, int src_w, int src_h, uint8_t *dst, float*dstf, int dst_w, int 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); -void debayer_rggb10packet (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_w, int dst_h); -void debayer_gbrg10 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_w, int dst_h); -void debayer_rggb10 (uint8_t * src, int src_w, int src_h, uint8_t * dst, int dst_w, int dst_h); +void debayer_rggb10packet (uint8_t *src, int src_w, int src_h, uint8_t *dst, float *dstf, int dst_w, int dst_h); +void debayer_gbrg10 (uint8_t *src, int src_w, int src_h, uint8_t *dst, float *dstf, int dst_w, int dst_h); +void debayer_rggb10 (uint8_t *src, int src_w, int src_h, uint8_t *dst, float *dstf, int dst_w, int dst_h); #endif diff --git a/main.cc b/main.cc index 97471e5..3285055 100644 --- a/main.cc +++ b/main.cc @@ -17,7 +17,10 @@ int SetupSignals(); std::string GetDefaultConfig(std::string name); VideoFrame inputimage; +VideoFrameFloat inputfloat; +VideoFrameFloat inputfloatfilter; VideoFrame currentimage; +VideoFrame currentimagefloat; static void *thread_webserver(void *ignored_argument) { @@ -65,12 +68,15 @@ static void *thread_video(void *ignored_argument) { currentimage.SetSize (config.web_width, config.web_height); while (running) { - if (vdev->GetFrame(&inputimage) == 0) { + if (vdev->GetFrame(&inputimage, &inputfloat) == 0) { vdev->Stop(); vdev->Start(); } Lock(); inputimage.CopyTo(¤timage, config.web_width, config.web_height); + if (inputfloatfilter.AddScaledImage(&inputfloat, 0.5, 0.5) == 0) + inputfloat.CopyTo(&inputfloatfilter); + inputfloatfilter.CopyTo(¤timagefloat); UnLock(); } diff --git a/miniwebcam.h b/miniwebcam.h index f3f6707..dfb806e 100644 --- a/miniwebcam.h +++ b/miniwebcam.h @@ -26,9 +26,11 @@ void ErrorExit(std::string text, int errorcode); int Lock(); int UnLock(); -extern VideoFrame currentimage; extern VideoFrame inputimage; extern VideoFrame currentimage; + +extern VideoFrameFloat inputfloat; +extern VideoFrame currentimagefloat; extern int running; #endif diff --git a/video.h b/video.h index 70d4121..997a0ca 100644 --- a/video.h +++ b/video.h @@ -81,7 +81,7 @@ class VideoDevice { virtual int SetIOMode(int newiomode) { debug (""); return 0; }; virtual int Start() { debug (""); return 0; }; virtual int Stop() { debug (""); return 0; }; - virtual int GetFrame (VideoFrame *destframe) { debug (""); return 0; }; + virtual int GetFrame (VideoFrame *destframe, VideoFrameFloat *destfloat) { debug (""); return 0; }; virtual int SetDevCtrl(unsigned int id, int value) { debug (""); return 0; }; virtual int GetDevCtrl(unsigned int id, int *value) { debug (""); return 0; }; }; diff --git a/videodevice_dump.cc b/videodevice_dump.cc index 30e9378..ccb8289 100644 --- a/videodevice_dump.cc +++ b/videodevice_dump.cc @@ -247,7 +247,7 @@ int VideoDevice_Dump::Stop() { // #define SIZE_FRAMEHEADER 8 #define SIZE_DUMPHEADER 12 -int VideoDevice_Dump::GetFrame(VideoFrame *destframe) { +int VideoDevice_Dump::GetFrame(VideoFrame *destframe, VideoFrameFloat *destfloat) { struct timeval curtv; unsigned int diff = 0; std::list::iterator ctrl; @@ -266,7 +266,7 @@ int VideoDevice_Dump::GetFrame(VideoFrame *destframe) { } while (diff < inframe_nexttime); ReadFrame(); - Convert(&cdata, destframe, inframe, inframe_size, + Convert(&cdata, destframe, destfloat, inframe, inframe_size, conf_videofmt, w, h); ctrl = vidctrls.begin(); diff --git a/videodevice_dump.h b/videodevice_dump.h index 794c202..529beba 100644 --- a/videodevice_dump.h +++ b/videodevice_dump.h @@ -34,7 +34,7 @@ class VideoDevice_Dump : public VideoDevice { int SetIOMode(int newiomode) { return 1; }; int Start(); int Stop(); - int GetFrame (VideoFrame *destframe); + int GetFrame (VideoFrame *destframe, VideoFrameFloat *destfloat); int SetDevCtrl(unsigned int id, int value); int GetDevCtrl(unsigned int id, int *value); }; diff --git a/videodevice_v4l2.cc b/videodevice_v4l2.cc index d89b3e7..22f9f3b 100644 --- a/videodevice_v4l2.cc +++ b/videodevice_v4l2.cc @@ -380,11 +380,11 @@ int VideoDevice_V4L2::Stop() { }; -int VideoDevice_V4L2::GetFrame(VideoFrame *destframe) { +int VideoDevice_V4L2::GetFrame(VideoFrame *destframe, VideoFrameFloat *destfloat) { struct v4l2_buffer buf; int len; - if (destframe == NULL) return 0; + if (destframe == NULL && destfloat == NULL) return 0; switch (conf_iomode) { case IOMODE_READ: @@ -399,7 +399,7 @@ int VideoDevice_V4L2::GetFrame(VideoFrame *destframe) { } } else { - Convert(&cdata, destframe, inbuffer[0].data, len, + Convert(&cdata, destframe, destfloat, inbuffer[0].data, len, fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height); } break; @@ -426,7 +426,7 @@ int VideoDevice_V4L2::GetFrame(VideoFrame *destframe) { } if (buf.index >= 0 && buf.index < VDEV_INBUFFERS) { - Convert(&cdata, destframe, inbuffer[buf.index].data, buf.bytesused, + Convert(&cdata, destframe, destfloat, inbuffer[buf.index].data, buf.bytesused, fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height); } @@ -471,7 +471,7 @@ int VideoDevice_V4L2::SetDevCtrl(unsigned int id, int value) { CLEAR(ctrl); ctrl.id = id; ctrl.value = value; - if (-1 == xioctl (fd, VIDIOC_S_CTRL, &ctrl)) { + if (-1 == xioctl (cfd != -1 ? cfd : fd, VIDIOC_S_CTRL, &ctrl)) { return 0; } @@ -484,7 +484,7 @@ int VideoDevice_V4L2::GetDevCtrl(unsigned int id, int *value) { CLEAR(ctrl); ctrl.id = id; - if (-1 == xioctl (fd, VIDIOC_G_CTRL, &ctrl)) { + if (-1 == xioctl (cfd != -1 ? cfd : fd, VIDIOC_G_CTRL, &ctrl)) { return 0; } *value = ctrl.value; diff --git a/videodevice_v4l2.h b/videodevice_v4l2.h index 647d7b2..750b647 100644 --- a/videodevice_v4l2.h +++ b/videodevice_v4l2.h @@ -30,7 +30,7 @@ class VideoDevice_V4L2 : public VideoDevice { int SetIOMode(int newiomode); int Start(); int Stop(); - int GetFrame (VideoFrame *destframe); + int GetFrame (VideoFrame *destframe, VideoFrameFloat *destfloat); int SetDevCtrl(unsigned int id, int value); int GetDevCtrl(unsigned int id, int *value); diff --git a/videoframe.cc b/videoframe.cc index 9162193..72557b9 100644 --- a/videoframe.cc +++ b/videoframe.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include "videoframe.h" #include "inmemoryfile.h" @@ -57,6 +58,10 @@ int VideoFrame::SetSize(int w, int h) { }; +/// @brief converts image to jpeg. +/// @param imf ptr to in memory file +/// @param quality +/// @return 0 on error, 1 on success int VideoFrame::ConvertToJpeg(InMemoryFile *imf, int quality) { unsigned char *outbuffer = NULL; unsigned long int outbuffersize; @@ -80,7 +85,7 @@ int VideoFrame::ConvertToJpeg(InMemoryFile *imf, int quality) { jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); jpeg_start_compress(&cinfo, TRUE); - row_stride = width * 3; /* JSAMPLEs per row in image_buffer */ + row_stride = width * 3; /* JSAMPLEs per row in image_buffer (24bit image)*/ while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = & mem[cinfo.next_scanline * row_stride]; @@ -92,7 +97,7 @@ int VideoFrame::ConvertToJpeg(InMemoryFile *imf, int quality) { imf->CopyFrom(outbuffer, outbuffersize); free (outbuffer); - + return 1; }; @@ -161,18 +166,37 @@ int VideoFrame::CopyTo(VideoFrame *dest, int destw, int desth) { /*********************************************************************/ +VideoFrameFloat::VideoFrameFloat() { + memf = NULL; + memf_allocated = 0; + width = 0; + height = 0; +}; + + +VideoFrameFloat::~VideoFrameFloat() { + FreeFrame(); +}; + + +void VideoFrameFloat::FreeFrame() { + if (memf != NULL) free(memf); + memf = NULL; + memf_allocated = 0; +}; void VideoFrameFloat::AllocateFrame() { - printf ("VideoFrameFloat::AllocateFrame()\n"); int memnewsize = width * height * 3 * sizeof(float); - if (memnewsize >= mem_allocated) return; - else if (memnewsize == 0) FreeFrame(); - - mem = (unsigned char *) realloc (mem, memnewsize); - mem_allocated = memnewsize; + if (memnewsize < memf_allocated) return; + else if (memnewsize == 0) { + FreeFrame(); + return; + } - if (mem == NULL) { + memf = (float *) realloc (memf, memnewsize); + memf_allocated = memnewsize; + if (memf == NULL) { debug ("Error on allocation new frame\n"); exit (1); } @@ -180,3 +204,92 @@ void VideoFrameFloat::AllocateFrame() { +int VideoFrameFloat::TestScreen(int w, int h) { + int x, y; + float r, g, b; + + SetSize (w, h); + + r = g = b = 0.0; + for (x = 0; x < w; x++) { + for (g = 0, y = 0; y < h; y++) { + if (g ) + b = 0.5*(r + g); + + memf[3*(x + y * width) + 0] = r; + memf[3*(x + y * width) + 1] = g; + memf[3*(x + y * width) + 2] = b; + + g += 0.01; + } + r += 0.01; + } + + return 1; +} + + +int VideoFrameFloat::SetSize(int w, int h) { + if (w < 0 || h < 0) return 0; + + width = w; + height = h; + AllocateFrame(); + + return 1; +}; + + +int VideoFrameFloat::ConvertToJpeg(InMemoryFile *imf, int quality) { + VideoFrame vf; + + if (CopyTo (&vf) == 0) return 0; + return vf.ConvertToJpeg(imf, quality); +}; + + +int VideoFrameFloat::CopyTo(VideoFrame *dest) { + int x, y; + unsigned char *dptr; + float *sptr; + + if (dest == NULL || memf == NULL || width == 0 || height == 0) return 0; + dest->SetSize(width, height); + + for (sptr = memf, dptr = dest->GetPixBuf(), y = 0; y < height; y++) + for (x = 0; x < width*3; x++) { + *dptr = (unsigned char) (sqrtf(*sptr) * 255.0); + dptr++; + sptr++; + } + + return 1; +}; + + +int VideoFrameFloat::CopyTo(VideoFrameFloat *dest) { + if (memf == NULL || height == 0 || width == 0) return 0; + + if (dest->SetSize(width, height) == 0) return 0; + memcpy (dest->memf, memf, 3 * height * width * sizeof(float)); + + return 1; +}; + + +int VideoFrameFloat::AddScaledImage(VideoFrameFloat *vf, float f1, float f2) { + float *sptr, *dptr; + int x, y; + + if (vf->height != height || vf->width != width || memf == NULL || vf->memf == NULL) return 0; + + for (dptr = memf, sptr = vf->GetPixBuf(), y = 0; y < height; y++) + for (x = 0; x < width*3; x++) { + *dptr = f1 * (*dptr) + f2 * (*sptr); + dptr++; + sptr++; + } + + return 1; +}; + diff --git a/videoframe.h b/videoframe.h index 1c2d93e..2fdfd21 100644 --- a/videoframe.h +++ b/videoframe.h @@ -3,11 +3,11 @@ #include "inmemoryfile.h" // -// only contain 24bit each color 8Bit +// only contain 48bits each color with 16Bit class VideoFrame { private: - virtual void AllocateFrame(); protected: + void AllocateFrame(); void FreeFrame(); int mem_allocated; unsigned char *mem; @@ -29,11 +29,27 @@ class VideoFrame { }; -class VideoFrameFloat : public VideoFrame { +class VideoFrameFloat { private: - void AllocateFrame(); protected: + void AllocateFrame(); + void FreeFrame(); + int height; + int width; + int memf_allocated; + float *memf; public: + VideoFrameFloat(); + ~VideoFrameFloat(); + + int SetSize(int w, int h); + int TestScreen(int w, int h); + float *GetPixBuf() { return memf; }; + int ConvertToJpeg(InMemoryFile *imf, int quality); + int CopyTo(VideoFrame *dest); + int CopyTo(VideoFrameFloat *dest); + + int AddScaledImage(VideoFrameFloat *vf, float f1, float f2); }; diff --git a/webserver.cc b/webserver.cc index e0aca12..d3601e4 100644 --- a/webserver.cc +++ b/webserver.cc @@ -30,6 +30,15 @@ int WebCamServer::HandleRequest (WebRequestBuffer *requestbuffer, WebServerClien (void*) jpgfile.mem, jpgfile.memsize) != 1) return 0; } + else if (request.find("/snapshot-float.jpg") != std::string::npos) { + InMemoryFile jpgfile; + Lock(); + currentimagefloat.ConvertToJpeg(&jpgfile, 99); + UnLock(); + if (webclient->SendResponseFileFromMemory(requestbuffer, request, "", + (void*) jpgfile.mem, + jpgfile.memsize) != 1) return 0; + } else { return 0; } @@ -42,13 +51,18 @@ int WebCamServer::HandleRequest (WebRequestBuffer *requestbuffer, WebServerClien std::string GenerateHtmlFile() { std::string res; res = "MiniWebCam"; - res += ""; + res += "
"; + res += ""; res += "