Blender V4.3
blendthumb_win32.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <cmath>
12#include <new>
13#include <shlwapi.h>
14#include <string>
15#include <thumbcache.h> /* for #IThumbnailProvider */
16
17#include "Wincodec.h"
18
19#include "blendthumb.hh"
20
21#include "BLI_filereader.h"
22
23#pragma comment(lib, "shlwapi.lib")
24
29class CBlendThumb : public IInitializeWithStream, public IThumbnailProvider {
30 public:
31 CBlendThumb() : _cRef(1), _pStream(nullptr) {}
32
33 virtual ~CBlendThumb()
34 {
35 if (_pStream) {
36 _pStream->Release();
37 }
38 }
39
40 IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
41 {
42 static const QITAB qit[] = {
43 QITABENT(CBlendThumb, IInitializeWithStream),
44 QITABENT(CBlendThumb, IThumbnailProvider),
45 {0},
46 };
47 return QISearch(this, qit, riid, ppv);
48 }
49
50 IFACEMETHODIMP_(ULONG) AddRef()
51 {
52 return InterlockedIncrement(&_cRef);
53 }
54
55 IFACEMETHODIMP_(ULONG) Release()
56 {
57 ULONG cRef = InterlockedDecrement(&_cRef);
58 if (!cRef) {
59 delete this;
60 }
61 return cRef;
62 }
63
65 IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode);
66
68 IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha);
69
70 private:
71 long _cRef;
72 IStream *_pStream; /* provided in Initialize(). */
73};
74
75HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv)
76{
77 CBlendThumb *pNew = new (std::nothrow) CBlendThumb();
78 HRESULT hr = pNew ? S_OK : E_OUTOFMEMORY;
79 if (SUCCEEDED(hr)) {
80 hr = pNew->QueryInterface(riid, ppv);
81 pNew->Release();
82 }
83 return hr;
84}
85
86IFACEMETHODIMP CBlendThumb::Initialize(IStream *pStream, DWORD)
87{
88 if (_pStream != nullptr) {
89 /* Can only be initialized once. */
90 return E_UNEXPECTED;
91 }
92 /* Take a reference to the stream. */
93 return pStream->QueryInterface(&_pStream);
94}
95
101
102 IStream *_pStream;
103};
104
105static int64_t stream_read(FileReader *reader, void *buffer, size_t size)
106{
107 StreamReader *stream = (StreamReader *)reader;
108
109 ULONG readsize;
110 stream->_pStream->Read(buffer, size, &readsize);
111 stream->reader.offset += readsize;
112
113 return int64_t(readsize);
114}
115
116static off64_t stream_seek(FileReader *reader, off64_t offset, int whence)
117{
118 StreamReader *stream = (StreamReader *)reader;
119
120 DWORD origin = STREAM_SEEK_SET;
121 switch (whence) {
122 case SEEK_CUR:
123 origin = STREAM_SEEK_CUR;
124 break;
125 case SEEK_END:
126 origin = STREAM_SEEK_END;
127 break;
128 }
129 LARGE_INTEGER offsetI;
130 offsetI.QuadPart = offset;
131 ULARGE_INTEGER newPos;
132 stream->_pStream->Seek(offsetI, origin, &newPos);
133 stream->reader.offset = newPos.QuadPart;
134
135 return stream->reader.offset;
136}
137
138static void stream_close(FileReader *reader)
139{
140 StreamReader *stream = (StreamReader *)reader;
141 delete stream;
142}
143
144IFACEMETHODIMP CBlendThumb::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha)
145{
146 HRESULT hr = S_FALSE;
147
148 StreamReader *file = new StreamReader;
149 file->reader.read = stream_read;
150 file->reader.seek = stream_seek;
151 file->reader.close = stream_close;
152 file->reader.offset = 0;
153 file->_pStream = _pStream;
154
155 file->reader.seek(&file->reader, 0, SEEK_SET);
156
157 /* Extract thumbnail from stream. */
158 Thumbnail thumb;
159 if (blendthumb_create_thumb_from_file(&file->reader, &thumb) != BT_OK) {
160 return S_FALSE;
161 }
162
163 /* Convert to BGRA for Windows. */
164 for (int i = 0; i < thumb.width * thumb.height; i++) {
165 std::swap(thumb.data[4 * i], thumb.data[4 * i + 2]);
166 }
167
168 *phbmp = CreateBitmap(thumb.width, thumb.height, 1, 32, thumb.data.data());
169 if (!*phbmp) {
170 return E_FAIL;
171 }
172 *pdwAlpha = WTSAT_ARGB;
173
174 /* Scale up the thumbnail if required. */
175 if (uint(thumb.width) < cx && uint(thumb.height) < cx) {
176 float scale = 1.0f / (std::max(thumb.width, thumb.height) / float(cx));
177 LONG NewWidth = LONG(thumb.width * scale);
178 LONG NewHeight = LONG(thumb.height * scale);
179
180 IWICImagingFactory *pImgFac;
181 hr = CoCreateInstance(
182 CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImgFac));
183
184 IWICBitmap *WICBmp;
185 hr = pImgFac->CreateBitmapFromHBITMAP(*phbmp, 0, WICBitmapUseAlpha, &WICBmp);
186
187 BITMAPINFO bmi = {};
188 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
189 bmi.bmiHeader.biWidth = NewWidth;
190 bmi.bmiHeader.biHeight = -NewHeight;
191 bmi.bmiHeader.biPlanes = 1;
192 bmi.bmiHeader.biBitCount = 32;
193 bmi.bmiHeader.biCompression = BI_RGB;
194
195 BYTE *pBits;
196 HBITMAP ResizedHBmp = CreateDIBSection(
197 nullptr, &bmi, DIB_RGB_COLORS, (void **)&pBits, nullptr, 0);
198 hr = ResizedHBmp ? S_OK : E_OUTOFMEMORY;
199 if (SUCCEEDED(hr)) {
200 IWICBitmapScaler *pIScaler;
201 hr = pImgFac->CreateBitmapScaler(&pIScaler);
202 hr = pIScaler->Initialize(WICBmp, NewWidth, NewHeight, WICBitmapInterpolationModeFant);
203
204 WICRect rect = {0, 0, NewWidth, NewHeight};
205 hr = pIScaler->CopyPixels(&rect, NewWidth * 4, NewWidth * NewHeight * 4, pBits);
206
207 if (SUCCEEDED(hr)) {
208 DeleteObject(*phbmp);
209 *phbmp = ResizedHBmp;
210 }
211 else {
212 DeleteObject(ResizedHBmp);
213 }
214
215 pIScaler->Release();
216 }
217 WICBmp->Release();
218 pImgFac->Release();
219 }
220 else {
221 hr = S_OK;
222 }
223 return hr;
224}
Wrapper for reading from various sources (e.g. raw files, compressed files, memory....
unsigned int uint
eThumbStatus blendthumb_create_thumb_from_file(FileReader *rawfile, Thumbnail *thumb)
@ BT_OK
Definition blendthumb.hh:29
static void stream_close(FileReader *reader)
static int64_t stream_read(FileReader *reader, void *buffer, size_t size)
HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv)
static off64_t stream_seek(FileReader *reader, off64_t offset, int whence)
IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode)
IFACEMETHODIMP_(ULONG) AddRef()
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha)
IFACEMETHODIMP_(ULONG) Release()
virtual ~CBlendThumb()
const T * data() const
Definition BLI_array.hh:301
draw_view in_light_buf[] float
__int64 int64_t
Definition stdint.h:89
off64_t offset
FileReaderReadFn read
blender::Array< uint8_t > data
Definition blendthumb.hh:23