/****************************************************************** * !注意! * * 本头文件中为你封装了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 #include #include template 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