300 lines
9.9 KiB
C++
300 lines
9.9 KiB
C++
// Media.cpp
|
||
#include "Media.h"
|
||
|
||
// YUV 转换为 RGB 的辅助函数
|
||
void yuvToRgb(int y, int u, int v, int& r, int& g, int& b)
|
||
{
|
||
r = y + 1.402 * (v - 128);
|
||
g = y - 0.344136 * (u - 128) - 0.714136 * (v - 128);
|
||
b = y + 1.772 * (u - 128);
|
||
|
||
r = qBound(0, r, 255);
|
||
g = qBound(0, g, 255);
|
||
b = qBound(0, b, 255);
|
||
}
|
||
|
||
// 将 QImage 数据转换为 YUV422
|
||
QByteArray convertQImageToYUV422(const QImage& image)
|
||
{
|
||
int width = image.width();
|
||
int height = image.height();
|
||
QByteArray yuvData;
|
||
yuvData.resize(width * height * 2); // YUV422: 每个像素2字节
|
||
|
||
int index = 0;
|
||
for (int y = 0; y < height; ++y) {
|
||
for (int x = 0; x < width; x += 2) {
|
||
QRgb pixel0 = image.pixel(x, y);
|
||
QRgb pixel1 = image.pixel(x + 1, y);
|
||
|
||
int r0 = qRed(pixel0);
|
||
int g0 = qGreen(pixel0);
|
||
int b0 = qBlue(pixel0);
|
||
|
||
int r1 = qRed(pixel1);
|
||
int g1 = qGreen(pixel1);
|
||
int b1 = qBlue(pixel1);
|
||
|
||
// 计算YUV值
|
||
int y0 = (0.299 * r0 + 0.587 * g0 + 0.114 * b0);
|
||
int u = (-0.169 * r0 - 0.331 * g0 + 0.5 * b0 + 128);
|
||
int y1 = (0.299 * r1 + 0.587 * g1 + 0.114 * b1);
|
||
int v = (0.5 * r0 - 0.419 * g0 - 0.081 * b0 + 128);
|
||
|
||
yuvData[index++] = static_cast<char>(qBound(0, y0, 255));
|
||
yuvData[index++] = static_cast<char>(qBound(0, u, 255));
|
||
yuvData[index++] = static_cast<char>(qBound(0, y1, 255));
|
||
yuvData[index++] = static_cast<char>(qBound(0, v, 255));
|
||
}
|
||
}
|
||
|
||
return yuvData;
|
||
}
|
||
|
||
// 将 QImage 数据转换为 YUV420
|
||
QByteArray convertQImageToYUV420(const QImage& image)
|
||
{
|
||
int width = image.width();
|
||
int height = image.height();
|
||
QByteArray yuvData;
|
||
int ySize = width * height;
|
||
int uvSize = (width / 2) * (height / 2);
|
||
yuvData.resize(ySize + 2 * uvSize); // Y 分量 + U 分量 + V 分量
|
||
|
||
int yIndex = 0;
|
||
int uIndex = ySize;
|
||
int vIndex = ySize + uvSize;
|
||
|
||
for (int y = 0; y < height; y++) {
|
||
for (int x = 0; x < width; x++) {
|
||
QRgb pixel = image.pixel(x, y);
|
||
|
||
int r = qRed(pixel);
|
||
int g = qGreen(pixel);
|
||
int b = qBlue(pixel);
|
||
|
||
// 计算 YUV 值
|
||
int Y = qBound(0, static_cast<int>(0.299 * r + 0.587 * g + 0.114 * b), 255);
|
||
int U = qBound(0, static_cast<int>(-0.169 * r - 0.331 * g + 0.5 * b + 128), 255);
|
||
int V = qBound(0, static_cast<int>(0.5 * r - 0.419 * g - 0.081 * b + 128), 255);
|
||
|
||
// 填充 Y 分量
|
||
yuvData[yIndex++] = static_cast<char>(Y);
|
||
|
||
// 对 U 和 V 分量进行抽样
|
||
if (y % 2 == 0 && x % 2 == 0) {
|
||
yuvData[uIndex++] = static_cast<char>(U);
|
||
yuvData[vIndex++] = static_cast<char>(V);
|
||
}
|
||
}
|
||
}
|
||
|
||
return yuvData;
|
||
}
|
||
|
||
// 将 YUV422 数据转换为 QImage
|
||
QImage convertYUV422ToQImage(const QByteArray& yuv422Data, int width, int height)
|
||
{
|
||
QImage image(width, height, QImage::Format_RGB888);
|
||
const uchar* yuvPtr = reinterpret_cast<const uchar*>(yuv422Data.constData());
|
||
const uchar* yuvDataEnd = yuvPtr + yuv422Data.size();
|
||
|
||
for (int y = 0; y < height; ++y) {
|
||
for (int x = 0; x < width; x += 2) {
|
||
if (yuvPtr + 4 > yuvDataEnd) {
|
||
qWarning() << "YUV data access out of range!";
|
||
return image;
|
||
}
|
||
|
||
int y0 = yuvPtr[0];
|
||
int u = yuvPtr[1];
|
||
int y1 = yuvPtr[2];
|
||
int v = yuvPtr[3];
|
||
|
||
yuvPtr += 4;
|
||
|
||
int r0, g0, b0;
|
||
int r1, g1, b1;
|
||
|
||
yuvToRgb(y0, u, v, r0, g0, b0);
|
||
yuvToRgb(y1, u, v, r1, g1, b1);
|
||
|
||
image.setPixel(x, y, qRgb(r0, g0, b0));
|
||
image.setPixel(x + 1, y, qRgb(r1, g1, b1));
|
||
}
|
||
}
|
||
|
||
return image;
|
||
}
|
||
|
||
// 将 YUV420 数据转换为 QImage
|
||
QImage convertYUV420ToQImage(const QByteArray& yuv420Data, int width, int height)
|
||
{
|
||
QImage image(width, height, QImage::Format_RGB888);
|
||
const uchar* yData = reinterpret_cast<const uchar*>(yuv420Data.constData());
|
||
const uchar* uData = yData + width * height;
|
||
const uchar* vData = uData + (width * height) / 4;
|
||
|
||
for (int y = 0; y < height; ++y) {
|
||
for (int x = 0; x < width; ++x) {
|
||
int yValue = yData[y * width + x];
|
||
int uValue = uData[(y / 2) * (width / 2) + (x / 2)];
|
||
int vValue = vData[(y / 2) * (width / 2) + (x / 2)];
|
||
|
||
int r, g, b;
|
||
yuvToRgb(yValue, uValue, vValue, r, g, b);
|
||
|
||
image.setPixel(x, y, qRgb(r, g, b));
|
||
}
|
||
}
|
||
|
||
return image;
|
||
}
|
||
|
||
void DataHandler::showPic(QSize labelSize, int lens_n,
|
||
int width, int height, int format, const QByteArray* valData)
|
||
{
|
||
qDebug() << "lens_n = " << lens_n;
|
||
qDebug() << "format = " << format;
|
||
qDebug() << "width = " << width;
|
||
qDebug() << "height = " << height;
|
||
qDebug() << "yuvData size = " << valData->size();
|
||
|
||
QImage image;
|
||
if (format == YUV422) {
|
||
image = convertYUV422ToQImage(*valData, width, height);
|
||
}
|
||
else if (format == YUV420) {
|
||
image = convertYUV420ToQImage(*valData, width, height);
|
||
}
|
||
else {
|
||
qWarning() << "Unsupported image format! Please use YUV422 or YUV420 format";
|
||
return;
|
||
}
|
||
|
||
QTransform transform;
|
||
transform.rotate(90); // 可以调整旋转角度
|
||
QImage rotatedImage = image.transformed(transform);
|
||
QImage scaledImage = rotatedImage.scaled(labelSize, Qt::KeepAspectRatio);
|
||
QPixmap pixmap = QPixmap::fromImage(scaledImage);
|
||
if (lens_n == 0) {
|
||
//leftLens_m_imageLabel->setPixmap(QPixmap::fromImage(scaledImage));
|
||
emit updateLeftLensImage(pixmap);
|
||
}
|
||
else if (lens_n == 1) {
|
||
//rightLens_m_imageLabel->setPixmap(QPixmap::fromImage(scaledImage));
|
||
emit updateRightLensImage(pixmap);
|
||
}
|
||
else {
|
||
qWarning() << "Unsupported image lens!";
|
||
}
|
||
|
||
// 生成保存图片的目录
|
||
QString saveDirPath = QDir::currentPath() + "/frontBoardImage";
|
||
QDir saveDir(saveDirPath);
|
||
if (!saveDir.exists()) {
|
||
saveDir.mkpath(saveDirPath);
|
||
}
|
||
QString currentTime = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss");
|
||
QByteArray rotatedYuvData;
|
||
if (format == YUV422) {
|
||
rotatedYuvData = convertQImageToYUV422(rotatedImage);
|
||
}
|
||
else if (format == YUV420) {
|
||
rotatedYuvData = convertQImageToYUV420(rotatedImage);
|
||
}
|
||
QString yuvFileName = saveDirPath + "/" + currentTime + ".yuv";
|
||
QFile yuvFile(yuvFileName);
|
||
if (yuvFile.open(QIODevice::WriteOnly)) {
|
||
yuvFile.write(rotatedYuvData);
|
||
yuvFile.close();
|
||
qDebug() << "YUV image saved to" << yuvFileName;
|
||
}
|
||
else {
|
||
qWarning() << "Failed to save rotated YUV image to" << yuvFileName;
|
||
}
|
||
|
||
// 额外:可以保存旋转后的图像为JPG或PNG格式
|
||
QString rotatedImageFileName = saveDirPath + "/" + currentTime + ".jpg";
|
||
rotatedImage.save(rotatedImageFileName, "JPG");
|
||
qDebug() << "JPG image saved to" << rotatedImageFileName;
|
||
}
|
||
|
||
void SerialDataHandler::showPic(QSize labelSize, int lens_n,
|
||
int width, int height, int format, const QByteArray* valData)
|
||
{
|
||
qDebug() << "lens_n = " << lens_n;
|
||
qDebug() << "format = " << format;
|
||
qDebug() << "width = " << width;
|
||
qDebug() << "height = " << height;
|
||
qDebug() << "yuvData size = " << valData->size();
|
||
|
||
QImage image;
|
||
if (format == YUV422) {
|
||
image = convertYUV422ToQImage(*valData, width, height);
|
||
}
|
||
else if (format == YUV420) {
|
||
image = convertYUV420ToQImage(*valData, width, height);
|
||
}
|
||
else {
|
||
qWarning() << "Unsupported image format! Please use YUV422 or YUV420 format";
|
||
return;
|
||
}
|
||
|
||
QTransform transform;
|
||
transform.rotate(270); // 可以调整旋转角度
|
||
QImage rotatedImage = image.transformed(transform);
|
||
QImage scaledImage = rotatedImage.scaled(labelSize, Qt::KeepAspectRatio);
|
||
QPixmap pixmap = QPixmap::fromImage(scaledImage);
|
||
if (lens_n == 0) {
|
||
//leftLens_m_imageLabel->setPixmap(QPixmap::fromImage(scaledImage));
|
||
emit updateLeftLensImage(pixmap);
|
||
}
|
||
else if (lens_n == 1) {
|
||
//rightLens_m_imageLabel->setPixmap(QPixmap::fromImage(scaledImage));
|
||
emit updateRightLensImage(pixmap);
|
||
}
|
||
else {
|
||
qWarning() << "Unsupported image lens!";
|
||
}
|
||
|
||
// 生成保存图片的目录
|
||
QString saveDirPath = QDir::currentPath() + "/frontBoardImage";
|
||
QDir saveDir(saveDirPath);
|
||
if (!saveDir.exists()) {
|
||
saveDir.mkpath(saveDirPath);
|
||
}
|
||
QString currentTime = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss");
|
||
QByteArray rotatedYuvData;
|
||
if (format == YUV422) {
|
||
rotatedYuvData = convertQImageToYUV422(rotatedImage);
|
||
}
|
||
else if (format == YUV420) {
|
||
rotatedYuvData = convertQImageToYUV420(rotatedImage);
|
||
}
|
||
|
||
QString len_num = "";
|
||
if (lens_n == 0)
|
||
len_num = "left";
|
||
else
|
||
len_num = "right";
|
||
QString yuvFileName = saveDirPath + "/" + len_num + "_" + currentTime + ".yuv";
|
||
QFile yuvFile(yuvFileName);
|
||
if (yuvFile.open(QIODevice::WriteOnly)) {
|
||
yuvFile.write(rotatedYuvData);
|
||
yuvFile.close();
|
||
qDebug() << "YUV image saved to" << yuvFileName;
|
||
}
|
||
else {
|
||
qWarning() << "Failed to save rotated YUV image to" << yuvFileName;
|
||
}
|
||
|
||
|
||
// 额外:可以保存旋转后的图像为JPG或PNG格式
|
||
QString rotatedImageFileName = saveDirPath + "/" + len_num + "_" + currentTime + ".jpg";
|
||
rotatedImage.save(rotatedImageFileName, "JPG");
|
||
qDebug() << "JPG image saved to" << rotatedImageFileName;
|
||
}
|
||
|
||
|