Bug fixes and new implementations

- Video format MJPEG implemented (libjpeg/qimage)
- Inactive priorities are now skipped correctly (PriorityMuxer.cpp line 297)
- v4l configuration section replaced with an object (preparation for #542)
This commit is contained in:
Paulchen-Panther
2019-04-28 19:53:45 +02:00
parent 4aab0ad55c
commit 0a8af60726
15 changed files with 587 additions and 415 deletions

View File

@@ -10,3 +10,7 @@ target_link_libraries(v4l2-grabber
hyperion
${QT_LIBRARIES}
)
if (JPEG_FOUND)
target_link_libraries(v4l2-grabber ${JPEG_LIBRARY})
endif()

View File

@@ -16,11 +16,15 @@
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <hyperion/Hyperion.h>
#include <QDirIterator>
#include <QFileInfo>
#include "grabber/V4L2Grabber.h"
using namespace hyperion;
#define CLEAR(x) memset(&(x), 0, sizeof(x))
V4L2Grabber::V4L2Grabber(const QString & device
@@ -55,6 +59,10 @@ V4L2Grabber::V4L2Grabber(const QString & device
setPixelDecimation(pixelDecimation);
getV4Ldevices();
// listen for component change for build-in grabber only
if (Hyperion::_hyperion)
connect(Hyperion::getInstance(), &Hyperion::componentStateChanged, this, &V4L2Grabber::componentStateChanged);
// init
setDeviceVideoStandard(device, videoStandard);
}
@@ -70,11 +78,7 @@ void V4L2Grabber::uninit()
if (_initialized)
{
Debug(_log,"uninit grabber: %s", QSTRING_CSTR(_deviceName));
stop();
uninit_device();
close_device();
_initialized = false;
}
}
@@ -233,6 +237,9 @@ void V4L2Grabber::stop()
{
stop_capturing();
_streamNotifier->setEnabled(false);
uninit_device();
close_device();
_initialized = false;
Info(_log, "Stopped");
}
}
@@ -518,74 +525,109 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
// set the requested pixel format
switch (_pixelFormat)
{
case PIXELFORMAT_UYVY:
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
case PIXELFORMAT_UYVY:
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
break;
case PIXELFORMAT_YUYV:
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
case PIXELFORMAT_YUYV:
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
break;
case PIXELFORMAT_RGB32:
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
case PIXELFORMAT_RGB32:
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
break;
case PIXELFORMAT_NO_CHANGE:
default:
// No change to device settings
#ifdef HAVE_JPEG
case PIXELFORMAT_MJPEG:
{
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
fmt.fmt.pix.field = V4L2_FIELD_ANY;
}
break;
#endif
case PIXELFORMAT_NO_CHANGE:
default:
// No change to device settings
break;
}
// TODO Does never accept own sizes? use always _imageResampler instead
/*
// calc the size based on pixelDecimation
fmt.fmt.pix.width = fmt.fmt.pix.width / _pixelDecimation;
fmt.fmt.pix.height = fmt.fmt.pix.height / _pixelDecimation;
// set the settings
fmt.fmt.pix.width = _width;
fmt.fmt.pix.height = _height;
if (-1 == xioctl(VIDIOC_S_FMT, &fmt))
{
throw_errno_exception("VIDIOC_S_FMT");
return;
}
// get the format settings again
// (the size may not have been accepted without an error)
if (-1 == xioctl(VIDIOC_G_FMT, &fmt))
{
throw_errno_exception("VIDIOC_G_FMT");
return;
}
*/
// set the line length
_lineLength = fmt.fmt.pix.bytesperline;
// store width & height
// initialize current width and height
_width = fmt.fmt.pix.width;
_height = fmt.fmt.pix.height;
// display the used width and height
Debug(_log, "width=%d height=%d", _width, _height );
// Trying to set frame rate
struct v4l2_streamparm streamparms;
CLEAR(streamparms);
streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(VIDIOC_G_PARM, &streamparms))
{
throw_errno_exception("VIDIOC_G_PARM");
// continue
}
else
{
// Check the capability flag is set to V4L2_CAP_TIMEPERFRAME
if (streamparms.parm.capture.capability == V4L2_CAP_TIMEPERFRAME)
{
// Driver supports the feature. Set required framerate
streamparms.parm.capture.capturemode = V4L2_MODE_HIGHQUALITY;
streamparms.parm.capture.timeperframe.numerator = 1;
streamparms.parm.capture.timeperframe.denominator = 30;
if(-1 == xioctl(VIDIOC_S_PARM, &streamparms))
{
throw_errno_exception("VIDIOC_S_PARM");
return;
}
}
}
// set the line length
_lineLength = fmt.fmt.pix.bytesperline;
// check pixel format and frame size
switch (fmt.fmt.pix.pixelformat)
{
case V4L2_PIX_FMT_UYVY:
_pixelFormat = PIXELFORMAT_UYVY;
_frameByteSize = _width * _height * 2;
Debug(_log, "Pixel format=UYVY");
case V4L2_PIX_FMT_UYVY:
{
_pixelFormat = PIXELFORMAT_UYVY;
_frameByteSize = _width * _height * 2;
Debug(_log, "Pixel format=UYVY");
}
break;
case V4L2_PIX_FMT_YUYV:
_pixelFormat = PIXELFORMAT_YUYV;
_frameByteSize = _width * _height * 2;
Debug(_log, "Pixel format=YUYV");
case V4L2_PIX_FMT_YUYV:
{
_pixelFormat = PIXELFORMAT_YUYV;
_frameByteSize = _width * _height * 2;
Debug(_log, "Pixel format=YUYV");
}
break;
case V4L2_PIX_FMT_RGB32:
_pixelFormat = PIXELFORMAT_RGB32;
_frameByteSize = _width * _height * 4;
Debug(_log, "Pixel format=RGB32");
case V4L2_PIX_FMT_RGB32:
{
_pixelFormat = PIXELFORMAT_RGB32;
_frameByteSize = _width * _height * 4;
Debug(_log, "Pixel format=RGB32");
}
break;
default:
throw_exception("Only pixel formats UYVY, YUYV, and RGB32 are supported");
#ifdef HAVE_JPEG
case V4L2_PIX_FMT_MJPEG:
{
_pixelFormat = PIXELFORMAT_MJPEG;
Debug(_log, "Pixel format=MJPEG");
}
break;
#endif
default:
throw_exception("Only pixel formats UYVY, YUYV, and RGB32 are supported");
return;
}
@@ -714,107 +756,108 @@ int V4L2Grabber::read_frame()
{
struct v4l2_buffer buf;
switch (_ioMethod) {
case IO_METHOD_READ:
int size;
if ((size = read(_fileDescriptor, _buffers[0].start, _buffers[0].length)) == -1)
{
switch (errno)
switch (_ioMethod)
{
case IO_METHOD_READ:
int size;
if ((size = read(_fileDescriptor, _buffers[0].start, _buffers[0].length)) == -1)
{
case EAGAIN:
return 0;
switch (errno)
{
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
/* fall through */
default:
throw_errno_exception("read");
default:
throw_errno_exception("read");
return 0;
}
}
rc = process_image(_buffers[0].start, size);
break;
case IO_METHOD_MMAP:
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(VIDIOC_DQBUF, &buf))
{
switch (errno)
{
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
throw_errno_exception("VIDIOC_DQBUF");
return 0;
}
}
assert(buf.index < _buffers.size());
rc = process_image(_buffers[buf.index].start, buf.bytesused);
if (-1 == xioctl(VIDIOC_QBUF, &buf))
{
throw_errno_exception("VIDIOC_QBUF");
return 0;
}
}
rc = process_image(_buffers[0].start, size);
break;
break;
case IO_METHOD_MMAP:
CLEAR(buf);
case IO_METHOD_USERPTR:
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
if (-1 == xioctl(VIDIOC_DQBUF, &buf))
{
switch (errno)
if (-1 == xioctl(VIDIOC_DQBUF, &buf))
{
case EAGAIN:
return 0;
switch (errno)
{
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
/* fall through */
default:
throw_errno_exception("VIDIOC_DQBUF");
default:
throw_errno_exception("VIDIOC_DQBUF");
return 0;
}
}
for (size_t i = 0; i < _buffers.size(); ++i)
{
if (buf.m.userptr == (unsigned long)_buffers[i].start && buf.length == _buffers[i].length)
{
break;
}
}
rc = process_image((void *)buf.m.userptr, buf.bytesused);
if (-1 == xioctl(VIDIOC_QBUF, &buf))
{
throw_errno_exception("VIDIOC_QBUF");
return 0;
}
break;
}
assert(buf.index < _buffers.size());
rc = process_image(_buffers[buf.index].start, buf.bytesused);
if (-1 == xioctl(VIDIOC_QBUF, &buf))
{
throw_errno_exception("VIDIOC_QBUF");
return 0;
}
break;
case IO_METHOD_USERPTR:
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
if (-1 == xioctl(VIDIOC_DQBUF, &buf))
{
switch (errno)
{
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
throw_errno_exception("VIDIOC_DQBUF");
return 0;
}
}
for (size_t i = 0; i < _buffers.size(); ++i)
{
if (buf.m.userptr == (unsigned long)_buffers[i].start && buf.length == _buffers[i].length)
{
break;
}
}
rc = process_image((void *)buf.m.userptr, buf.bytesused);
if (-1 == xioctl(VIDIOC_QBUF, &buf))
{
throw_errno_exception("VIDIOC_QBUF");
return 0;
}
break;
}
}
catch (std::exception& e)
{
@@ -828,23 +871,101 @@ int V4L2Grabber::read_frame()
bool V4L2Grabber::process_image(const void *p, int size)
{
// We do want a new frame...
#ifdef HAVE_JPEG
if (size != _frameByteSize && _pixelFormat != PIXELFORMAT_MJPEG)
#else
if (size != _frameByteSize)
#endif
{
Error(_log, "Frame too small: %d != %d", size, _frameByteSize);
}
else
{
process_image(reinterpret_cast<const uint8_t *>(p));
process_image(reinterpret_cast<const uint8_t *>(p), size);
return true;
}
return false;
}
void V4L2Grabber::process_image(const uint8_t * data)
void V4L2Grabber::process_image(const uint8_t * data, int size)
{
Image<ColorRgb> image(0, 0);
_imageResampler.processImage(data, _width, _height, _lineLength, _pixelFormat, image);
Image<ColorRgb> image(_width, _height);
#ifdef HAVE_JPEG
if (_pixelFormat == PIXELFORMAT_MJPEG)
{
_decompress = new jpeg_decompress_struct;
_error = new errorManager;
_decompress->err = jpeg_std_error(&_error->pub);
_error->pub.error_exit = &errorHandler;
_error->pub.output_message = &outputHandler;
jpeg_create_decompress(_decompress);
if (setjmp(_error->setjmp_buffer))
{
jpeg_abort_decompress(_decompress);
jpeg_destroy_decompress(_decompress);
delete _decompress;
delete _error;
return;
}
jpeg_mem_src(_decompress, const_cast<uint8_t*>(data), size);
if (jpeg_read_header(_decompress, (bool) TRUE) != JPEG_HEADER_OK)
{
jpeg_abort_decompress(_decompress);
jpeg_destroy_decompress(_decompress);
delete _decompress;
delete _error;
return;
}
jpeg_start_decompress(_decompress);
QImage imageFrame = QImage(_decompress->output_width, _decompress->output_height, QImage::Format_RGB888);
int y = 0;
while (_decompress->output_scanline < _decompress->output_height)
{
uchar *row = imageFrame.scanLine(_decompress->output_scanline);
jpeg_read_scanlines(_decompress, &row, 1);
y++;
}
jpeg_finish_decompress(_decompress);
jpeg_destroy_decompress(_decompress);
delete _decompress;
delete _error;
if (imageFrame.isNull())
return;
QRect rect(_cropLeft, _cropTop, imageFrame.width() - _cropLeft - _cropRight, imageFrame.height() - _cropTop - _cropBottom);
imageFrame = imageFrame.copy(rect);
imageFrame = imageFrame.scaled(imageFrame.width() / _pixelDecimation, imageFrame.height() / _pixelDecimation,Qt::KeepAspectRatio);
if ((image.width() != unsigned(imageFrame.width())) && (image.height() != unsigned(imageFrame.height())))
image.resize(imageFrame.width(), imageFrame.height());
for (int y=0; y<imageFrame.height(); ++y)
{
for (int x=0; x<imageFrame.width(); ++x)
{
const QRgb inPixel = imageFrame.pixel(x,y);
ColorRgb & outPixel = image(x,y);
outPixel.red = (inPixel & 0xff0000) >> 16;
outPixel.green = (inPixel & 0xff00) >> 8;
outPixel.blue = (inPixel & 0xff);
}
}
}
else
#endif
_imageResampler.processImage(data, _width, _height, _lineLength, _pixelFormat, image);
if (_signalDetectionEnabled)
{
@@ -963,3 +1084,19 @@ void V4L2Grabber::setDeviceVideoStandard(QString device, VideoStandard videoStan
start();
}
}
void V4L2Grabber::componentStateChanged(const hyperion::Components component, bool enable)
{
if (component == COMP_V4L)
{
if (_initialized != enable)
{
if (enable)
{
if(init()) start();
}
else
uninit();
}
}
}

View File

@@ -294,7 +294,7 @@ void PriorityMuxer::setCurrentTime(void)
else
{
// timeoutTime of -100 is awaiting data (inactive); skip
if(infoIt->timeoutTime_ms >= -100)
if(infoIt->timeoutTime_ms > -100)
newPriority = qMin(newPriority, infoIt->priority);
// call timeTrigger when effect or color is running with timeout > 0, blacklist prio 255

View File

@@ -1,208 +1,200 @@
{
"type":"array",
"type" : "object",
"required" : true,
"title" : "edt_conf_v4l2_heading_title",
"minItems": 1,
"maxItems": 1,
"items":
"properties" :
{
"type" : "object",
"required" : true,
"title" : "edt_conf_v4l2_heading_title",
"properties" :
"device" :
{
"device" :
{
"type" : "string",
"title" : "edt_conf_v4l2_device_title",
"default" : "auto",
"minLength" : 4,
"required" : true,
"propertyOrder" : 1
},
"standard" :
{
"type" : "string",
"title" : "edt_conf_v4l2_standard_title",
"enum" : ["PAL","NTSC","SECAM","NO_CHANGE"],
"default" : "NO_CHANGE",
"options" : {
"enum_titles" : ["edt_conf_enum_PAL", "edt_conf_enum_NTSC", "edt_conf_enum_SECAM", "edt_conf_enum_NO_CHANGE"]
},
"required" : true,
"propertyOrder" : 2
},
"sizeDecimation" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_sizeDecimation_title",
"minimum" : 1,
"maximum" : 30,
"default" : 6,
"required" : true,
"propertyOrder" : 3
},
"cropLeft" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_cropLeft_title",
"minimum" : 0,
"default" : 0,
"append" : "edt_append_pixel",
"required" : true,
"propertyOrder" : 4
},
"cropRight" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_cropRight_title",
"minimum" : 0,
"default" : 0,
"append" : "edt_append_pixel",
"required" : true,
"propertyOrder" : 5
},
"cropTop" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_cropTop_title",
"minimum" : 0,
"default" : 0,
"append" : "edt_append_pixel",
"required" : true,
"propertyOrder" : 6
},
"cropBottom" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_cropBottom_title",
"minimum" : 0,
"default" : 0,
"append" : "edt_append_pixel",
"required" : true,
"propertyOrder" : 7
},
"signalDetection" :
{
"type" : "boolean",
"title" : "edt_conf_v4l2_signalDetection_title",
"default" : false,
"required" : true,
"propertyOrder" : 8
},
"redSignalThreshold" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_redSignalThreshold_title",
"minimum" : 0,
"maximum" : 100,
"default" : 5,
"append" : "edt_append_percent",
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 9
},
"greenSignalThreshold" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_greenSignalThreshold_title",
"minimum" : 0,
"maximum" : 100,
"default" : 5,
"append" : "edt_append_percent",
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 10
},
"blueSignalThreshold" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_blueSignalThreshold_title",
"minimum" : 0,
"maximum" : 100,
"default" : 5,
"append" : "edt_append_percent",
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 11
},
"sDVOffsetMin" :
{
"type" : "number",
"title" : "edt_conf_v4l2_sDVOffsetMin_title",
"minimum" : 0.0,
"maximum" : 1.0,
"default" : 0.25,
"step" : 0.01,
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 12
},
"sDVOffsetMax" :
{
"type" : "number",
"title" : "edt_conf_v4l2_sDVOffsetMax_title",
"minimum" : 0.0,
"maximum" : 1.0,
"default" : 0.75,
"step" : 0.01,
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 13
},
"sDHOffsetMin" :
{
"type" : "number",
"title" : "edt_conf_v4l2_sDHOffsetMin_title",
"minimum" : 0.0,
"maximum" : 1.0,
"default" : 0.25,
"step" : 0.01,
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 14
},
"sDHOffsetMax" :
{
"type" : "number",
"title" : "edt_conf_v4l2_sDHOffsetMax_title",
"minimum" : 0.0,
"maximum" : 1.0,
"default" : 0.75,
"step" : 0.01,
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 15
}
"type" : "string",
"title" : "edt_conf_v4l2_device_title",
"default" : "auto",
"minLength" : 4,
"required" : true,
"propertyOrder" : 1
},
"standard" :
{
"type" : "string",
"title" : "edt_conf_v4l2_standard_title",
"enum" : ["PAL","NTSC","SECAM","NO_CHANGE"],
"default" : "NO_CHANGE",
"options" : {
"enum_titles" : ["edt_conf_enum_PAL", "edt_conf_enum_NTSC", "edt_conf_enum_SECAM", "edt_conf_enum_NO_CHANGE"]
},
"required" : true,
"propertyOrder" : 2
},
"sizeDecimation" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_sizeDecimation_title",
"minimum" : 1,
"maximum" : 30,
"default" : 6,
"required" : true,
"propertyOrder" : 3
},
"cropLeft" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_cropLeft_title",
"minimum" : 0,
"default" : 0,
"append" : "edt_append_pixel",
"required" : true,
"propertyOrder" : 4
},
"cropRight" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_cropRight_title",
"minimum" : 0,
"default" : 0,
"append" : "edt_append_pixel",
"required" : true,
"propertyOrder" : 5
},
"cropTop" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_cropTop_title",
"minimum" : 0,
"default" : 0,
"append" : "edt_append_pixel",
"required" : true,
"propertyOrder" : 6
},
"cropBottom" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_cropBottom_title",
"minimum" : 0,
"default" : 0,
"append" : "edt_append_pixel",
"required" : true,
"propertyOrder" : 7
},
"signalDetection" :
{
"type" : "boolean",
"title" : "edt_conf_v4l2_signalDetection_title",
"default" : false,
"required" : true,
"propertyOrder" : 8
},
"redSignalThreshold" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_redSignalThreshold_title",
"minimum" : 0,
"maximum" : 100,
"default" : 5,
"append" : "edt_append_percent",
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 9
},
"greenSignalThreshold" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_greenSignalThreshold_title",
"minimum" : 0,
"maximum" : 100,
"default" : 5,
"append" : "edt_append_percent",
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 10
},
"blueSignalThreshold" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_blueSignalThreshold_title",
"minimum" : 0,
"maximum" : 100,
"default" : 5,
"append" : "edt_append_percent",
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 11
},
"sDVOffsetMin" :
{
"type" : "number",
"title" : "edt_conf_v4l2_sDVOffsetMin_title",
"minimum" : 0.0,
"maximum" : 1.0,
"default" : 0.25,
"step" : 0.01,
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 12
},
"sDVOffsetMax" :
{
"type" : "number",
"title" : "edt_conf_v4l2_sDVOffsetMax_title",
"minimum" : 0.0,
"maximum" : 1.0,
"default" : 0.75,
"step" : 0.01,
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 13
},
"sDHOffsetMin" :
{
"type" : "number",
"title" : "edt_conf_v4l2_sDHOffsetMin_title",
"minimum" : 0.0,
"maximum" : 1.0,
"default" : 0.25,
"step" : 0.01,
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 14
},
"sDHOffsetMax" :
{
"type" : "number",
"title" : "edt_conf_v4l2_sDHOffsetMax_title",
"minimum" : 0.0,
"maximum" : 1.0,
"default" : 0.75,
"step" : 0.01,
"options": {
"dependencies": {
"signalDetection": true
}
},
"required" : true,
"propertyOrder" : 15
}
},
"additionalProperties" : false
}
}

View File

@@ -121,6 +121,10 @@ void ImageResampler::processImage(const uint8_t * data, int width, int height, i
rgb.red = data[index+2];
}
break;
#ifdef HAVE_JPEG
case PIXELFORMAT_MJPEG:
break;
#endif
case PIXELFORMAT_NO_CHANGE:
Error(Logger::getInstance("ImageResampler"), "Invalid pixel format given");
break;