color decoding added; size decimation added

Former-commit-id: ca3a959a4e842c86978855b005f97ce7a383a4fd
This commit is contained in:
johan 2014-01-12 16:28:41 +01:00
parent 421ec6926f
commit 545f2ee114
2 changed files with 90 additions and 14 deletions

View File

@ -19,6 +19,24 @@
#define CLEAR(x) memset(&(x), 0, sizeof(x)) #define CLEAR(x) memset(&(x), 0, sizeof(x))
static inline uint8_t clamp(int x)
{
return (x<0) ? 0 : ((x>255) ? 255 : uint8_t(x));
}
static void yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t & r, uint8_t & g, uint8_t & b)
{
// see: http://en.wikipedia.org/wiki/YUV#Y.27UV444_to_RGB888_conversion
int c = y - 16;
int d = u - 128;
int e = v - 128;
r = clamp((298 * c + 409 * e + 128) >> 8);
g = clamp((298 * c - 100 * d - 208 * e + 128) >> 8);
b = clamp((298 * c + 516 * d + 128) >> 8);
}
V4L2Grabber::V4L2Grabber(const std::string &device, int input, VideoStandard videoStandard, int frameDecimation, int pixelDecimation) : V4L2Grabber::V4L2Grabber(const std::string &device, int input, VideoStandard videoStandard, int frameDecimation, int pixelDecimation) :
_deviceName(device), _deviceName(device),
_ioMethod(IO_METHOD_MMAP), _ioMethod(IO_METHOD_MMAP),
@ -26,8 +44,8 @@ V4L2Grabber::V4L2Grabber(const std::string &device, int input, VideoStandard vid
_buffers(), _buffers(),
_width(0), _width(0),
_height(0), _height(0),
_frameDecimation(frameDecimation), _frameDecimation(std::max(1, frameDecimation)),
_pixelDecimation(pixelDecimation), _pixelDecimation(std::max(1, pixelDecimation)),
_currentFrame(0) _currentFrame(0)
{ {
open_device(); open_device();
@ -569,15 +587,24 @@ void V4L2Grabber::process_image(const uint8_t * data)
{ {
std::cout << "process image" << std::endl; std::cout << "process image" << std::endl;
QImage image(_width, _height, QImage::Format_RGB888); int width = (_width + _pixelDecimation/2) / _pixelDecimation;
int height = (_height + _pixelDecimation/2) / _pixelDecimation;
for (int y = 0; y < image.height(); ++y) QImage image(width, height, QImage::Format_RGB888);
for (int ySource = _pixelDecimation/2, yDest = 0; ySource < _height; ySource += _pixelDecimation, ++yDest)
{ {
for (int x = 0; x < image.width(); ++x) for (int xSource = _pixelDecimation/2, xDest = 0; xSource < _width; xSource += _pixelDecimation, ++xDest)
{ {
uint8_t value = data[(image.width() * y + x) * 2 + 1]; int index = (_width * ySource + xSource) * 2;
//std::cout << "data = " << int(value) << std::endl; uint8_t y = data[index+1];
image.setPixel(x, y, qRgb(value, value, value)); uint8_t u = (xSource%2 == 0) ? data[index] : data[index-2];
uint8_t v = (xSource%2 == 0) ? data[index+2] : data[index];
uint8_t r, g, b;
yuv2rgb(y, u, v, r, g, b);
image.setPixel(xDest, yDest, qRgb(r, g, b));
} }
} }

View File

@ -13,6 +13,39 @@
using namespace vlofgren; using namespace vlofgren;
/// Data parameter for the video standard
typedef vlofgren::PODParameter<V4L2Grabber::VideoStandard> VideoStandardParameter;
namespace vlofgren {
/// Translates a string (as passed on the commandline) to a color standard
///
/// @param[in] s The string (as passed on the commandline)
/// @return The color standard
/// @throws Parameter::ParameterRejected If the string did not result in a video standard
template<>
V4L2Grabber::VideoStandard VideoStandardParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
{
QString input = QString::fromStdString(s).toLower();
if (input == "pal")
{
return V4L2Grabber::PAL;
}
else if (input == "ntsc")
{
return V4L2Grabber::NTSC;
}
else if (input == "no-change")
{
return V4L2Grabber::NO_CHANGE;
}
throw Parameter::ParameterRejected("Invalid value for video standard. Valid values are: PAL, NTSC, and NO-CHANGE");
return V4L2Grabber::NO_CHANGE;
}
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
try try
@ -21,7 +54,17 @@ int main(int argc, char** argv)
OptionsParser optionParser("Simple application to send a command to hyperion using the Json interface"); OptionsParser optionParser("Simple application to send a command to hyperion using the Json interface");
ParameterSet & parameters = optionParser.getParameters(); ParameterSet & parameters = optionParser.getParameters();
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<> >('h', "help", "Show this help message and exit"); StringParameter & argDevice = parameters.add<StringParameter> ('d', "device", "The device to use [default=/dev/video0]");
VideoStandardParameter & argVideoStandard = parameters.add<VideoStandardParameter>('v', "video-standard", "The used video standard. Valid values are PAL. NYSC, or NO-CHANGE [default=PAL]");
IntParameter & argInput = parameters.add<IntParameter> ('i', "input", "Input channel [default=0]");
IntParameter & argSizeDecimation = parameters.add<IntParameter> ('s', "size-decimator", "Decimation factor for the output size [default=1]");
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<> > ('h', "help", "Show this help message and exit");
// set defaults
argDevice.setDefault("/dev/video0");
argVideoStandard.setDefault(V4L2Grabber::PAL);
argInput.setDefault(0);
argSizeDecimation.setDefault(1);
// parse all options // parse all options
optionParser.parse(argc, const_cast<const char **>(argv)); optionParser.parse(argc, const_cast<const char **>(argv));
@ -32,6 +75,17 @@ int main(int argc, char** argv)
optionParser.usage(); optionParser.usage();
return 0; return 0;
} }
V4L2Grabber grabber(
argDevice.getValue(),
argInput.getValue(),
argVideoStandard.getValue(),
1,
argSizeDecimation.getValue());
grabber.start();
grabber.capture(1);
grabber.stop();
} }
catch (const std::runtime_error & e) catch (const std::runtime_error & e)
{ {
@ -40,10 +94,5 @@ int main(int argc, char** argv)
return 1; return 1;
} }
V4L2Grabber grabber("/dev/video0", 0, V4L2Grabber::PAL, 25, 8);
grabber.start();
grabber.capture(250);
grabber.stop();
return 0; return 0;
} }