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.
SimpleSkyCam/videoframe.cc

320 lines
6.3 KiB

#include <errno.h>
#include <string.h>
#include "video.h"
#include "config.h"
#include "gui.h"
#include "error.h"
#include "convert.h"
#include "videodev.h"
VideoFrameRaw::VideoFrameRaw() {
size = 0;
data = NULL;
w = 0;
h = 0;
pixfmt = 0x0;
}
VideoFrameRaw::~VideoFrameRaw() {
if (data != NULL) {
free (data);
data = NULL;
}
}
int VideoFrameRaw::CopyFrom(int spixfmt, int sw, int sh, int ssize, unsigned char *sdata) {
if (size != ssize) {
if (ReAlloc(ssize) != 0) {
errorexit((char*) "%s:%d %s could not reallocate memory. Error:%s\n",
__FILE__, __LINE__, __FUNCTION__, strerror(errno));
}
}
if (data == NULL) {
errorexit((char*) "%s:%d %s invalid pointer of data. Error:%s\n",
__FILE__, __LINE__, __FUNCTION__, strerror(errno));
}
w = sw;
h = sh;
pixfmt = spixfmt;
memcpy (data, sdata, ssize);
/* int i, x, y, d;
for (y = 0; y < w; y++) for (x = 0; x < w; x++) {
for (i = 0, d = 0; i < 4; i++) {
d += data[4* (y*w+x)];
}
if (d > 1000) printf ("%d,%d -> %d\n", x, y, d);
}
*/
return 1;
}
int VideoFrameRaw::CopyFrom(VideoFrameRaw *src) {
if (src == NULL) return 0;
return CopyFrom(src->pixfmt, src->w, src->h, src->size, src->data);
}
int VideoFrameRaw::CopyFrom(VideoFrame *src) {
if (src == NULL) return 0;
return CopyFrom(V4L2_PIX_FMT_RGB24, src->w, src->h, src->size, src->data);
}
int VideoFrameRaw::ReAlloc(int newsize) {
unsigned char *newdata = NULL;
if (newsize == 0) {
free (data);
data = NULL;
size = newsize;
return 0;
}
if (data == NULL) {
if ((data = (unsigned char*) malloc (newsize)) == NULL) return -1;
}
else if (size < newsize || size > newsize) {
if ((newdata = (unsigned char*) realloc (data, newsize)) == NULL) {
free (data);
size = 0;
return -1;
}
data = newdata;
}
size = newsize;
return 0;
}
int VideoFrameRaw::RectCopyFrom(VideoFrameRaw *src, int rectx, int recty, int rectw, int recth) {
int res = 0;
pixfmt = src->pixfmt;
res = PixCopy (src->data, src->pixfmt, src->w, src->h,
&data, &size, &w, &h,
rectx, recty, rectw, recth);
/*
for (int i = 0; i < size; i++) if (data[i] > 0) {
printf ("%s:%d found data in destination.\n", __FILE__, __LINE__);
break;
}
for (int i = 0; i < src->size; i++) if (src->data[i] > 0) {
printf ("%s:%d found data in source.\n", __FILE__, __LINE__);
break;
}
int bytesperpixel = 3;
int dsize = 0;
switch (src->pixfmt) {
case (V4L2_PIX_FMT_SGRBG8):
bytesperpixel = 2;
break;
case (V4L2_PIX_FMT_BGR32):
case (V4L2_PIX_FMT_RGB32):
case (V4L2_PIX_FMT_SGRBG16):
bytesperpixel = 4;
break;
case (V4L2_PIX_FMT_BGR24):
case (V4L2_PIX_FMT_RGB24):
bytesperpixel = 3;
break;
default:
return 0;
}
*/
return res;
}
#define VIDEOFRAME_DEPTH_BYTES 3
VideoFrame::VideoFrame() {
data = NULL;
w = 0;
h = 0;
size = 0;
};
VideoFrame::~VideoFrame() {
if (data) {
free (data);
data = NULL;
}
w = 0;
h = 0;
size = 0;
};
//
// we will only allocate a new image if the needed size increases
void VideoFrame::SetSize(int nw, int nh) {
uint32_t newsize = VIDEOFRAME_DEPTH_BYTES * nh * nw;
if (newsize > size || data == NULL) {
unsigned char *newdata = (unsigned char *) malloc (newsize);
if (data != NULL) free (data);
data = newdata;
size = newsize;
}
w = nw;
h = nh;
};
VideoFrame VideoFrame::operator=(VideoFrame rightside) {
w = rightside.w;
h = rightside.h;
size = rightside.size;
if (size > 0) data = (unsigned char *) malloc (rightside.size);
if (rightside.data != NULL && size > 0) {
memcpy (data, rightside.data, size);
}
return *this;
}
void VideoFrame::CopyFrom(VideoFrame *source) {
SetSize (source->w, source->h);
memcpy(data, source->data, VIDEOFRAME_DEPTH_BYTES * w * h);
}
void VideoFrame::CopyFrom(FloatImage *source) {
float min, max, f;
int x, y, i, idx;
unsigned char v;
SetSize (source->w, source->h);
// find min max;
min = source->data[0];
max = source->data[0];
for (y = 0; y < h; y++) for (x = 0; x < w; x++)
for (i = 0; i < 3; i++) {
idx = 3 * (y * w + x);
if (min > source->data[idx+i]) min = source->data[idx+i];
if (max < source->data[idx+i]) max = source->data[idx+i];
}
for (y = 0; y < h; y++) for (x = 0; x < w; x++)
for (i = 0; i < 3; i++) {
idx = 3 * (y * w + x);
f = (float)(255.0 * (source->data[idx+i]-min) / (max-min));
if (f < 0.0) v = 0;
else if (f > 255.0) v = 255;
else v = f;
data[idx+i] = v;
}
}
void VideoFrame::CopyTo(FloatImage *dest) {
int x, y, i, idx;
if (dest == NULL) return;
dest->SetSize (w, h);
for (y = 0; y < h; y++) for (x = 0; x < w; x++)
for (i = 0; i < 3; i++) {
idx = 3 * (y * w + x);
dest->data[idx+i] = data[idx+i];
}
}
void VideoFrame::ToPixbuf(GdkPixbuf** dest) {
int destw, desth, bytelen;
unsigned char *destpixel;
if (dest == NULL) return;
desth = gdk_pixbuf_get_height(*dest);
destw = gdk_pixbuf_get_width(*dest);
// check if the memory allocation way ok.
if (destw != w || desth != h) {
g_object_unref (*dest);
*dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, false, 8, w, h);
}
// copy data
destpixel = gdk_pixbuf_get_pixels(*dest);
bytelen = gdk_pixbuf_get_byte_length(*dest);
if (bytelen < h * w * 3) {
printf ("******* Error: %s:%d bytelen (set to:%d) is not %d\n", __FILE__, __LINE__, bytelen, (h * w * 3));
printf ("******* please inform the maintainer of this project.\n");
printf ("******* this should not have happened at all.\n");
exit (-1);
}
memcpy (destpixel, data, 3*w*h);
}
FloatImage::FloatImage() {
data = NULL;
w = 0;
h = 0;
size = 0;
};
FloatImage::~FloatImage() {
if (data) {
free (data);
data = NULL;
}
w = 0;
h = 0;
size = 0;
};
//
// we will only allocate a new image if the needed size increases
void FloatImage::SetSize(int nw, int nh) {
uint32_t newsize = 3 * nh * nw * sizeof(float);
if (newsize > size || data == NULL) {
float *newdata = (float *) malloc (newsize);
if (data != NULL) free (data);
data = newdata;
size = newsize;
}
w = nw;
h = nh;
};
FloatImage FloatImage::operator=(FloatImage rightside) {
w = rightside.w;
h = rightside.h;
size = rightside.size;
if (size > 0) data = (float *) malloc (rightside.size);
if (rightside.data != NULL && size > 0) {
memcpy (data, rightside.data, size);
}
return *this;
}
void FloatImage::CopyFrom(FloatImage *source) {
SetSize (source->w, source->h);
memcpy(data, source->data, 3 * w * h);
}