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.

241 lines
5.4 KiB

#include "vidoiltank.h"
//
// jpeg: replacement for error_exit
//
METHODDEF(void) jpg_error_exit (j_common_ptr cinfo) {
jpg_error_ptr myerr = (jpg_error_ptr) cinfo->err;
(*cinfo->err->output_message) (cinfo);
longjmp(myerr->setjmp_buffer, 1);
}
//
// clamp and convert2rgb is build on the sample of the v4l2 api documentation
//
inline unsigned char clamp (double x) {
int r = (int)x;
if (r < 0) return 0;
else if (r > 255) return 255;
else return r;
};
inline void convert2rgb (unsigned char Y1, unsigned char Cb, unsigned char Cr,
unsigned char *ER, unsigned char *EB, unsigned char *EG) {
register int y1, pb, pr;
y1 = Y1 - 16;
pb = Cb - 128;
pr = Cr - 128;
*ER = clamp (y1 + 1.402 * pr);
*EB = clamp (y1 - 0.344 * pb - 0.714 * pr);
*EG = clamp (y1 + 1.772 * pb);
};
int convert (struct jpeg_decompress_struct *cdata, ImageRaw *dest, 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;
struct jpg_error_mgr jerr;
if (cdata == NULL) return -1;
// check if there is a destination and that the destination is large to keep
// the full image
if (dest == NULL || ptrsrc == NULL)
return -1;
if (dest->data != NULL && dest->w != srcw && dest->h != srch) {
free (dest->data);
dest->data = NULL;
}
if (dest->data == NULL) {
dest->w = srcw;
dest->h = srch;
dest->size = srcw * srch * 3;
dest->data = (unsigned char*) malloc (dest->size);
}
ptrdst = dest->data;
switch (pixelformat) {
case (V4L2_PIX_FMT_RGB32):
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
/* read the pixel */
ptrsrc++;
r = *(ptrsrc++);
g = *(ptrsrc++);
b = *(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;
xd++;
}
}
/* if the source image is too small ignore the other places.. */
if (xd < dest->w)
ptrdst += 3 * (dest->w - xd);
yd++;
}
break;
case (V4L2_PIX_FMT_BGR32):
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
/* read the pixel */
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;
xd++;
}
}
/* if the source image is too small ignore the other places.. */
if (xd < dest->w)
ptrdst += 3 * (dest->w - xd);
yd++;
}
break;
case (V4L2_PIX_FMT_UYVY):
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
/* read the pixel */
if (xs & 1) {
y1 = (unsigned char)*(ptrsrc + 1);
cr = (unsigned char)*(ptrsrc);
cb = (unsigned char)*(ptrsrc - 2);
}
else {
y1 = (unsigned char)*(ptrsrc + 1);
cr = (unsigned char)*(ptrsrc + 2);
cb = (unsigned char)*(ptrsrc);
}
convert2rgb (y1, cr, cb, &r, &g, &b);
ptrsrc += 2;
/* only paint the image if the source is within the destination */
if (xd < dest->w) {
/* set the pixel */
*(ptrdst++) = b;
*(ptrdst++) = g;
*(ptrdst++) = r;
xd++;
}
}
/* if the source image is too small ignore the other places.. */
if (xd < dest->w)
ptrdst += 3 * (dest->w - xd);
yd++;
}
break;
case (V4L2_PIX_FMT_YUYV):
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
if (yd < dest->h) {
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
/* read the pixel */
if (xs & 1) {
y1 = *(ptrsrc);
cb = *(ptrsrc + 1);
cr = *(ptrsrc - 1);
}
else {
y1 = *(ptrsrc);
cb = *(ptrsrc + 3);
cr = *(ptrsrc + 1);
}
convert2rgb (y1, cr, cb, &r, &g, &b);
ptrsrc += 2;
/* only paint the image if the source is within the destination */
if (xd < dest->w) {
/* set the pixel */
*(ptrdst++) = r;
*(ptrdst++) = g;
*(ptrdst++) = b;
xd++;
}
}
/* if the source image is too small ignore the other places.. */
if (xd < dest->w)
ptrdst += 3 * (dest->w - xd);
yd++;
}
}
break;
case (V4L2_PIX_FMT_MJPEG):
cdata->err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = jpg_error_exit;
if (setjmp(jerr.setjmp_buffer)) {
// jpeg data and allocations will be destroyed via StopCapture.
printf ("%s:%d %s JPEG Error\n", __FILE__, __LINE__, __FUNCTION__);
return -1;
}
jpeg_mem_src(cdata, ptrsrc, srcsize);
jpeg_read_header(cdata, TRUE);
jpeg_start_decompress(cdata);
while (cdata->output_scanline < cdata->output_height) {
unsigned char *temp_array[] = {ptrdst + (cdata->output_scanline) * srcw * 3};
jpeg_read_scanlines(cdata, temp_array, 1);
}
jpeg_finish_decompress(cdata);
break;
default:
break;
}
return 0;
};
int convertstart(struct jpeg_decompress_struct *cdata, uint32_t pixelformat) {
if (cdata == NULL) return -1;
if (pixelformat == V4L2_PIX_FMT_MJPEG) {
jpeg_create_decompress(cdata);
}
return 0;
};
int convertstop(struct jpeg_decompress_struct *cdata, uint32_t pixelformat) {
if (cdata == NULL) return -1;
if (pixelformat == V4L2_PIX_FMT_MJPEG) jpeg_destroy_decompress(cdata);
return 0;
};