#include #include // For IThumbnailProvider. #include #include "libxisf.h" #include "../src/rawimage.h" bool loadXISF(const LibXISF::ByteArray &data, std::shared_ptr &rawImage); bool loadFITS(const LibXISF::ByteArray &data, std::shared_ptr &rawImage); void RawImageToHTBITMAP(std::shared_ptr &rawImage, HBITMAP *hbmp, UINT thumbSize) { rawImage->calcStats(); DWORD thre = 20; DWORD dataSize = 4; HRESULT hr = HRESULT_FROM_WIN32(RegGetValueW(HKEY_CURRENT_USER, L"SOFTWARE\\nou\\Tenmon\\settings", L"thumbnailstretchthreshold", RRF_RT_DWORD, NULL, &thre, &dataSize)); float thref = 0.1f; if(hr == S_OK) thref = thre / 100.0f; if(rawImage->imageStats().m_median[0] < rawImage->norm() * thref) { //OutputDebugStringA("Stretch image"); MTFParam params = rawImage->calcMTFParams(); rawImage->applySTF(params); } UINT w = rawImage->width(); UINT h = rawImage->height(); UINT cw = thumbSize; UINT ch = thumbSize; if (w > h) ch = h * thumbSize / w; else cw = w * thumbSize / h; rawImage->resize(cw, ch); rawImage->convertToType(RawImage::UINT8); BITMAPINFO bmi = {}; bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); bmi.bmiHeader.biWidth = cw; bmi.bmiHeader.biHeight = -static_cast(ch); bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; UINT lw = cw * 4; BYTE *pBits; HBITMAP bmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, reinterpret_cast(&pBits), NULL, 0); const unsigned char *p = (const unsigned char*)rawImage->data(); const unsigned short *ps = (const unsigned short*)rawImage->data(); if(rawImage->channels() == 1) { for(UINT y = 0; y < ch; y++) { for(UINT x = 0; x < cw; x++) { pBits[(y * lw) + x * 4 + 0] = p[y * cw + x]; pBits[(y * lw) + x * 4 + 1] = p[y * cw + x]; pBits[(y * lw) + x * 4 + 2] = p[y * cw + x]; pBits[(y * lw) + x * 4 + 3] = 255; } } } else { for(UINT y = 0; y < ch; y++) { for(UINT x = 0; x < cw; x++) { pBits[(y * lw) + x * 4 + 0] = p[y * cw * 4 + x * 4 + 2]; pBits[(y * lw) + x * 4 + 1] = p[y * cw * 4 + x * 4 + 1]; pBits[(y * lw) + x * 4 + 2] = p[y * cw * 4 + x * 4 + 0]; pBits[(y * lw) + x * 4 + 3] = 255; } } } *hbmp = bmp; } class TenmonThumbProvider : public IInitializeWithStream, public IThumbnailProvider { public: TenmonThumbProvider() : _cRef(1), _pStream(NULL) { } virtual ~TenmonThumbProvider() { if (_pStream) { _pStream->Release(); } } // IUnknown IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv) { static const QITAB qit[] = { QITABENT(TenmonThumbProvider, IInitializeWithStream), QITABENT(TenmonThumbProvider, IThumbnailProvider), { 0 }, }; return QISearch(this, qit, riid, ppv); } IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&_cRef); } IFACEMETHODIMP_(ULONG) Release() { ULONG cRef = InterlockedDecrement(&_cRef); if (!cRef) { delete this; } return cRef; } // IInitializeWithStream IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode); // IThumbnailProvider IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha); private: long _cRef; IStream *_pStream; // provided during initialization. }; HRESULT TenmonThumbnailer_CreateInstance(REFIID riid, void **ppv) { TenmonThumbProvider *pNew = new (std::nothrow) TenmonThumbProvider(); HRESULT hr = pNew ? S_OK : E_OUTOFMEMORY; if (SUCCEEDED(hr)) { hr = pNew->QueryInterface(riid, ppv); pNew->Release(); } return hr; } // IInitializeWithStream IFACEMETHODIMP TenmonThumbProvider::Initialize(IStream *pStream, DWORD) { HRESULT hr = E_UNEXPECTED; // can only be inited once if (_pStream == NULL) { // take a reference to the stream if we have not been inited yet hr = pStream->QueryInterface(&_pStream); } return hr; } // IThumbnailProvider IFACEMETHODIMP TenmonThumbProvider::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha) { LibXISF::ByteArray data; ULONG readSize = 0; ULONG read; data.resize(1024*1024); while(_pStream->Read(data.data() + readSize, data.size() - readSize, &read) == S_OK) { readSize += read; data.resize(data.size() + 1024*1024); } readSize += read; *pdwAlpha = WTSAT_RGB; data.resize(readSize); std::shared_ptr rawImage; if(data[0] == 'X' && data[1] == 'I' && data[2] == 'S' && data[3] == 'F') { if(!loadXISF(data, rawImage)) return E_FAIL; } else { if(!loadFITS(data, rawImage)) return E_FAIL; } RawImageToHTBITMAP(rawImage, phbmp, cx); return S_OK; }