Added RAW8 support for SVB camera, fixed RGB24 format; also fixed RGB conversions

master
Stefan Jahn 3 years ago
parent 3a95c90f7c
commit eacab6a56d

@ -1,3 +1,8 @@
2022-12-04:
- RAW8 format support for SVB camera, also fixed RGB24 format
- many bug fixes for RGB conversions
- DNG and SER file format fixes
2022-11-29:
- Crash on invalid dumpfile solved.
- closing and reopening of windows is working now.

@ -21,6 +21,7 @@ uint32_t convert_pixelformats [] = {
V4L2_PIX_FMT_BGR24,
V4L2_PIX_FMT_UYVY,
V4L2_PIX_FMT_SGRBG16,
V4L2_PIX_FMT_SGRBG8,
0
};
@ -246,17 +247,17 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
/* read the pixel */
ptrsrc++;
r = *(ptrsrc++);
g = *(ptrsrc++);
b = *(ptrsrc++);
ptrsrc++;
/* only paint the image if the source is within the destination */
if (xd < dest->w) {
/* set the pixel */
*(ptrdst++) = b;
*(ptrdst++) = g;
*(ptrdst++) = r;
*(ptrdst++) = g;
*(ptrdst++) = b;
xd++;
}
}
@ -273,17 +274,17 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
/* read the pixel */
ptrsrc++;
b = *(ptrsrc++);
g = *(ptrsrc++);
r = *(ptrsrc++);
ptrsrc++;
/* only paint the image if the source is within the destination */
if (xd < dest->w) {
/* set the pixel */
*(ptrdst++) = b;
*(ptrdst++) = g;
*(ptrdst++) = r;
*(ptrdst++) = g;
*(ptrdst++) = b;
xd++;
}
}
@ -306,9 +307,9 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
/* only paint the image if the source is within the destination */
if (xd < dest->w) {
/* set the pixel */
*(ptrdst++) = b;
*(ptrdst++) = g;
*(ptrdst++) = r;
*(ptrdst++) = g;
*(ptrdst++) = b;
xd++;
}
}
@ -332,9 +333,9 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
/* only paint the image if the source is within the destination */
if (xd < dest->w) {
/* set the pixel */
*(ptrdst++) = b;
*(ptrdst++) = g;
*(ptrdst++) = r;
*(ptrdst++) = g;
*(ptrdst++) = b;
xd++;
}
}
@ -347,9 +348,18 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
break;
case (V4L2_PIX_FMT_SGRBG16):
printf ("%s:%d %s debayer:%d\n", __FILE__, __LINE__, __FUNCTION__, config.debayer_mode);
if (config.debayer_mode == 0) debayer_grbg16_simple ((uint16_t *)ptrsrc, srcw, srch, ptrdst, dest->w, dest->h);
else debayer_grbg16_bilinear ((uint16_t *)ptrsrc, srcw, srch, ptrdst, dest->w, dest->h);
printf ("%s:%d %s debayer:%d\n", __FILE__, __LINE__, __FUNCTION__, config.debayer_mode);
if (config.debayer_mode == 0)
debayer_grbg16_simple ((uint16_t *)ptrsrc, srcw, srch, ptrdst, dest->w, dest->h);
else
debayer_grbg16_bilinear ((uint16_t *)ptrsrc, srcw, srch, ptrdst, dest->w, dest->h);
break;
case (V4L2_PIX_FMT_SGRBG8):
if (config.debayer_mode == 0)
debayer_grbg8_simple ((uint8_t *)ptrsrc, srcw, srch, ptrdst, dest->w, dest->h);
else
debayer_grbg8_bilinear ((uint8_t *)ptrsrc, srcw, srch, ptrdst, dest->w, dest->h);
break;
case (V4L2_PIX_FMT_UYVY):
@ -373,9 +383,9 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
/* only paint the image if the source is within the destination */
if (xd < dest->w) {
/* set the pixel */
*(ptrdst++) = b;
*(ptrdst++) = g;
*(ptrdst++) = r;
*(ptrdst++) = g;
*(ptrdst++) = b;
xd++;
}
}

@ -66,7 +66,8 @@ void debayer_grbg16_simple (uint16_t * src, int src_w, int src_h,
#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 STORE *(dst++) = BITCONV(r); *(dst++) = BITCONV(g); *(dst++) = BITCONV(b); src++;
#define STORE8 *(dst++) = (r & 0xff); *(dst++) = (g & 0xff); *(dst++) = (b & 0xff); src++;
/*
@ -189,3 +190,177 @@ void debayer_grbg16_bilinear (uint16_t * src, int src_w, int src_h,
b = LE;
STORE;
}
/*
The function converts a 8bit GRBG 2x2 CFA coded image into an 8bit
RGB image by setting the missing RGB values to zero.
*/
void debayer_grbg8_simple (uint8_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h) {
// GG RR
// BB GG
uint8_t t;
uint8_t r, g, b;
int ys, yd, xs, xd;
for (ys = 0, yd = 0; ys < src_h && yd < dst_h; ys++, yd++) {
for (xs = 0, xd = 0; xs < src_w; xs++) {
/* read the pixel but only the higher 8bit, assuming data is little endian */
t = *(src++);
if (xs & 1) {
if (ys & 1) {
// lower right green pixel
b = 0; g = t; r = 0;
} else {
// upper right red pixel
b = 0; g = 0; r = t;
}
} else {
if (ys & 1) {
// lower left blue pixel
b = t; g = 0; r = 0;
} else {
// upper left green pixel
b = 0; g = t; r = 0;
}
}
/* only paint the image if the source is within the destination */
if (xd < dst_w) {
/* set the pixel */
*(dst++) = r;
*(dst++) = g;
*(dst++) = b;
xd++;
}
}
/* if the source image is too small ignore the other places */
if (xd < dst_w)
dst += 3 * (dst_w - xd);
}
}
/*
The function converts a 8bit GRBG 2x2 CFA coded image into an 8bit
RGB image by bilinear interpolation.
*/
void debayer_grbg8_bilinear (uint8_t * src, int src_w, int src_h,
uint8_t * dst, 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;
// 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;
// green pixel
r = (LE + RI) / 2;
g = CE;
b = DN;
STORE8;
}
// upper right pixel (red)
r = CE;
g = (DN + LE) / 2;
b = DNLE;
STORE8;
// 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;
for (xs = 1; xs < src_w - 1; xs+=2) {
// green pixel
r = (UP + DN) / 2;
g = CE;
b = (LE + RI) / 2;
STORE8;
// blue pixel
r = (UPLE + UPRI + DNLE + DNRI) / 4;
g = (LE + RI + UP + DN) / 4;
b = CE;
STORE8;
}
// last pixel in line (green)
r = (UP + DN) / 2;
g = CE;
b = LE;
STORE8;
// 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;
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;
// green pixel
r = (LE + RI) / 2;
g = CE;
b = (UP + DN) / 2;
STORE8;
}
// last pixel in line (red)
r = CE;
g = (UP + DN + LE) / 3;
b = (UPLE + DNLE) / 2;
STORE8;
}
// bottom left pixel
r = UPRI;
g = (UP + RI) / 2;
b = CE;
STORE8;
// 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;
// blue pixel
r = (UPLE + UPRI) / 2;
g = (LE + UP + RI) / 2;
b = CE;
STORE8;
}
// bottom right pixel (green)
r = UP;
g = CE;
b = LE;
STORE8;
}

@ -3,9 +3,12 @@
void debayer_grbg16_simple (uint16_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h);
void debayer_grbg8_simple (uint8_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h);
void debayer_grbg16_bilinear (uint16_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h);
void debayer_grbg8_bilinear (uint8_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h);
#endif

@ -117,7 +117,7 @@ int VideoDev_SVBCam::Open() {
Close();
return VDEV_STATUS_ERROR;
}
printf ("%s:%d %s height: %ld width: %ld\n", __FILE__, __LINE__, __FUNCTION__, camprop.MaxHeight, camprop.MaxWidth);
printf ("%s:%d %s MaxHeight: %ld MaxWidth: %ld\n", __FILE__, __LINE__, __FUNCTION__, camprop.MaxHeight, camprop.MaxWidth);
for(int i=0; i < 8 && camprop.SupportedVideoFormat[i] != SVB_IMG_END; i++) {
printf ("%s:%d %s VideoFormat Index:%d ", __FILE__, __LINE__, __FUNCTION__, i);
@ -162,7 +162,7 @@ int VideoDev_SVBCam::Open() {
printf("\t\tSVB_IMG_END\n");
break;
default:
printf ("\t\tunbekannt\n");
printf ("\t\tunknown\n");
break;
}
}
@ -178,7 +178,7 @@ int VideoDev_SVBCam::Open() {
print_error(err);
return VDEV_STATUS_ERROR;
}
printf ("%s:%d %s Got Control idx: %d name:%s desc:%s [%ld - %ld]\n", __FILE__, __LINE__, __FUNCTION__,
printf ("%s:%d %s Got Control idx:%d name:%s desc:%s [%ld - %ld]\n", __FILE__, __LINE__, __FUNCTION__,
i, camcontrols[i].Name, camcontrols[i].Description, (long)camcontrols[i].MinValue, (long)camcontrols[i].MaxValue);
vctl.name = (char*)camcontrols[i].Name;
vctl.id = i;
@ -209,26 +209,26 @@ int VideoDev_SVBCam::Open() {
return VDEV_STATUS_ERROR;
}
break;
case (V4L2_PIX_FMT_RGB32):
case (V4L2_PIX_FMT_BGR32):
if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB32)) != SVB_SUCCESS) {
print_error(err);
return VDEV_STATUS_ERROR;
}
break;
case (V4L2_PIX_FMT_RGB24):
if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB24)) != SVB_SUCCESS) {
print_error(err);
return VDEV_STATUS_ERROR;
}
break;
case (V4L2_PIX_FMT_BGR24):
if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB24)) != SVB_SUCCESS) {
print_error(err);
return VDEV_STATUS_ERROR;
}
break;
default:
conf_format = convert_from_pixelformat(V4L2_PIX_FMT_RGB24);
inframe_pixfmt = V4L2_PIX_FMT_RGB24;
if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB24)) != SVB_SUCCESS) {
print_error(err);
return VDEV_STATUS_ERROR;
}
break;
conf_format = convert_from_pixelformat(V4L2_PIX_FMT_BGR24);
inframe_pixfmt = V4L2_PIX_FMT_BGR24;
if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB24)) != SVB_SUCCESS) {
print_error(err);
return VDEV_STATUS_ERROR;
}
break;
}
@ -264,8 +264,8 @@ int VideoDev_SVBCam::Close() {
/*
* prepare inframe for raw picture data, will hold a video frame with 16bit per channel
* inframe size = 2*3*W*H
* prepare inframe for raw picture data, will hold a video frame with 16bit per channel or BGR32/BGR24
* inframe size = 4*W*H
* send the start capture signal to the cam
*/
int VideoDev_SVBCam::CaptureStart() {
@ -281,7 +281,7 @@ int VideoDev_SVBCam::CaptureStart() {
//
// allocate memory for frame data
if (inframe != NULL) free (inframe);
inframe_size = 6 * inframe_w * inframe_h;
inframe_size = 4 * inframe_w * inframe_h;
inframe = (unsigned char*) malloc(inframe_size);
ConvertStart(&cdata, inframe_pixfmt);
@ -368,14 +368,53 @@ int VideoDev_SVBCam::GetDeviceFormats(string device, std::list<string> *formats)
Close();
return VDEV_STATUS_ERROR;
}
printf ("%s:%d %s height: %ld width: %ld maxdepth:%d BayerPattern:%d\n", __FILE__, __LINE__, __FUNCTION__, camprop.MaxHeight,
camprop.MaxWidth, camprop.MaxBitDepth, camprop.BayerPattern);
printf ("%s:%d %s MaxHeight:%ld MaxWidth:%ld MaxDepth:%d\n", __FILE__, __LINE__, __FUNCTION__, camprop.MaxHeight,
camprop.MaxWidth, camprop.MaxBitDepth);
char pattern[5];
switch(camprop.BayerPattern) {
case SVB_BAYER_RG:
strcpy(pattern, "RGGB");
break;
case SVB_BAYER_BG:
strcpy(pattern, "BGGR");
break;
case SVB_BAYER_GR:
strcpy(pattern, "GRBG");
break;
case SVB_BAYER_GB:
strcpy(pattern, "GBRG");
break;
default:
strcpy(pattern, "NONE");
break;
}
printf ("%s:%d %s BayerPattern:%s Color:%d Binning: \n", __FILE__, __LINE__, __FUNCTION__, pattern, camprop.IsColorCam);
for(int i=0; i < 16 && camprop.SupportedBins[i] != 0; i++) {
printf ("%s:%d %s Binning Index:%d ", __FILE__, __LINE__, __FUNCTION__, i);
printf ("\t\%dx%d\n", camprop.SupportedBins[i], camprop.SupportedBins[i]);
}
for(int i=0; i < 8 && camprop.SupportedVideoFormat[i] != SVB_IMG_END; i++) {
printf ("%s:%d %s VideoFormat Index:%d ", __FILE__, __LINE__, __FUNCTION__, i);
switch (camprop.SupportedVideoFormat[i]) {
case SVB_IMG_RAW8:
printf("\t\tSVB_IMG_RAW8\n");
switch(camprop.BayerPattern) {
case SVB_BAYER_RG:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SRGGB8));
break;
case SVB_BAYER_BG:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SBGGR8));
break;
case SVB_BAYER_GR:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SGRBG8));
break;
case SVB_BAYER_GB:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SGBRG8));
break;
default:
break;
}
break;
case SVB_IMG_RAW10:
printf("\t\tSVB_IMG_RAW10\n");
@ -388,7 +427,22 @@ int VideoDev_SVBCam::GetDeviceFormats(string device, std::list<string> *formats)
break;
case SVB_IMG_RAW16:
printf("\t\tSVB_IMG_RAW16\n");
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SGRBG16));
switch(camprop.BayerPattern) {
case SVB_BAYER_RG:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SRGGB16));
break;
case SVB_BAYER_BG:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SBGGR16));
break;
case SVB_BAYER_GR:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SGRBG16));
break;
case SVB_BAYER_GB:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SGBRG16));
break;
default:
break;
}
break;
case SVB_IMG_Y8:
printf("\t\tSVB_IMG_Y8\n");
@ -407,17 +461,17 @@ int VideoDev_SVBCam::GetDeviceFormats(string device, std::list<string> *formats)
break;
case SVB_IMG_RGB24:
printf("\t\tSVB_IMG_RGB24\n");
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_RGB24));
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_BGR24));
break;
case SVB_IMG_RGB32:
printf("\t\tSVB_IMG_RGB32\n");
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_RGB32));
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_BGR32));
break;
case SVB_IMG_END:
printf("\t\tSVB_IMG_END\n");
break;
default:
printf ("\t\tunbekannt\n");
printf ("\t\tunknown\n");
break;
}
}

Loading…
Cancel
Save