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.
296 lines
6.6 KiB
296 lines
6.6 KiB
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <jpeglib.h>
|
|
#include <UDPTCPNetwork.h>
|
|
#include <math.h>
|
|
|
|
#include "videoframe.h"
|
|
#include "inmemoryfile.h"
|
|
|
|
VideoFrame::VideoFrame() {
|
|
mem = NULL;
|
|
width = 0;
|
|
height = 0;
|
|
mem_allocated = 0;
|
|
};
|
|
|
|
VideoFrame::~VideoFrame() {
|
|
FreeFrame();
|
|
};
|
|
|
|
|
|
void VideoFrame::FreeFrame() {
|
|
if (mem != NULL) {
|
|
free (mem);
|
|
mem = NULL;
|
|
width = 0;
|
|
height = 0;
|
|
mem_allocated = 0;
|
|
}
|
|
};
|
|
|
|
|
|
void VideoFrame::AllocateFrame() {
|
|
int memnewsize = width * height * 3;
|
|
if (memnewsize < mem_allocated) return;
|
|
else if (memnewsize == 0) FreeFrame();
|
|
|
|
mem = (unsigned char *) realloc (mem, memnewsize);
|
|
mem_allocated = memnewsize;
|
|
|
|
if (mem == NULL) {
|
|
debug ("Error on allocation new frame\n");
|
|
exit (1);
|
|
}
|
|
};
|
|
|
|
|
|
int VideoFrame::SetSize(int w, int h) {
|
|
if (w < 0 && h < 0) return 0;
|
|
|
|
width = w;
|
|
height = h;
|
|
|
|
AllocateFrame();
|
|
|
|
return 1;
|
|
};
|
|
|
|
|
|
/// @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;
|
|
struct jpeg_compress_struct cinfo;
|
|
struct jpeg_error_mgr jerr;
|
|
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
|
int row_stride; /* physical row width in image buffer */
|
|
|
|
if (imf == NULL) return 0;
|
|
if (height == 0 || width == 0) return 0;
|
|
|
|
cinfo.err = jpeg_std_error(&jerr);
|
|
jpeg_create_compress(&cinfo);
|
|
|
|
jpeg_mem_dest(&cinfo, &outbuffer, &outbuffersize);
|
|
|
|
cinfo.image_width = width; /* image width and height, in pixels */
|
|
cinfo.image_height = height;
|
|
cinfo.input_components = 3; /* # of color components per pixel */
|
|
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
|
|
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 (24bit image)*/
|
|
|
|
while (cinfo.next_scanline < cinfo.image_height) {
|
|
row_pointer[0] = & mem[cinfo.next_scanline * row_stride];
|
|
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
|
|
}
|
|
|
|
jpeg_finish_compress(&cinfo);
|
|
jpeg_destroy_compress(&cinfo);
|
|
|
|
imf->CopyFrom(outbuffer, outbuffersize);
|
|
free (outbuffer);
|
|
|
|
return 1;
|
|
};
|
|
|
|
|
|
int VideoFrame::TestScreen(int w, int h) {
|
|
int x, y;
|
|
unsigned char r, g, b;
|
|
|
|
SetSize (w, h);
|
|
|
|
r = g = b = 0;
|
|
for (x = 0; x < w; x++) {
|
|
for (g = 0, y = 0; y < h; y++) {
|
|
b = r + g;
|
|
|
|
mem[3*(x + y * width) + 0] = r;
|
|
mem[3*(x + y * width) + 1] = g;
|
|
mem[3*(x + y * width) + 2] = b;
|
|
|
|
g++;
|
|
}
|
|
r ++;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
int VideoFrame::CopyTo(VideoFrame *dest, int destw, int desth) {
|
|
unsigned char *destptr;
|
|
if (dest == NULL) return 0;
|
|
|
|
if (destw <= 0 || desth <= 0) {
|
|
destw = width;
|
|
desth = height;
|
|
}
|
|
|
|
dest->SetSize(destw, desth);
|
|
destptr = dest->GetPixBuf();
|
|
if (destptr == NULL) return 0;
|
|
|
|
float scale_x = (float)width / destw;
|
|
float scale_y = (float)height / desth;
|
|
|
|
for (int dy = 0; dy < dest->height; ++dy) {
|
|
for (int dx = 0; dx < dest->width; ++dx) {
|
|
// Map destination coordinates back to source coordinates
|
|
int sx = (int)(dx * scale_x);
|
|
int sy = (int)(dy * scale_y);
|
|
|
|
// Bounds checking (should be unnecessary with correct scale calculation)
|
|
if (sx >= width) sx = width - 1;
|
|
if (sy >= height) sy = height - 1;
|
|
|
|
// Calculate byte index in the source and destination buffers
|
|
int src_idx = 3*((sy * width) + sx);
|
|
int dest_idx = 3*((dy * destw) + dx);
|
|
|
|
// Copy the pixel data (e.g., all 3 RGB bytes)
|
|
memcpy(&destptr[dest_idx], &mem[src_idx], 3);
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
};
|
|
|
|
/*********************************************************************/
|
|
|
|
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() {
|
|
int memnewsize = width * height * 3 * sizeof(float);
|
|
if (memnewsize < memf_allocated) return;
|
|
else if (memnewsize == 0) {
|
|
FreeFrame();
|
|
return;
|
|
}
|
|
|
|
memf = (float *) realloc (memf, memnewsize);
|
|
memf_allocated = memnewsize;
|
|
if (memf == NULL) {
|
|
debug ("Error on allocation new frame\n");
|
|
exit (1);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
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 ratio) {
|
|
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 = (1.0-ratio) * (*dptr) + ratio * (*sptr);
|
|
dptr++;
|
|
sptr++;
|
|
}
|
|
|
|
return 1;
|
|
};
|
|
|