实现图片上传下载。
This commit is contained in:
parent
174e22ea79
commit
6e11d190c0
@ -12,6 +12,10 @@
|
|||||||
#include <QQmlApplicationEngine>
|
#include <QQmlApplicationEngine>
|
||||||
#include <QSerialPortInfo>
|
#include <QSerialPortInfo>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <fstream>
|
||||||
|
#include <mbedtls/md5.h>
|
||||||
|
|
||||||
|
constexpr uint32_t ImageSliceSize = 2048;
|
||||||
|
|
||||||
Application::Application(int &argc, char **argv) : m_app(std::make_shared<QApplication>(argc, argv)) {
|
Application::Application(int &argc, char **argv) : m_app(std::make_shared<QApplication>(argc, argv)) {
|
||||||
QFont font;
|
QFont font;
|
||||||
@ -178,6 +182,31 @@ void Application::getEnrolledImage(const QString &username, uint8_t timeout) {
|
|||||||
m_communication->enrollEx(username.toStdString(), timeout);
|
m_communication->enrollEx(username.toStdString(), timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::uploadImage() {
|
||||||
|
m_uploadImageSendedSize = 0;
|
||||||
|
std::ifstream ifs("palm.yuv", std::ofstream::binary);
|
||||||
|
m_uploadBuffer = std::vector<char>((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
|
||||||
|
|
||||||
|
ModuleCommunication::UploadImageInformation request;
|
||||||
|
mbedtls_md5_context context;
|
||||||
|
mbedtls_md5_init(&context);
|
||||||
|
mbedtls_md5_starts(&context);
|
||||||
|
mbedtls_md5_update(&context, reinterpret_cast<const uint8_t *>(m_uploadBuffer.data()), m_uploadBuffer.size());
|
||||||
|
mbedtls_md5_finish(&context, request.md5);
|
||||||
|
mbedtls_md5_free(&context);
|
||||||
|
|
||||||
|
request.operation = 0;
|
||||||
|
request.width = 600;
|
||||||
|
request.height = 800;
|
||||||
|
request.size = m_uploadBuffer.size();
|
||||||
|
strncpy(request.username, "下发测试", sizeof(request.username));
|
||||||
|
m_communication->uploadImageInfo(request);
|
||||||
|
LOG(info) << "upload image, md5: "
|
||||||
|
<< ModuleCommunication::protocolDataFormatString(request.md5, sizeof(request.md5));
|
||||||
|
|
||||||
|
m_startUploadTime = std::chrono::system_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
ModuleCommunication *Application::module() const {
|
ModuleCommunication *Application::module() const {
|
||||||
return m_communication.get();
|
return m_communication.get();
|
||||||
}
|
}
|
||||||
@ -238,7 +267,7 @@ void Application::onErrorOccurred(const QString &error) {
|
|||||||
void Application::onNewEnrolledImageInfo(uint32_t size, const uint8_t *md5) {
|
void Application::onNewEnrolledImageInfo(uint32_t size, const uint8_t *md5) {
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
m_enrolledImageSize = size;
|
m_enrolledImageSize = size;
|
||||||
m_communication->requestEnrolledImage(0, 1024);
|
m_communication->requestEnrolledImage(0, ImageSliceSize);
|
||||||
m_enrollYImageBuffer.clear();
|
m_enrollYImageBuffer.clear();
|
||||||
m_startUploadTime = system_clock::now();
|
m_startUploadTime = system_clock::now();
|
||||||
}
|
}
|
||||||
@ -249,13 +278,16 @@ void Application::onNewImageSliceData(const std::vector<uint8_t> &data) {
|
|||||||
// << ", total size: " << m_enrolledImageSize;
|
// << ", total size: " << m_enrolledImageSize;
|
||||||
m_enrollYImageBuffer.append(reinterpret_cast<const char *>(data.data()), data.size());
|
m_enrollYImageBuffer.append(reinterpret_cast<const char *>(data.data()), data.size());
|
||||||
if (m_enrollYImageBuffer.size() < m_enrolledImageSize) {
|
if (m_enrollYImageBuffer.size() < m_enrolledImageSize) {
|
||||||
m_communication->requestEnrolledImage(m_enrollYImageBuffer.size(), 1024);
|
m_communication->requestEnrolledImage(m_enrollYImageBuffer.size(), ImageSliceSize);
|
||||||
} else {
|
} else {
|
||||||
LOG(info) << "request finished, elapsed: "
|
LOG(info) << "request finished, elapsed: "
|
||||||
<< duration_cast<milliseconds>(system_clock::now() - m_startUploadTime);
|
<< duration_cast<milliseconds>(system_clock::now() - m_startUploadTime);
|
||||||
QImage image(reinterpret_cast<const uint8_t *>(m_enrollYImageBuffer.data()), 600, 800,
|
QImage image(reinterpret_cast<const uint8_t *>(m_enrollYImageBuffer.data()), 600, 800,
|
||||||
QImage::Format_Grayscale8);
|
QImage::Format_Grayscale8);
|
||||||
image.save("test.jpg");
|
image.save("test.jpg");
|
||||||
|
|
||||||
|
std::ofstream ofs("palm.yuv", std::ofstream::binary);
|
||||||
|
ofs.write(m_enrollYImageBuffer.data(), m_enrollYImageBuffer.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,7 +301,7 @@ void Application::onCommandStarted(ModuleCommunication::MessageId messageId) {
|
|||||||
|
|
||||||
void Application::onCommandFinished(ModuleCommunication::MessageId messageId,
|
void Application::onCommandFinished(ModuleCommunication::MessageId messageId,
|
||||||
ModuleCommunication::MessageStatus status) {
|
ModuleCommunication::MessageStatus status) {
|
||||||
LOG(info) << m_persistenceMode << " " << m_persistenceModeStarted << " " << m_persistenceVerifyInterval;
|
// LOG(info) << m_persistenceMode << " " << m_persistenceModeStarted << " " << m_persistenceVerifyInterval;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
if (messageId == ModuleCommunication::Verify) {
|
if (messageId == ModuleCommunication::Verify) {
|
||||||
m_verifyElapsed = duration_cast<milliseconds>(system_clock::now() - m_verifyStartTime);
|
m_verifyElapsed = duration_cast<milliseconds>(system_clock::now() - m_verifyStartTime);
|
||||||
@ -279,6 +311,22 @@ void Application::onCommandFinished(ModuleCommunication::MessageId messageId,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (messageId == ModuleCommunication::UploadImageInfo) {
|
||||||
|
m_communication->uploadImageData(
|
||||||
|
m_uploadImageSendedSize, (const uint8_t *)m_uploadBuffer.data() + m_uploadImageSendedSize, ImageSliceSize);
|
||||||
|
} else if (messageId == ModuleCommunication::UploadImageData) {
|
||||||
|
m_uploadImageSendedSize += ImageSliceSize;
|
||||||
|
if (m_uploadImageSendedSize < m_uploadBuffer.size()) {
|
||||||
|
auto remainSize = m_uploadBuffer.size() - m_uploadImageSendedSize;
|
||||||
|
m_communication->uploadImageData(m_uploadImageSendedSize,
|
||||||
|
(const uint8_t *)m_uploadBuffer.data() + m_uploadImageSendedSize,
|
||||||
|
remainSize < ImageSliceSize ? remainSize : ImageSliceSize);
|
||||||
|
} else {
|
||||||
|
LOG(info) << "upload finished, elapsed: "
|
||||||
|
<< duration_cast<milliseconds>(system_clock::now() - m_startUploadTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (messageId == ModuleCommunication::Verify && m_persistenceMode) { // 持续识别逻辑
|
if (messageId == ModuleCommunication::Verify && m_persistenceMode) { // 持续识别逻辑
|
||||||
m_persistenceModeStarted = true;
|
m_persistenceModeStarted = true;
|
||||||
} else if (messageId == ModuleCommunication::Reset) {
|
} else if (messageId == ModuleCommunication::Reset) {
|
||||||
|
@ -47,6 +47,7 @@ public:
|
|||||||
Q_INVOKABLE void deleteUser(uint16_t userid);
|
Q_INVOKABLE void deleteUser(uint16_t userid);
|
||||||
Q_INVOKABLE void deleteAll();
|
Q_INVOKABLE void deleteAll();
|
||||||
Q_INVOKABLE void getEnrolledImage(const QString &username, uint8_t timeout);
|
Q_INVOKABLE void getEnrolledImage(const QString &username, uint8_t timeout);
|
||||||
|
Q_INVOKABLE void uploadImage();
|
||||||
ModuleCommunication *module() const;
|
ModuleCommunication *module() const;
|
||||||
bool connected() const;
|
bool connected() const;
|
||||||
bool uvcOpened() const;
|
bool uvcOpened() const;
|
||||||
@ -94,6 +95,9 @@ private:
|
|||||||
QByteArray m_enrollYImageBuffer;
|
QByteArray m_enrollYImageBuffer;
|
||||||
std::chrono::system_clock::time_point m_startUploadTime;
|
std::chrono::system_clock::time_point m_startUploadTime;
|
||||||
|
|
||||||
|
uint32_t m_uploadImageSendedSize;
|
||||||
|
std::vector<char> m_uploadBuffer;
|
||||||
|
|
||||||
std::shared_ptr<VideoPlayer> m_videoPlayer;
|
std::shared_ptr<VideoPlayer> m_videoPlayer;
|
||||||
VideoFrameProvider *m_videoFrameProvider;
|
VideoFrameProvider *m_videoFrameProvider;
|
||||||
};
|
};
|
||||||
|
@ -106,8 +106,9 @@ void ModuleCommunication::requestEnrolledImage(uint32_t offset, uint32_t size) {
|
|||||||
auto [data, frameSize] =
|
auto [data, frameSize] =
|
||||||
generateFrame(GetEnrolledImage, reinterpret_cast<const uint8_t *>(&request), sizeof(request));
|
generateFrame(GetEnrolledImage, reinterpret_cast<const uint8_t *>(&request), sizeof(request));
|
||||||
m_serialPort->write(reinterpret_cast<const char *>(data), frameSize);
|
m_serialPort->write(reinterpret_cast<const char *>(data), frameSize);
|
||||||
LOG_CAT(info, GUI) << "发送获取图片指令: " << protocolDataFormatString(data, frameSize);
|
// 打印太耗时
|
||||||
LOG_CAT(info, GUI) << Separator;
|
// LOG_CAT(info, GUI) << "发送获取图片指令: " << protocolDataFormatString(data, frameSize);
|
||||||
|
// LOG_CAT(info, GUI) << Separator;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleCommunication::requestPalmFeature(uint16_t userid) {
|
void ModuleCommunication::requestPalmFeature(uint16_t userid) {
|
||||||
@ -146,6 +147,31 @@ void ModuleCommunication::enrollPalmFeature(uint16_t userid, const PalmFeature &
|
|||||||
if (buffer != nullptr) delete[] buffer;
|
if (buffer != nullptr) delete[] buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModuleCommunication::uploadImageInfo(const UploadImageInformation &info) {
|
||||||
|
UploadImageInformation request;
|
||||||
|
request.operation = info.operation;
|
||||||
|
request.width = htons(info.width);
|
||||||
|
request.height = htons(info.height);
|
||||||
|
request.size = htonl(info.size);
|
||||||
|
memcpy(request.username, info.username, sizeof(request.username));
|
||||||
|
memcpy(request.md5, info.md5, sizeof(request.md5));
|
||||||
|
auto [data, frameSize] =
|
||||||
|
generateFrame(UploadImageInfo, reinterpret_cast<const uint8_t *>(&request), sizeof(request));
|
||||||
|
m_serialPort->write(reinterpret_cast<const char *>(data), frameSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleCommunication::uploadImageData(uint32_t offset, const uint8_t *data, uint32_t size) {
|
||||||
|
uint32_t dataSize = sizeof(UploadImageDataSlice) + size;
|
||||||
|
auto buffer = new uint8_t[dataSize];
|
||||||
|
auto request = reinterpret_cast<UploadImageDataSlice *>(buffer);
|
||||||
|
request->size = htonl(size);
|
||||||
|
request->offset = htonl(offset);
|
||||||
|
memcpy(request->data, data, size);
|
||||||
|
auto [frameData, frameSize] = generateFrame(UploadImageData, buffer, dataSize);
|
||||||
|
m_serialPort->write(reinterpret_cast<const char *>(frameData), frameSize);
|
||||||
|
delete[] buffer;
|
||||||
|
}
|
||||||
|
|
||||||
ModuleCommunication::MessageId ModuleCommunication::currentMessageId() const {
|
ModuleCommunication::MessageId ModuleCommunication::currentMessageId() const {
|
||||||
return m_currentMessageId;
|
return m_currentMessageId;
|
||||||
}
|
}
|
||||||
@ -216,7 +242,8 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) {
|
|||||||
// LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size);
|
// LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size);
|
||||||
if (result == Success) {
|
if (result == Success) {
|
||||||
auto info = reinterpret_cast<const ImageSliceReply *>(data + 7);
|
auto info = reinterpret_cast<const ImageSliceReply *>(data + 7);
|
||||||
emit newImageSliceData(std::vector<uint8_t>(info->data, info->data + ntohl(info->size)));
|
uint32_t sliceSize = ntohl(info->size);
|
||||||
|
emit newImageSliceData(std::vector<uint8_t>(info->data, info->data + sliceSize));
|
||||||
}
|
}
|
||||||
// LOG_CAT(info, GUI) << Separator;
|
// LOG_CAT(info, GUI) << Separator;
|
||||||
break;
|
break;
|
||||||
@ -264,6 +291,12 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) {
|
|||||||
LOG_CAT(info, GUI) << Separator;
|
LOG_CAT(info, GUI) << Separator;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case UploadImageInfo: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UploadImageData: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
LOG(warning) << "unknown reply command: 0x" << (static_cast<int>(replyId) & 0xff)
|
LOG(warning) << "unknown reply command: 0x" << (static_cast<int>(replyId) & 0xff)
|
||||||
<< ", data: " << protocolDataFormatString(data, size);
|
<< ", data: " << protocolDataFormatString(data, size);
|
||||||
@ -353,7 +386,7 @@ void ModuleCommunication::onErrorOccurred(QSerialPort::SerialPortError error) {
|
|||||||
|
|
||||||
std::pair<uint8_t *, uint32_t> ModuleCommunication::generateFrame(MessageId command, const uint8_t *data,
|
std::pair<uint8_t *, uint32_t> ModuleCommunication::generateFrame(MessageId command, const uint8_t *data,
|
||||||
uint16_t size) {
|
uint16_t size) {
|
||||||
static uint8_t sendBuffer[1024] = {0};
|
static uint8_t sendBuffer[4096] = {0};
|
||||||
memset(sendBuffer, 0, sizeof(sendBuffer));
|
memset(sendBuffer, 0, sizeof(sendBuffer));
|
||||||
sendBuffer[0] = 0xef;
|
sendBuffer[0] = 0xef;
|
||||||
sendBuffer[1] = 0xaa;
|
sendBuffer[1] = 0xaa;
|
||||||
|
@ -23,6 +23,8 @@ public:
|
|||||||
GetEnrolledImage = 0x1F,
|
GetEnrolledImage = 0x1F,
|
||||||
DeleteUser = 0x20,
|
DeleteUser = 0x20,
|
||||||
DeleteAll = 0x21,
|
DeleteAll = 0x21,
|
||||||
|
UploadImageInfo = 0xF6,
|
||||||
|
UploadImageData = 0xF7,
|
||||||
RegisterPalmFeature = 0xF9,
|
RegisterPalmFeature = 0xF9,
|
||||||
RequestPalmFeature = 0xFA,
|
RequestPalmFeature = 0xFA,
|
||||||
Idle = 0xFF,
|
Idle = 0xFF,
|
||||||
@ -114,6 +116,23 @@ public:
|
|||||||
uint8_t feature[0];
|
uint8_t feature[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UploadImageInformation {
|
||||||
|
uint8_t operation; // 0:图片录入掌静脉
|
||||||
|
uint8_t format; // 0: 灰度图(纯Y分量)
|
||||||
|
uint16_t width;
|
||||||
|
uint16_t height;
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t md5[16]; // 图片内容 md5 值
|
||||||
|
char username[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UploadImageDataSlice {
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t reserved[4]; // 预留
|
||||||
|
uint8_t data[0];
|
||||||
|
};
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
explicit ModuleCommunication(QObject *parent = nullptr);
|
explicit ModuleCommunication(QObject *parent = nullptr);
|
||||||
bool open(const QString &portName, int baudRate);
|
bool open(const QString &portName, int baudRate);
|
||||||
@ -129,8 +148,11 @@ public:
|
|||||||
void requestPalmFeature(uint16_t userid);
|
void requestPalmFeature(uint16_t userid);
|
||||||
void enrollPalmFeature(uint16_t userid, const PalmFeature &feature);
|
void enrollPalmFeature(uint16_t userid, const PalmFeature &feature);
|
||||||
|
|
||||||
MessageId currentMessageId() const;
|
void uploadImageInfo(const UploadImageInformation &info);
|
||||||
|
void uploadImageData(uint32_t offset, const uint8_t *data, uint32_t size);
|
||||||
|
|
||||||
|
MessageId currentMessageId() const;
|
||||||
|
static std::string protocolDataFormatString(const uint8_t *data, int size);
|
||||||
signals:
|
signals:
|
||||||
void newVerifyResult(uint16_t userid, const QString &username);
|
void newVerifyResult(uint16_t userid, const QString &username);
|
||||||
void newPalmFeature(const PalmFeature &feature);
|
void newPalmFeature(const PalmFeature &feature);
|
||||||
@ -145,7 +167,7 @@ protected:
|
|||||||
void onReadyRead();
|
void onReadyRead();
|
||||||
void onErrorOccurred(QSerialPort::SerialPortError error);
|
void onErrorOccurred(QSerialPort::SerialPortError error);
|
||||||
std::pair<uint8_t *, uint32_t> generateFrame(MessageId command, const uint8_t *data = nullptr, uint16_t size = 0);
|
std::pair<uint8_t *, uint32_t> generateFrame(MessageId command, const uint8_t *data = nullptr, uint16_t size = 0);
|
||||||
std::string protocolDataFormatString(const uint8_t *data, int size);
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<QSerialPort> m_serialPort;
|
std::shared_ptr<QSerialPort> m_serialPort;
|
||||||
QByteArray m_receivedBuffer;
|
QByteArray m_receivedBuffer;
|
||||||
|
@ -111,6 +111,7 @@ ColumnLayout {
|
|||||||
}
|
}
|
||||||
Button {
|
Button {
|
||||||
text: "图片下发注册"
|
text: "图片下发注册"
|
||||||
|
onClicked: App.uploadImage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user