Blender  V3.3
blendthumb_win32.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include <math.h>
10 #include <new>
11 #include <shlwapi.h>
12 #include <string>
13 #include <thumbcache.h> /* for #IThumbnailProvider */
14 
15 #include "Wincodec.h"
16 
17 #include "blendthumb.hh"
18 
19 #include "BLI_filereader.h"
20 
21 #pragma comment(lib, "shlwapi.lib")
22 
27 class CBlendThumb : public IInitializeWithStream, public IThumbnailProvider {
28  public:
29  CBlendThumb() : _cRef(1), _pStream(NULL)
30  {
31  }
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 
75 HRESULT 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 
86 IFACEMETHODIMP CBlendThumb::Initialize(IStream *pStream, DWORD)
87 {
88  if (_pStream != NULL) {
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 
99 typedef struct {
101 
102  IStream *_pStream;
103 } StreamReader;
104 
105 static ssize_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 (ssize_t)readsize;
114 }
115 
116 static 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 
138 static void stream_close(FileReader *reader)
139 {
140  StreamReader *stream = (StreamReader *)reader;
141  delete stream;
142 }
143 
144 IFACEMETHODIMP CBlendThumb::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha)
145 {
146  HRESULT hr = S_FALSE;
147 
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 down the thumbnail if required. */
175  if ((unsigned)thumb.width > cx || (unsigned)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, NULL, 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(NULL, &bmi, DIB_RGB_COLORS, (void **)&pBits, NULL, 0);
197  hr = ResizedHBmp ? S_OK : E_OUTOFMEMORY;
198  if (SUCCEEDED(hr)) {
199  IWICBitmapScaler *pIScaler;
200  hr = pImgFac->CreateBitmapScaler(&pIScaler);
201  hr = pIScaler->Initialize(WICBmp, NewWidth, NewHeight, WICBitmapInterpolationModeFant);
202 
203  WICRect rect = {0, 0, NewWidth, NewHeight};
204  hr = pIScaler->CopyPixels(&rect, NewWidth * 4, NewWidth * NewHeight * 4, pBits);
205 
206  if (SUCCEEDED(hr)) {
207  DeleteObject(*phbmp);
208  *phbmp = ResizedHBmp;
209  }
210  else {
211  DeleteObject(ResizedHBmp);
212  }
213 
214  pIScaler->Release();
215  }
216  WICBmp->Release();
217  pImgFac->Release();
218  }
219  else {
220  hr = S_OK;
221  }
222  return hr;
223 }
typedef float(TangentPoint)[2]
Wrapper for reading from various sources (e.g. raw files, compressed files, memory....
SSIZE_T ssize_t
Definition: BLI_winstuff.h:71
void swap(T &a, T &b)
Definition: Common.h:19
typedef UINT(API *GHOST_WIN32_GetDpiForWindow)(HWND)
@ BT_OK
Definition: blendthumb.hh:28
eThumbStatus blendthumb_create_thumb_from_file(struct FileReader *rawfile, Thumbnail *thumb)
static void stream_close(FileReader *reader)
HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv)
static off64_t stream_seek(FileReader *reader, off64_t offset, int whence)
static ssize_t stream_read(FileReader *reader, void *buffer, size_t size)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
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:300
FILE * file
ccl_global float * buffer
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
off64_t offset
FileReader reader
IStream * _pStream
blender::Array< uint8_t > data
Definition: blendthumb.hh:22
int height
Definition: blendthumb.hh:24
float max