This repository has been archived on 2025-11-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
cpp-AsciiArtPlayer/Z_3/PicReader.h
2025-11-09 14:10:48 +08:00

194 lines
6.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/******************************************************************
* !注意! *
* 本头文件中为你封装了WinAPI中WIC底层函数方便你进行图片读取而不必引 *
* 入或安装其他的外部库,但是我们有一定的约束条件,请你仔细阅读以下规定 *
* 本头文件中任何没有TO-DO的地方请你不要修改若函数存在问题 *
* 请及时联系老师或助教! *
* 每一个TO-DO块以TO-DO说明 (TO-DO) END 结束,具体可看下方代码 *
* readPic()函数为你封装了WinAPI中的方法可以将图片读取为RGBA的 *
* bitmap数据但这并不代表你可以通过修改这个函数直接达到读取灰度图的 *
* 目的。 *
* getData()是你最终需要完善的函数将读取出来的一维BYTE数组转换 *
* 成你实现的Array类。 *
* testReader()是demo中提供读取数据的其中一个思路。 *
******************************************************************/
#ifndef PIC_READER_H
#define PIC_READER_H
#include <windows.h>
#include <wincodec.h>
#include <commdlg.h>
template <typename T>
inline void SafeRelease(T *&p) {
if (nullptr != p) {
p->Release();
p = nullptr;
}
}
class PicReader {
public:
PicReader();
~PicReader();
void readPic(LPCSTR);
void /*TO-DO可能你需要修改返回类型 END*/ getData(/*TO-DO这里可能需要修改传参 END*/);
void testReader(BYTE *&,UINT &, UINT &);
private:
void init();
bool checkHR(HRESULT);
void quitWithError(LPCSTR);
HWND hWnd;
HANDLE hFile;
IWICImagingFactory *m_pIWICFactory;
IWICFormatConverter *m_pConvertedSourceBitmap;
/*TO-DO这里可能会增加你需要的内部成员 END*/
};
PicReader::PicReader() : m_pConvertedSourceBitmap(nullptr), m_pIWICFactory(nullptr) {
init();
}
PicReader::~PicReader() {
if (hFile != NULL) CloseHandle(hFile);
SafeRelease(m_pConvertedSourceBitmap);
SafeRelease(m_pIWICFactory);
CoUninitialize();
}
bool PicReader::checkHR(HRESULT hr) {
return (hr < 0);
}
void PicReader::quitWithError(LPCSTR message) {
MessageBoxA(hWnd, message, "Application Error", MB_ICONEXCLAMATION | MB_OK);
quick_exit(0xffffffff);
}
void PicReader::init() {
hWnd = GetForegroundWindow();
// Enables the terminate-on-corruption feature.
HeapSetInformation(nullptr, HeapEnableTerminationOnCorruption, nullptr, 0);
HRESULT hr = S_OK;
//Init the WIC
hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
// Create WIC factory
hr = CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&m_pIWICFactory)
);
// Throw error if create factor failed
if (checkHR(hr)) { quitWithError("Init Reader Failed"); }
}
void PicReader::readPic(LPCSTR fileName) {
HRESULT hr = S_OK;
// Create a File Handle (WinAPI method not std c)
if (hFile != NULL) CloseHandle(hFile);
hFile = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
quitWithError("Cannot find such file, please retry or check the access");
}
// Create a decoder
IWICBitmapDecoder *pDecoder = nullptr;
hr = m_pIWICFactory->CreateDecoderFromFileHandle((ULONG_PTR)hFile, nullptr, WICDecodeMetadataCacheOnDemand, &pDecoder);
if (checkHR(hr)) { quitWithError("Create Decoder Failed"); }
// Retrieve the first frame of the image from the decoder
IWICBitmapFrameDecode *pFrame = nullptr;
hr = pDecoder->GetFrame(0, &pFrame);
if (checkHR(hr)) { quitWithError("Get Frame Failed"); }
// Format convert the frame to 32bppRGBA
SafeRelease(m_pConvertedSourceBitmap);
hr = m_pIWICFactory->CreateFormatConverter(&m_pConvertedSourceBitmap);
if (checkHR(hr)) { quitWithError("Get Format Converter Failed"); }
hr = m_pConvertedSourceBitmap->Initialize(pFrame, GUID_WICPixelFormat32bppRGBA, WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeCustom);
if (checkHR(hr)) { quitWithError("Init Bitmap Failed"); }
// Clean memory
SafeRelease(pDecoder);
SafeRelease(pFrame);
}
void /*TO-DO可能你需要修改返回类型 END*/ PicReader::getData(/*TO-DO这里可能需要修改传参 END*/) {
HRESULT hr = S_OK;
// Get the size of Image
UINT x, y;
hr = m_pConvertedSourceBitmap->GetSize(&x, &y);
if (checkHR(hr)) { quitWithError("Check Bitmap Size Failed"); }
// Create the buffer of pixels, the type of BYTE is unsigned char
BYTE *data;
data = new BYTE[x * y * 4];
memset(data, 0, x * y * 4);
// Copy the pixels to the buffer
UINT stride = x * 4;
hr = m_pConvertedSourceBitmap->CopyPixels(nullptr, stride, x * y * 4, data);
if (checkHR(hr)) { quitWithError("Copy Pixels Failed"); }
/******************************************************************
* TO-DO: *
* *
* 实现一个Array类并将上面的data转存至你的Array内 *
* *
* 数据说明从Bitmap Copy出来的数据每4个为一组代表一个像素 *
* 数据为一个长度为图像的(长*宽*4)的一维数组 *
* 即数据排布为 R G B A R G B A R G B A..... *
* *
* !注意! 你仅可以只改动从此开始到下一个TO-DO END位置的代码 *
******************************************************************/
delete[] data;
/******************************************************************
* TO-DO END *
******************************************************************/
// Close the file handle
CloseHandle(hFile);
hFile = NULL;
}
void PicReader::testReader(BYTE* &_out, UINT& _x, UINT& _y){
HRESULT hr = S_OK;
// Get the size of Image
UINT x, y;
hr = m_pConvertedSourceBitmap->GetSize(&x, &y);
if (checkHR(hr)) { quitWithError("Check Bitmap Size Failed"); }
// Create the buffer of pixels, the type of BYTE is unsigned char
BYTE *data;
data = new BYTE[x * y * 4];
memset(data, 0, x * y * 4);
// Copy the pixels to the buffer
UINT stride = x * 4;
hr = m_pConvertedSourceBitmap->CopyPixels(nullptr, stride, x * y * 4, data);
if (checkHR(hr)) { quitWithError("Copy Pixels Failed"); }
_out = data; _x = x; _y = y;
// Close the file handle
CloseHandle(hFile);
hFile = NULL;
}
#endif