Vitaliy Zarubin
1 year ago
6 changed files with 405 additions and 369 deletions
@ -0,0 +1,209 @@ |
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> |
||||||
|
* SPDX-License-Identifier: BSD-3-Clause |
||||||
|
*/ |
||||||
|
#ifndef FLUTTER_PLUGIN_CAMERA_AURORA_PLUGIN_YUV_H |
||||||
|
#define FLUTTER_PLUGIN_CAMERA_AURORA_PLUGIN_YUV_H |
||||||
|
|
||||||
|
#include <libyuv/libyuv.h> |
||||||
|
|
||||||
|
#include <QBuffer> |
||||||
|
#include <QImage> |
||||||
|
#include <QtCore> |
||||||
|
|
||||||
|
namespace yuv { |
||||||
|
|
||||||
|
struct Result |
||||||
|
{ |
||||||
|
uint8_t *y; |
||||||
|
int strideY; |
||||||
|
uint8_t *u; |
||||||
|
int strideU; |
||||||
|
uint8_t *v; |
||||||
|
int strideV; |
||||||
|
int width; |
||||||
|
int height; |
||||||
|
std::shared_ptr<uint8_t> raw; |
||||||
|
}; |
||||||
|
|
||||||
|
Result I420Scale(const uint8_t *srcY, |
||||||
|
const uint8_t *srcU, |
||||||
|
const uint8_t *srcV, |
||||||
|
int srcWidth, |
||||||
|
int srcHeight, |
||||||
|
int outWidth, |
||||||
|
int outHeight) |
||||||
|
{ |
||||||
|
auto bufSize = (((outWidth * outHeight) + ((outWidth + 1) / 2) * ((outHeight + 1) / 2))) * 2; |
||||||
|
auto buf = std::shared_ptr<uint8_t>((uint8_t *) malloc(bufSize), free); |
||||||
|
|
||||||
|
auto y = buf.get(); |
||||||
|
auto u = buf.get() + outWidth * outHeight; |
||||||
|
auto v = buf.get() + outWidth * outHeight + (outWidth * outHeight + 3) / 4; |
||||||
|
|
||||||
|
auto srcStrideY = srcWidth; |
||||||
|
auto srcStrideU = (srcWidth + 1) / 2; |
||||||
|
auto srcStrideV = srcStrideU; |
||||||
|
|
||||||
|
auto outStrideY = outWidth; |
||||||
|
auto outStrideU = (outWidth + 1) / 2; |
||||||
|
auto outStrideV = outStrideU; |
||||||
|
|
||||||
|
libyuv::I420Scale(srcY, |
||||||
|
srcStrideY, |
||||||
|
srcU, |
||||||
|
srcStrideU, |
||||||
|
srcV, |
||||||
|
srcStrideV, |
||||||
|
srcWidth, |
||||||
|
srcHeight, |
||||||
|
y, |
||||||
|
outStrideY, |
||||||
|
u, |
||||||
|
outStrideU, |
||||||
|
v, |
||||||
|
outStrideV, |
||||||
|
outWidth, |
||||||
|
outHeight, |
||||||
|
libyuv::kFilterBilinear); |
||||||
|
|
||||||
|
return Result{y, outStrideY, u, outStrideU, v, outStrideV, outWidth, outHeight, buf}; |
||||||
|
} |
||||||
|
|
||||||
|
Result I420Rotate(const uint8_t *srcY, |
||||||
|
const uint8_t *srcU, |
||||||
|
const uint8_t *srcV, |
||||||
|
int srcWidth, |
||||||
|
int srcHeight, |
||||||
|
int degree) |
||||||
|
{ |
||||||
|
int d = degree; |
||||||
|
|
||||||
|
if (degree < 0) { |
||||||
|
d = 360 - ((degree * -1) % 360); |
||||||
|
} |
||||||
|
|
||||||
|
if (degree >= 360) { |
||||||
|
d = degree % 360; |
||||||
|
} |
||||||
|
|
||||||
|
int outWidth = srcWidth; |
||||||
|
int outHeight = srcHeight; |
||||||
|
|
||||||
|
if (d == 90 || d == 270) { |
||||||
|
outWidth = srcHeight; |
||||||
|
outHeight = srcWidth; |
||||||
|
} |
||||||
|
|
||||||
|
enum libyuv::RotationMode mode = (enum libyuv::RotationMode) d; |
||||||
|
|
||||||
|
auto bufSize = (((outWidth * outHeight) + ((outWidth + 1) / 2) * ((outHeight + 1) / 2))) * 2; |
||||||
|
auto buf = std::shared_ptr<uint8_t>((uint8_t *) malloc(bufSize), free); |
||||||
|
|
||||||
|
auto y = buf.get(); |
||||||
|
auto u = buf.get() + outWidth * outHeight; |
||||||
|
auto v = buf.get() + outWidth * outHeight + (outWidth * outHeight + 3) / 4; |
||||||
|
|
||||||
|
auto srcStrideY = srcWidth; |
||||||
|
auto srcStrideU = (srcWidth + 1) / 2; |
||||||
|
auto srcStrideV = srcStrideU; |
||||||
|
|
||||||
|
auto outStrideY = outWidth; |
||||||
|
auto outStrideU = (outWidth + 1) / 2; |
||||||
|
auto outStrideV = outStrideU; |
||||||
|
|
||||||
|
libyuv::I420Rotate(srcY, |
||||||
|
srcStrideY, |
||||||
|
srcU, |
||||||
|
srcStrideU, |
||||||
|
srcV, |
||||||
|
srcStrideV, |
||||||
|
y, |
||||||
|
outStrideY, |
||||||
|
u, |
||||||
|
outStrideU, |
||||||
|
v, |
||||||
|
outStrideV, |
||||||
|
srcWidth, |
||||||
|
srcHeight, |
||||||
|
mode); |
||||||
|
|
||||||
|
return Result{y, outStrideY, u, outStrideU, v, outStrideV, outWidth, outHeight, buf}; |
||||||
|
} |
||||||
|
|
||||||
|
std::shared_ptr<uint8_t> I420ToARGB( |
||||||
|
const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV, int srcWidth, int srcHeight) |
||||||
|
{ |
||||||
|
auto srcStrideY = srcWidth; |
||||||
|
auto srcStrideU = (srcWidth + 1) / 2; |
||||||
|
auto srcStrideV = srcStrideU; |
||||||
|
|
||||||
|
auto bits = std::shared_ptr<uint8_t>((uint8_t *) malloc(srcWidth * srcHeight * 4), free); |
||||||
|
|
||||||
|
libyuv::I420ToARGB(srcY, |
||||||
|
srcStrideY, |
||||||
|
srcU, |
||||||
|
srcStrideU, |
||||||
|
srcV, |
||||||
|
srcStrideV, |
||||||
|
bits.get(), |
||||||
|
srcWidth * 4, |
||||||
|
srcWidth, |
||||||
|
srcHeight); |
||||||
|
|
||||||
|
return bits; |
||||||
|
} |
||||||
|
|
||||||
|
QImage I420ToQImage( |
||||||
|
const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV, int srcWidth, int srcHeight) |
||||||
|
{ |
||||||
|
QSize size(srcWidth, srcHeight); |
||||||
|
QImage image(size, QImage::Format_RGBA8888); |
||||||
|
|
||||||
|
auto srcStrideY = srcWidth; |
||||||
|
auto srcStrideU = (srcWidth + 1) / 2; |
||||||
|
auto srcStrideV = srcStrideU; |
||||||
|
|
||||||
|
libyuv::I420ToARGB(srcY, |
||||||
|
srcStrideY, |
||||||
|
srcU, |
||||||
|
srcStrideU, |
||||||
|
srcV, |
||||||
|
srcStrideV, |
||||||
|
reinterpret_cast<uint8_t *>(image.bits()), |
||||||
|
srcWidth * 4, |
||||||
|
srcWidth, |
||||||
|
srcHeight); |
||||||
|
|
||||||
|
return image; |
||||||
|
} |
||||||
|
|
||||||
|
std::string I420ToBase64(const uint8_t *srcY, |
||||||
|
const uint8_t *srcU, |
||||||
|
const uint8_t *srcV, |
||||||
|
int srcWidth, |
||||||
|
int srcHeight, |
||||||
|
int orientationDisplay, |
||||||
|
int orientationCamera, |
||||||
|
int direction) |
||||||
|
{ |
||||||
|
auto angle = orientationCamera - orientationDisplay; |
||||||
|
|
||||||
|
if (direction < 0 && (orientationDisplay == 90 || orientationDisplay == 270)) { |
||||||
|
angle -= 180; |
||||||
|
} |
||||||
|
|
||||||
|
auto result = I420Rotate(srcY, srcU, srcV, srcWidth, srcHeight, angle); |
||||||
|
|
||||||
|
auto image = I420ToQImage(result.y, result.u, result.v, result.width, result.height); |
||||||
|
|
||||||
|
QBuffer qbuffer; |
||||||
|
qbuffer.open(QIODevice::WriteOnly); |
||||||
|
image.save(&qbuffer, "JPEG"); |
||||||
|
|
||||||
|
return qbuffer.data().toBase64().toStdString(); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace yuv
|
||||||
|
|
||||||
|
#endif /* FLUTTER_PLUGIN_CAMERA_AURORA_PLUGIN_YUV_H */ |
Loading…
Reference in new issue