Files
2026-03-02 21:40:25 +08:00

239 lines
5.5 KiB
C++

#include "RawFileStream.h"
#include <filesystem>
#include <fstream>
#include <mutex>
#include <future>
namespace RawFileTools
{
constexpr int FileNotExit = 400;
constexpr int FileOpenFaild = 401;
constexpr int FileFrameNotFull = 402;
using MyStream = GuideRawFileStream;
using MyIterator = MyStream::GuideRawFileStreamIterator;
struct MyStream::privateData
{
size_t totalFrame_ = 0;
size_t frameSize_ = 0;
size_t ImageSize_ = 0;
GFrameFormat fromat_;
std::string filePath_;
int errorCode_ = 0;
std::mutex queueMutex_;
std::vector<char> FrameDataVector_;
std::future<bool> taskFuture_;
bool result=false;
};
MyStream::GuideRawFileStream(const std::string& rawPath,
const GFrameFormat& format) :impl(std::make_unique<privateData>())
{
impl->fromat_ = format;
impl->filePath_ = rawPath;
const int c_nPixelBytes = format.dBytesOfPixel;
impl->frameSize_ = format.nImageWidth * (format.nImageHeight + format.nParamLineCount) * c_nPixelBytes;
impl->ImageSize_ = format.nImageWidth * format.nImageHeight * c_nPixelBytes;
startReadFile();
}
MyStream::~GuideRawFileStream()
{
impl->FrameDataVector_.clear();
}
size_t MyStream::getTotalFrameCount()const
{
return impl->totalFrame_;
}
MyStream::ErrorCode MyStream::getErrorCode()const
{
return impl->errorCode_;
}
std::string MyStream::getErrorWhat()
{
switch (impl->errorCode_)
{
case 400:
return "文件不存在";
case 401:
return "文件打开失败";
case 402:
return "读取的文件数据不完整";
default:
return "未知原因";
}
}
bool MyStream::isReadReady()const
{
if (impl->taskFuture_.valid())
{
impl->result= impl->taskFuture_.get();
}
return impl->result;
}
std::optional<std::vector<char>> MyStream::getImageDataWithParame(size_t currentFrame)const
{
if (impl->result)
{
std::vector<char> buffer(impl->frameSize_);
std::copy(impl->FrameDataVector_.begin()+currentFrame*impl->frameSize_,
impl->FrameDataVector_.begin() + currentFrame * impl->frameSize_+ impl->frameSize_,
buffer.begin());
return buffer;
}
return std::nullopt;
}
std::optional<std::vector<char>> MyStream::getImageData(size_t currentFrame)const
{
if (impl->result)
{
std::vector<char> buffer(impl->ImageSize_);
if (impl->fromat_.nParamStartLine > 2)
{
//头参数行
size_t HeadOffset = (impl->fromat_.nParamLineCount) *
(impl->fromat_.nImageWidth) *
(impl->fromat_.dBytesOfPixel);
std::copy(impl->FrameDataVector_.begin() + (currentFrame * impl->frameSize_)+HeadOffset,
impl->FrameDataVector_.begin() + (currentFrame * impl->frameSize_)+ HeadOffset + impl->ImageSize_,
buffer.begin());
}
else {
//尾参数行
// std::lock_guard<std::mutex> lock(impl->queueMutex_);
//auto ptr = (impl->FrameDataVector_.data() + ((currentFrame * impl->frameSize_)));
std::copy(impl->FrameDataVector_.begin()+ (currentFrame * impl->frameSize_),
impl->FrameDataVector_.begin()+ (currentFrame * impl->frameSize_)+ impl->ImageSize_,
buffer.begin());
}
return buffer;
}
return std::nullopt;
}
void MyStream::startReadFile()
{
impl->taskFuture_ = std::async(std::launch::async, [this]() {
std::filesystem::path filePath = impl->filePath_;
if (!std::filesystem::exists(impl->filePath_))
{
impl->errorCode_ = FileNotExit;
return false;
}
uintmax_t fileSize = std::filesystem::file_size(impl->filePath_);
std::ifstream file(impl->filePath_, std::ios::binary);
if (!file)
{
impl->errorCode_ = FileOpenFaild;
return false;
}
impl->totalFrame_ = fileSize / impl->frameSize_;
std::lock_guard lock(impl->queueMutex_);
impl->FrameDataVector_.reserve(fileSize);
size_t framesRead = 0;
while (framesRead < impl->totalFrame_)
{
std::vector<char> frame(impl->frameSize_);
file.read(reinterpret_cast<char*>(frame.data()), impl->frameSize_);
if (file.gcount() != impl->frameSize_)
{
impl->errorCode_ = FileFrameNotFull;
return false;
}
impl->FrameDataVector_.insert(impl->FrameDataVector_.end(), frame.begin(), frame.end());
framesRead++;
}
file.close();
return true;
});
}
MyIterator& MyIterator::operator++()noexcept
{
if (current_frame < stream_->getTotalFrameCount())
{
++current_frame;
}
return *this;
}
MyIterator MyIterator::operator++(int)noexcept
{
MyIterator temp = *this;
++(*this);
return temp;
}
MyIterator& MyIterator::operator--()noexcept
{
if (current_frame > 0)
{
--current_frame;
}
return *this;
}
MyIterator MyIterator::operator--(int)noexcept
{
MyIterator temp = *this;
--(*this);
return temp;
}
bool MyIterator::operator ==(const MyIterator& other) const
{
return current_frame == other.current_frame;
}
bool MyIterator::operator != (const MyIterator& other) const
{
return current_frame != other.current_frame;
}
MyIterator MyStream::begin()const
{
return MyIterator(this, 0);
}
MyIterator MyStream::end()const
{
return MyIterator(this, this->getTotalFrameCount());
}
MyIterator::GuideRawFileStreamIterator(const GuideRawFileStream* stream, size_t currentFrame)
:stream_(stream),current_frame(currentFrame)
{
}
GuideRawFileStream::GuideRawFileStreamIterator::GuideRawFileStreamIterator(const GuideRawFileStreamIterator& rhs)noexcept
{
this->current_frame = rhs.current_frame;
this->stream_ = rhs.stream_;
}
std::optional<std::vector<char>> MyIterator::getImageDataWithParame()
{
return stream_->getImageDataWithParame(current_frame);
}
std::optional<std::vector<char>> MyIterator::getImageData()
{
return stream_->getImageData(current_frame);
}
size_t MyIterator::getCurrentFrameCount() const
{
return current_frame;
}
}//namespaceRawFileTools