[WINDOWSCODECS]
[reactos.git] / reactos / dll / win32 / windowscodecs / bmpencode.c
1 /*
2 * Copyright 2009 Vincent Povirk for CodeWeavers
3 * Copyright 2016 Dmitry Timoshkov
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #include "wincodecs_private.h"
21
22 #include <wingdi.h>
23
24 struct bmp_pixelformat {
25 const WICPixelFormatGUID *guid;
26 UINT bpp;
27 UINT colors; /* palette size */
28 DWORD compression;
29 DWORD redmask;
30 DWORD greenmask;
31 DWORD bluemask;
32 DWORD alphamask;
33 };
34
35 static const struct bmp_pixelformat formats[] = {
36 {&GUID_WICPixelFormat24bppBGR, 24, 0, BI_RGB},
37 {&GUID_WICPixelFormatBlackWhite, 1, 2, BI_RGB},
38 {&GUID_WICPixelFormat1bppIndexed, 1, 2, BI_RGB},
39 {&GUID_WICPixelFormat2bppIndexed, 2, 4, BI_RGB},
40 {&GUID_WICPixelFormat4bppIndexed, 4, 16, BI_RGB},
41 {&GUID_WICPixelFormat8bppIndexed, 8, 256, BI_RGB},
42 {&GUID_WICPixelFormat16bppBGR555, 16, 0, BI_RGB},
43 {&GUID_WICPixelFormat16bppBGR565, 16, 0, BI_BITFIELDS, 0xf800, 0x7e0, 0x1f, 0},
44 {&GUID_WICPixelFormat32bppBGR, 32, 0, BI_RGB},
45 #if 0
46 /* Windows doesn't seem to support this one. */
47 {&GUID_WICPixelFormat32bppBGRA, 32, 0, BI_BITFIELDS, 0xff0000, 0xff00, 0xff, 0xff000000},
48 #endif
49 {NULL}
50 };
51
52 typedef struct BmpFrameEncode {
53 IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
54 LONG ref;
55 IStream *stream;
56 BOOL initialized;
57 UINT width, height;
58 BYTE *bits;
59 const struct bmp_pixelformat *format;
60 double xres, yres;
61 UINT lineswritten;
62 UINT stride;
63 WICColor palette[256];
64 UINT colors;
65 BOOL committed;
66 } BmpFrameEncode;
67
68 static inline BmpFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
69 {
70 return CONTAINING_RECORD(iface, BmpFrameEncode, IWICBitmapFrameEncode_iface);
71 }
72
73 static HRESULT WINAPI BmpFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid,
74 void **ppv)
75 {
76 BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
77 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
78
79 if (!ppv) return E_INVALIDARG;
80
81 if (IsEqualIID(&IID_IUnknown, iid) ||
82 IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
83 {
84 *ppv = &This->IWICBitmapFrameEncode_iface;
85 }
86 else
87 {
88 *ppv = NULL;
89 return E_NOINTERFACE;
90 }
91
92 IUnknown_AddRef((IUnknown*)*ppv);
93 return S_OK;
94 }
95
96 static ULONG WINAPI BmpFrameEncode_AddRef(IWICBitmapFrameEncode *iface)
97 {
98 BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
99 ULONG ref = InterlockedIncrement(&This->ref);
100
101 TRACE("(%p) refcount=%u\n", iface, ref);
102
103 return ref;
104 }
105
106 static ULONG WINAPI BmpFrameEncode_Release(IWICBitmapFrameEncode *iface)
107 {
108 BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
109 ULONG ref = InterlockedDecrement(&This->ref);
110
111 TRACE("(%p) refcount=%u\n", iface, ref);
112
113 if (ref == 0)
114 {
115 if (This->stream) IStream_Release(This->stream);
116 HeapFree(GetProcessHeap(), 0, This->bits);
117 HeapFree(GetProcessHeap(), 0, This);
118 }
119
120 return ref;
121 }
122
123 static HRESULT WINAPI BmpFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
124 IPropertyBag2 *pIEncoderOptions)
125 {
126 BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
127 TRACE("(%p,%p)\n", iface, pIEncoderOptions);
128
129 if (This->initialized) return WINCODEC_ERR_WRONGSTATE;
130
131 This->initialized = TRUE;
132
133 return S_OK;
134 }
135
136 static HRESULT WINAPI BmpFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
137 UINT uiWidth, UINT uiHeight)
138 {
139 BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
140 TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight);
141
142 if (!This->initialized || This->bits) return WINCODEC_ERR_WRONGSTATE;
143
144 This->width = uiWidth;
145 This->height = uiHeight;
146
147 return S_OK;
148 }
149
150 static HRESULT WINAPI BmpFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
151 double dpiX, double dpiY)
152 {
153 BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
154 TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
155
156 if (!This->initialized || This->bits) return WINCODEC_ERR_WRONGSTATE;
157
158 This->xres = dpiX;
159 This->yres = dpiY;
160
161 return S_OK;
162 }
163
164 static HRESULT WINAPI BmpFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface,
165 WICPixelFormatGUID *pPixelFormat)
166 {
167 BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
168 int i;
169 TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat));
170
171 if (!This->initialized || This->bits) return WINCODEC_ERR_WRONGSTATE;
172
173 for (i=0; formats[i].guid; i++)
174 {
175 if (IsEqualGUID(formats[i].guid, pPixelFormat))
176 break;
177 }
178
179 if (!formats[i].guid) i = 0;
180 else if (IsEqualGUID(pPixelFormat, &GUID_WICPixelFormatBlackWhite))
181 i = 2; /* GUID_WICPixelFormat1bppIndexed */
182
183 This->format = &formats[i];
184 memcpy(pPixelFormat, This->format->guid, sizeof(GUID));
185
186 return S_OK;
187 }
188
189 static HRESULT WINAPI BmpFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface,
190 UINT cCount, IWICColorContext **ppIColorContext)
191 {
192 FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
193 return E_NOTIMPL;
194 }
195
196 static HRESULT WINAPI BmpFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
197 IWICPalette *palette)
198 {
199 BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
200 HRESULT hr;
201
202 TRACE("(%p,%p)\n", iface, palette);
203
204 if (!palette) return E_INVALIDARG;
205
206 if (!This->initialized)
207 return WINCODEC_ERR_NOTINITIALIZED;
208
209 hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors);
210 if (hr == S_OK)
211 {
212 UINT i;
213 for (i = 0; i < This->colors; i++)
214 This->palette[i] |= 0xff000000; /* BMP palette has no alpha */
215 }
216 return hr;
217 }
218
219 static HRESULT WINAPI BmpFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
220 IWICBitmapSource *pIThumbnail)
221 {
222 FIXME("(%p,%p): stub\n", iface, pIThumbnail);
223 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
224 }
225
226 static HRESULT BmpFrameEncode_AllocateBits(BmpFrameEncode *This)
227 {
228 if (!This->bits)
229 {
230 if (!This->initialized || !This->width || !This->height || !This->format)
231 return WINCODEC_ERR_WRONGSTATE;
232
233 This->stride = (((This->width * This->format->bpp)+31)/32)*4;
234 This->bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->stride * This->height);
235 if (!This->bits) return E_OUTOFMEMORY;
236 }
237
238 return S_OK;
239 }
240
241 static HRESULT WINAPI BmpFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
242 UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels)
243 {
244 BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
245 HRESULT hr;
246 WICRect rc;
247 TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
248
249 if (!This->initialized || !This->width || !This->height || !This->format)
250 return WINCODEC_ERR_WRONGSTATE;
251
252 hr = BmpFrameEncode_AllocateBits(This);
253 if (FAILED(hr)) return hr;
254
255 rc.X = 0;
256 rc.Y = 0;
257 rc.Width = This->width;
258 rc.Height = lineCount;
259
260 hr = copy_pixels(This->format->bpp, pbPixels, This->width, lineCount, cbStride,
261 &rc, This->stride, This->stride*(This->height-This->lineswritten),
262 This->bits + This->stride*This->lineswritten);
263
264 if (SUCCEEDED(hr))
265 This->lineswritten += lineCount;
266
267 return hr;
268 }
269
270 static HRESULT WINAPI BmpFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
271 IWICBitmapSource *pIBitmapSource, WICRect *prc)
272 {
273 BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
274 HRESULT hr;
275 TRACE("(%p,%p,%p)\n", iface, pIBitmapSource, prc);
276
277 if (!This->initialized)
278 return WINCODEC_ERR_WRONGSTATE;
279
280 hr = configure_write_source(iface, pIBitmapSource, prc,
281 This->format ? This->format->guid : NULL, This->width, This->height,
282 This->xres, This->yres);
283
284 if (SUCCEEDED(hr))
285 {
286 hr = write_source(iface, pIBitmapSource, prc,
287 This->format->guid, This->format->bpp, This->width, This->height);
288 }
289
290 return hr;
291 }
292
293 static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
294 {
295 BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
296 BITMAPFILEHEADER bfh;
297 BITMAPV5HEADER bih;
298 UINT info_size, i;
299 LARGE_INTEGER pos;
300 ULONG byteswritten;
301 HRESULT hr;
302 const BYTE *bits;
303
304 TRACE("(%p)\n", iface);
305
306 if (!This->bits || This->committed || This->height != This->lineswritten)
307 return WINCODEC_ERR_WRONGSTATE;
308
309 bfh.bfType = 0x4d42; /* "BM" */
310 bfh.bfReserved1 = 0;
311 bfh.bfReserved2 = 0;
312
313 bih.bV5Size = info_size = sizeof(BITMAPINFOHEADER);
314 bih.bV5Width = This->width;
315 bih.bV5Height = This->height; /* bottom-top bitmap */
316 bih.bV5Planes = 1;
317 bih.bV5BitCount = This->format->bpp;
318 bih.bV5Compression = This->format->compression;
319 bih.bV5SizeImage = This->stride*This->height;
320 bih.bV5XPelsPerMeter = (This->xres+0.0127) / 0.0254;
321 bih.bV5YPelsPerMeter = (This->yres+0.0127) / 0.0254;
322 bih.bV5ClrUsed = (This->format->bpp <= 8) ? This->colors : 0;
323 bih.bV5ClrImportant = bih.bV5ClrUsed;
324
325 if (This->format->compression == BI_BITFIELDS)
326 {
327 if (This->format->alphamask)
328 bih.bV5Size = info_size = sizeof(BITMAPV4HEADER);
329 else
330 info_size = sizeof(BITMAPINFOHEADER)+12;
331 bih.bV5RedMask = This->format->redmask;
332 bih.bV5GreenMask = This->format->greenmask;
333 bih.bV5BlueMask = This->format->bluemask;
334 bih.bV5AlphaMask = This->format->alphamask;
335 bih.bV5CSType = LCS_DEVICE_RGB;
336 }
337
338 bfh.bfSize = sizeof(BITMAPFILEHEADER) + info_size + bih.bV5SizeImage;
339 bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + info_size;
340 bfh.bfOffBits += bih.bV5ClrUsed * sizeof(WICColor);
341
342 pos.QuadPart = 0;
343 hr = IStream_Seek(This->stream, pos, STREAM_SEEK_SET, NULL);
344 if (FAILED(hr)) return hr;
345
346 hr = IStream_Write(This->stream, &bfh, sizeof(BITMAPFILEHEADER), &byteswritten);
347 if (FAILED(hr)) return hr;
348 if (byteswritten != sizeof(BITMAPFILEHEADER)) return E_FAIL;
349
350 hr = IStream_Write(This->stream, &bih, info_size, &byteswritten);
351 if (FAILED(hr)) return hr;
352 if (byteswritten != info_size) return E_FAIL;
353
354 /* write the palette */
355 if (This->format->colors)
356 {
357 hr = IStream_Write(This->stream, This->palette, This->colors * sizeof(WICColor), &byteswritten);
358 if (FAILED(hr)) return hr;
359 if (byteswritten != This->colors * sizeof(WICColor)) return E_FAIL;
360 }
361
362 /* write the image bits as a bottom-top array */
363 bits = This->bits + bih.bV5SizeImage;
364 for (i = 0; i < This->height; i++)
365 {
366 bits -= This->stride;
367 hr = IStream_Write(This->stream, bits, This->stride, &byteswritten);
368 if (FAILED(hr)) return hr;
369 if (byteswritten != This->stride) return E_FAIL;
370 }
371
372 This->committed = TRUE;
373
374 return S_OK;
375 }
376
377 static HRESULT WINAPI BmpFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface,
378 IWICMetadataQueryWriter **ppIMetadataQueryWriter)
379 {
380 FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter);
381 return E_NOTIMPL;
382 }
383
384 static const IWICBitmapFrameEncodeVtbl BmpFrameEncode_Vtbl = {
385 BmpFrameEncode_QueryInterface,
386 BmpFrameEncode_AddRef,
387 BmpFrameEncode_Release,
388 BmpFrameEncode_Initialize,
389 BmpFrameEncode_SetSize,
390 BmpFrameEncode_SetResolution,
391 BmpFrameEncode_SetPixelFormat,
392 BmpFrameEncode_SetColorContexts,
393 BmpFrameEncode_SetPalette,
394 BmpFrameEncode_SetThumbnail,
395 BmpFrameEncode_WritePixels,
396 BmpFrameEncode_WriteSource,
397 BmpFrameEncode_Commit,
398 BmpFrameEncode_GetMetadataQueryWriter
399 };
400
401 typedef struct BmpEncoder {
402 IWICBitmapEncoder IWICBitmapEncoder_iface;
403 LONG ref;
404 IStream *stream;
405 BmpFrameEncode *frame;
406 } BmpEncoder;
407
408 static inline BmpEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
409 {
410 return CONTAINING_RECORD(iface, BmpEncoder, IWICBitmapEncoder_iface);
411 }
412
413 static HRESULT WINAPI BmpEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid,
414 void **ppv)
415 {
416 BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
417 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
418
419 if (!ppv) return E_INVALIDARG;
420
421 if (IsEqualIID(&IID_IUnknown, iid) ||
422 IsEqualIID(&IID_IWICBitmapEncoder, iid))
423 {
424 *ppv = &This->IWICBitmapEncoder_iface;
425 }
426 else
427 {
428 *ppv = NULL;
429 return E_NOINTERFACE;
430 }
431
432 IUnknown_AddRef((IUnknown*)*ppv);
433 return S_OK;
434 }
435
436 static ULONG WINAPI BmpEncoder_AddRef(IWICBitmapEncoder *iface)
437 {
438 BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
439 ULONG ref = InterlockedIncrement(&This->ref);
440
441 TRACE("(%p) refcount=%u\n", iface, ref);
442
443 return ref;
444 }
445
446 static ULONG WINAPI BmpEncoder_Release(IWICBitmapEncoder *iface)
447 {
448 BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
449 ULONG ref = InterlockedDecrement(&This->ref);
450
451 TRACE("(%p) refcount=%u\n", iface, ref);
452
453 if (ref == 0)
454 {
455 if (This->stream) IStream_Release(This->stream);
456 if (This->frame) IWICBitmapFrameEncode_Release(&This->frame->IWICBitmapFrameEncode_iface);
457 HeapFree(GetProcessHeap(), 0, This);
458 }
459
460 return ref;
461 }
462
463 static HRESULT WINAPI BmpEncoder_Initialize(IWICBitmapEncoder *iface,
464 IStream *pIStream, WICBitmapEncoderCacheOption cacheOption)
465 {
466 BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
467
468 TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption);
469
470 IStream_AddRef(pIStream);
471 This->stream = pIStream;
472
473 return S_OK;
474 }
475
476 static HRESULT WINAPI BmpEncoder_GetContainerFormat(IWICBitmapEncoder *iface,
477 GUID *pguidContainerFormat)
478 {
479 memcpy(pguidContainerFormat, &GUID_ContainerFormatBmp, sizeof(GUID));
480 return S_OK;
481 }
482
483 static HRESULT WINAPI BmpEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info)
484 {
485 IWICComponentInfo *comp_info;
486 HRESULT hr;
487
488 TRACE("%p,%p\n", iface, info);
489
490 if (!info) return E_INVALIDARG;
491
492 hr = CreateComponentInfo(&CLSID_WICBmpEncoder, &comp_info);
493 if (hr == S_OK)
494 {
495 hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info);
496 IWICComponentInfo_Release(comp_info);
497 }
498 return hr;
499 }
500
501 static HRESULT WINAPI BmpEncoder_SetColorContexts(IWICBitmapEncoder *iface,
502 UINT cCount, IWICColorContext **ppIColorContext)
503 {
504 FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
505 return E_NOTIMPL;
506 }
507
508 static HRESULT WINAPI BmpEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *palette)
509 {
510 BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
511
512 TRACE("(%p,%p)\n", iface, palette);
513 return This->stream ? WINCODEC_ERR_UNSUPPORTEDOPERATION : WINCODEC_ERR_NOTINITIALIZED;
514 }
515
516 static HRESULT WINAPI BmpEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
517 {
518 TRACE("(%p,%p)\n", iface, pIThumbnail);
519 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
520 }
521
522 static HRESULT WINAPI BmpEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview)
523 {
524 TRACE("(%p,%p)\n", iface, pIPreview);
525 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
526 }
527
528 static HRESULT WINAPI BmpEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
529 IWICBitmapFrameEncode **ppIFrameEncode, IPropertyBag2 **ppIEncoderOptions)
530 {
531 BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
532 BmpFrameEncode *encode;
533 HRESULT hr;
534
535 TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
536
537 if (This->frame) return WINCODEC_ERR_UNSUPPORTEDOPERATION;
538
539 if (!This->stream) return WINCODEC_ERR_NOTINITIALIZED;
540
541 hr = CreatePropertyBag2(NULL, 0, ppIEncoderOptions);
542 if (FAILED(hr)) return hr;
543
544 encode = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpFrameEncode));
545 if (!encode)
546 {
547 IPropertyBag2_Release(*ppIEncoderOptions);
548 *ppIEncoderOptions = NULL;
549 return E_OUTOFMEMORY;
550 }
551 encode->IWICBitmapFrameEncode_iface.lpVtbl = &BmpFrameEncode_Vtbl;
552 encode->ref = 2;
553 IStream_AddRef(This->stream);
554 encode->stream = This->stream;
555 encode->initialized = FALSE;
556 encode->width = 0;
557 encode->height = 0;
558 encode->bits = NULL;
559 encode->format = NULL;
560 encode->xres = 0.0;
561 encode->yres = 0.0;
562 encode->lineswritten = 0;
563 encode->colors = 0;
564 encode->committed = FALSE;
565
566 *ppIFrameEncode = &encode->IWICBitmapFrameEncode_iface;
567 This->frame = encode;
568
569 return S_OK;
570 }
571
572 static HRESULT WINAPI BmpEncoder_Commit(IWICBitmapEncoder *iface)
573 {
574 BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
575 TRACE("(%p)\n", iface);
576
577 if (!This->frame || !This->frame->committed) return WINCODEC_ERR_WRONGSTATE;
578
579 return S_OK;
580 }
581
582 static HRESULT WINAPI BmpEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface,
583 IWICMetadataQueryWriter **ppIMetadataQueryWriter)
584 {
585 FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter);
586 return E_NOTIMPL;
587 }
588
589 static const IWICBitmapEncoderVtbl BmpEncoder_Vtbl = {
590 BmpEncoder_QueryInterface,
591 BmpEncoder_AddRef,
592 BmpEncoder_Release,
593 BmpEncoder_Initialize,
594 BmpEncoder_GetContainerFormat,
595 BmpEncoder_GetEncoderInfo,
596 BmpEncoder_SetColorContexts,
597 BmpEncoder_SetPalette,
598 BmpEncoder_SetThumbnail,
599 BmpEncoder_SetPreview,
600 BmpEncoder_CreateNewFrame,
601 BmpEncoder_Commit,
602 BmpEncoder_GetMetadataQueryWriter
603 };
604
605 HRESULT BmpEncoder_CreateInstance(REFIID iid, void** ppv)
606 {
607 BmpEncoder *This;
608 HRESULT ret;
609
610 TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
611
612 *ppv = NULL;
613
614 This = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpEncoder));
615 if (!This) return E_OUTOFMEMORY;
616
617 This->IWICBitmapEncoder_iface.lpVtbl = &BmpEncoder_Vtbl;
618 This->ref = 1;
619 This->stream = NULL;
620 This->frame = NULL;
621
622 ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv);
623 IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
624
625 return ret;
626 }