C++/CX 如何将 IRandomAccessStream^ 转换为字节并返回。 (UWP)
C++/CX How to convert from IRandomAccessStream^ to bytes and back. (UWP)
所以我有一个流,我希望能够将它转换为 unsigned char * bytes 并返回可用流。
这个流是图片(重要的话是二进制的?)
基本上我现在的尝试是这样的:
IRandomAccessStream^ inputStream;
DataWriter^ dataWriter = ref new DataWriter(inputStream);
IBuffer^ buffer1 = dataWriter->DetachBuffer();
unsigned char * bytes = GetPointerToPixelData(buffer1);
DataWriter ^writer = ref new DataWriter();
writer->WriteBytes(Platform::ArrayReference<BYTE>(bytes, sizeof(bytes)));
task<DataWriterStoreOperation^>(writer->StoreAsync()).get();
task<Windows::Foundation::IAsyncOperation<bool>>(writer->FlushAsync()).get();
IBuffer ^buffer2 = writer->DetachBuffer();
IRandomAccessStream^ newStream;
task<Windows::Foundation::IAsyncOperationWithProgress<unsigned int, unsigned int>>(newStream->WriteAsync(buffer2)).get();
task<Windows::Foundation::IAsyncOperation<bool>>(newStream->FlushAsync()).get();
UseNewStream(newStream)
我已经添加了所有这些任务<...>,因为没有它们它就无法工作,而且我不确定如何让它工作?
我在网上找到的函数 GetPointerToPixelData 如下:
byte* GetPointerToPixelData(IBuffer^ buffer)
{
// Cast to Object^, then to its underlying IInspectable interface.
Object^ obj = buffer;
ComPtr<IInspectable> insp(reinterpret_cast<IInspectable*>(obj));
// Query the IBufferByteAccess interface.
ComPtr<IBufferByteAccess> bufferByteAccess;
insp.As(&bufferByteAccess);
// Retrieve the buffer data.
byte* pixels = nullptr;
bufferByteAccess->Buffer(&pixels);
return pixels;
}
谢谢! :)
首先,如果要将图像流转为字节,需要通过DataReader
, not by DataWriter
读取流,用于写数据。其次,DetachBuffer()
方法是针对"Detaches the buffer that is associated with the data reader"的,不是读缓冲区。最后,DataReader
可以直接用ReadBytes(Byte[])
方法读取字节。例如:
uint64 length = 0;
BYTE *extracted;
void CleanImagetobyte::MainPage::btnconverttobyte_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
create_task(KnownFolders::GetFolderForUserAsync(nullptr /* current user */, KnownFolderId::PicturesLibrary))
.then([this](StorageFolder^ picturesFolder)
{
return picturesFolder->GetFileAsync("B.jpg");
}).then([this](task<StorageFile^> task)
{
try
{
StorageFile^ file = task.get();
auto name = file->Name;
return file->OpenAsync(FileAccessMode::Read);
}
catch (Exception^ e)
{
// I/O errors are reported as exceptions.
}
}).then([this](task<IRandomAccessStream^> task)
{
IRandomAccessStream^ inputStream = task.get();
length = inputStream->Size;
IBuffer^ buffer = ref new Buffer(inputStream->Size);
inputStream->ReadAsync(buffer, inputStream->Size, InputStreamOptions::None);
DataReader^ reader = DataReader::FromBuffer(buffer);
extracted = new BYTE[buffer->Length];
reader->ReadBytes(Platform::ArrayReference<BYTE>(extracted, buffer->Length));
});
}
void CleanImagetobyte::MainPage::btnconvertback_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
create_task(KnownFolders::GetFolderForUserAsync(nullptr /* current user */, KnownFolderId::PicturesLibrary))
.then([this](StorageFolder^ picturesFolder)
{
return picturesFolder->CreateFileAsync("newB.jpg", CreationCollisionOption::ReplaceExisting);
}).then([this](task<StorageFile^> task)
{
StorageFile^ file = task.get();
Array<byte>^ arr = ref new Array<byte>(extracted, length);
FileIO::WriteBytesAsync(file, arr);
});
}
更详细的读写文件请参考this document。
所以我有一个流,我希望能够将它转换为 unsigned char * bytes 并返回可用流。
这个流是图片(重要的话是二进制的?)
基本上我现在的尝试是这样的:
IRandomAccessStream^ inputStream;
DataWriter^ dataWriter = ref new DataWriter(inputStream);
IBuffer^ buffer1 = dataWriter->DetachBuffer();
unsigned char * bytes = GetPointerToPixelData(buffer1);
DataWriter ^writer = ref new DataWriter();
writer->WriteBytes(Platform::ArrayReference<BYTE>(bytes, sizeof(bytes)));
task<DataWriterStoreOperation^>(writer->StoreAsync()).get();
task<Windows::Foundation::IAsyncOperation<bool>>(writer->FlushAsync()).get();
IBuffer ^buffer2 = writer->DetachBuffer();
IRandomAccessStream^ newStream;
task<Windows::Foundation::IAsyncOperationWithProgress<unsigned int, unsigned int>>(newStream->WriteAsync(buffer2)).get();
task<Windows::Foundation::IAsyncOperation<bool>>(newStream->FlushAsync()).get();
UseNewStream(newStream)
我已经添加了所有这些任务<...>,因为没有它们它就无法工作,而且我不确定如何让它工作? 我在网上找到的函数 GetPointerToPixelData 如下:
byte* GetPointerToPixelData(IBuffer^ buffer)
{
// Cast to Object^, then to its underlying IInspectable interface.
Object^ obj = buffer;
ComPtr<IInspectable> insp(reinterpret_cast<IInspectable*>(obj));
// Query the IBufferByteAccess interface.
ComPtr<IBufferByteAccess> bufferByteAccess;
insp.As(&bufferByteAccess);
// Retrieve the buffer data.
byte* pixels = nullptr;
bufferByteAccess->Buffer(&pixels);
return pixels;
}
谢谢! :)
首先,如果要将图像流转为字节,需要通过DataReader
, not by DataWriter
读取流,用于写数据。其次,DetachBuffer()
方法是针对"Detaches the buffer that is associated with the data reader"的,不是读缓冲区。最后,DataReader
可以直接用ReadBytes(Byte[])
方法读取字节。例如:
uint64 length = 0;
BYTE *extracted;
void CleanImagetobyte::MainPage::btnconverttobyte_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
create_task(KnownFolders::GetFolderForUserAsync(nullptr /* current user */, KnownFolderId::PicturesLibrary))
.then([this](StorageFolder^ picturesFolder)
{
return picturesFolder->GetFileAsync("B.jpg");
}).then([this](task<StorageFile^> task)
{
try
{
StorageFile^ file = task.get();
auto name = file->Name;
return file->OpenAsync(FileAccessMode::Read);
}
catch (Exception^ e)
{
// I/O errors are reported as exceptions.
}
}).then([this](task<IRandomAccessStream^> task)
{
IRandomAccessStream^ inputStream = task.get();
length = inputStream->Size;
IBuffer^ buffer = ref new Buffer(inputStream->Size);
inputStream->ReadAsync(buffer, inputStream->Size, InputStreamOptions::None);
DataReader^ reader = DataReader::FromBuffer(buffer);
extracted = new BYTE[buffer->Length];
reader->ReadBytes(Platform::ArrayReference<BYTE>(extracted, buffer->Length));
});
}
void CleanImagetobyte::MainPage::btnconvertback_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
create_task(KnownFolders::GetFolderForUserAsync(nullptr /* current user */, KnownFolderId::PicturesLibrary))
.then([this](StorageFolder^ picturesFolder)
{
return picturesFolder->CreateFileAsync("newB.jpg", CreationCollisionOption::ReplaceExisting);
}).then([this](task<StorageFile^> task)
{
StorageFile^ file = task.get();
Array<byte>^ arr = ref new Array<byte>(extracted, length);
FileIO::WriteBytesAsync(file, arr);
});
}
更详细的读写文件请参考this document。