实现图片上传下载。

This commit is contained in:
luocai 2024-06-20 21:28:30 +08:00
parent 174e22ea79
commit 6e11d190c0
5 changed files with 117 additions and 9 deletions

View File

@ -12,6 +12,10 @@
#include <QQmlApplicationEngine>
#include <QSerialPortInfo>
#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)) {
QFont font;
@ -178,6 +182,31 @@ void Application::getEnrolledImage(const QString &username, uint8_t 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 {
return m_communication.get();
}
@ -238,7 +267,7 @@ void Application::onErrorOccurred(const QString &error) {
void Application::onNewEnrolledImageInfo(uint32_t size, const uint8_t *md5) {
using namespace std::chrono;
m_enrolledImageSize = size;
m_communication->requestEnrolledImage(0, 1024);
m_communication->requestEnrolledImage(0, ImageSliceSize);
m_enrollYImageBuffer.clear();
m_startUploadTime = system_clock::now();
}
@ -249,13 +278,16 @@ void Application::onNewImageSliceData(const std::vector<uint8_t> &data) {
// << ", total size: " << m_enrolledImageSize;
m_enrollYImageBuffer.append(reinterpret_cast<const char *>(data.data()), data.size());
if (m_enrollYImageBuffer.size() < m_enrolledImageSize) {
m_communication->requestEnrolledImage(m_enrollYImageBuffer.size(), 1024);
m_communication->requestEnrolledImage(m_enrollYImageBuffer.size(), ImageSliceSize);
} else {
LOG(info) << "request finished, elapsed: "
<< duration_cast<milliseconds>(system_clock::now() - m_startUploadTime);
QImage image(reinterpret_cast<const uint8_t *>(m_enrollYImageBuffer.data()), 600, 800,
QImage::Format_Grayscale8);
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,
ModuleCommunication::MessageStatus status) {
LOG(info) << m_persistenceMode << " " << m_persistenceModeStarted << " " << m_persistenceVerifyInterval;
// LOG(info) << m_persistenceMode << " " << m_persistenceModeStarted << " " << m_persistenceVerifyInterval;
using namespace std::chrono;
if (messageId == ModuleCommunication::Verify) {
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) { // 持续识别逻辑
m_persistenceModeStarted = true;
} else if (messageId == ModuleCommunication::Reset) {

View File

@ -47,6 +47,7 @@ public:
Q_INVOKABLE void deleteUser(uint16_t userid);
Q_INVOKABLE void deleteAll();
Q_INVOKABLE void getEnrolledImage(const QString &username, uint8_t timeout);
Q_INVOKABLE void uploadImage();
ModuleCommunication *module() const;
bool connected() const;
bool uvcOpened() const;
@ -94,6 +95,9 @@ private:
QByteArray m_enrollYImageBuffer;
std::chrono::system_clock::time_point m_startUploadTime;
uint32_t m_uploadImageSendedSize;
std::vector<char> m_uploadBuffer;
std::shared_ptr<VideoPlayer> m_videoPlayer;
VideoFrameProvider *m_videoFrameProvider;
};

View File

@ -106,8 +106,9 @@ void ModuleCommunication::requestEnrolledImage(uint32_t offset, uint32_t size) {
auto [data, frameSize] =
generateFrame(GetEnrolledImage, reinterpret_cast<const uint8_t *>(&request), sizeof(request));
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) {
@ -146,6 +147,31 @@ void ModuleCommunication::enrollPalmFeature(uint16_t userid, const PalmFeature &
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 {
return m_currentMessageId;
}
@ -216,7 +242,8 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) {
// LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size);
if (result == Success) {
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;
break;
@ -264,6 +291,12 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) {
LOG_CAT(info, GUI) << Separator;
break;
}
case UploadImageInfo: {
break;
}
case UploadImageData: {
break;
}
default:
LOG(warning) << "unknown reply command: 0x" << (static_cast<int>(replyId) & 0xff)
<< ", 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,
uint16_t size) {
static uint8_t sendBuffer[1024] = {0};
static uint8_t sendBuffer[4096] = {0};
memset(sendBuffer, 0, sizeof(sendBuffer));
sendBuffer[0] = 0xef;
sendBuffer[1] = 0xaa;

View File

@ -23,6 +23,8 @@ public:
GetEnrolledImage = 0x1F,
DeleteUser = 0x20,
DeleteAll = 0x21,
UploadImageInfo = 0xF6,
UploadImageData = 0xF7,
RegisterPalmFeature = 0xF9,
RequestPalmFeature = 0xFA,
Idle = 0xFF,
@ -114,6 +116,23 @@ public:
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()
explicit ModuleCommunication(QObject *parent = nullptr);
bool open(const QString &portName, int baudRate);
@ -129,8 +148,11 @@ public:
void requestPalmFeature(uint16_t userid);
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:
void newVerifyResult(uint16_t userid, const QString &username);
void newPalmFeature(const PalmFeature &feature);
@ -145,7 +167,7 @@ protected:
void onReadyRead();
void onErrorOccurred(QSerialPort::SerialPortError error);
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:
std::shared_ptr<QSerialPort> m_serialPort;
QByteArray m_receivedBuffer;

View File

@ -111,6 +111,7 @@ ColumnLayout {
}
Button {
text: "图片下发注册"
onClicked: App.uploadImage()
}
}
}