2 * Copyright 2009 Vincent Povirk for CodeWeavers
3 * Copyright 2016 Dmitry Timoshkov
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.
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.
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
30 #include "wincodecs_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
36 struct bmp_pixelformat
{
37 const WICPixelFormatGUID
*guid
;
39 UINT colors
; /* palette size */
47 static const struct bmp_pixelformat formats
[] = {
48 {&GUID_WICPixelFormat24bppBGR
, 24, 0, BI_RGB
},
49 {&GUID_WICPixelFormatBlackWhite
, 1, 2, BI_RGB
},
50 {&GUID_WICPixelFormat1bppIndexed
, 1, 2, BI_RGB
},
51 {&GUID_WICPixelFormat2bppIndexed
, 2, 4, BI_RGB
},
52 {&GUID_WICPixelFormat4bppIndexed
, 4, 16, BI_RGB
},
53 {&GUID_WICPixelFormat8bppIndexed
, 8, 256, BI_RGB
},
54 {&GUID_WICPixelFormat16bppBGR555
, 16, 0, BI_RGB
},
55 {&GUID_WICPixelFormat16bppBGR565
, 16, 0, BI_BITFIELDS
, 0xf800, 0x7e0, 0x1f, 0},
56 {&GUID_WICPixelFormat32bppBGR
, 32, 0, BI_RGB
},
58 /* Windows doesn't seem to support this one. */
59 {&GUID_WICPixelFormat32bppBGRA
, 32, 0, BI_BITFIELDS
, 0xff0000, 0xff00, 0xff, 0xff000000},
64 typedef struct BmpFrameEncode
{
65 IWICBitmapFrameEncode IWICBitmapFrameEncode_iface
;
71 const struct bmp_pixelformat
*format
;
75 WICColor palette
[256];
80 static inline BmpFrameEncode
*impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode
*iface
)
82 return CONTAINING_RECORD(iface
, BmpFrameEncode
, IWICBitmapFrameEncode_iface
);
85 static HRESULT WINAPI
BmpFrameEncode_QueryInterface(IWICBitmapFrameEncode
*iface
, REFIID iid
,
88 BmpFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
89 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
91 if (!ppv
) return E_INVALIDARG
;
93 if (IsEqualIID(&IID_IUnknown
, iid
) ||
94 IsEqualIID(&IID_IWICBitmapFrameEncode
, iid
))
96 *ppv
= &This
->IWICBitmapFrameEncode_iface
;
101 return E_NOINTERFACE
;
104 IUnknown_AddRef((IUnknown
*)*ppv
);
108 static ULONG WINAPI
BmpFrameEncode_AddRef(IWICBitmapFrameEncode
*iface
)
110 BmpFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
111 ULONG ref
= InterlockedIncrement(&This
->ref
);
113 TRACE("(%p) refcount=%u\n", iface
, ref
);
118 static ULONG WINAPI
BmpFrameEncode_Release(IWICBitmapFrameEncode
*iface
)
120 BmpFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
121 ULONG ref
= InterlockedDecrement(&This
->ref
);
123 TRACE("(%p) refcount=%u\n", iface
, ref
);
127 if (This
->stream
) IStream_Release(This
->stream
);
128 HeapFree(GetProcessHeap(), 0, This
->bits
);
129 HeapFree(GetProcessHeap(), 0, This
);
135 static HRESULT WINAPI
BmpFrameEncode_Initialize(IWICBitmapFrameEncode
*iface
,
136 IPropertyBag2
*pIEncoderOptions
)
138 BmpFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
139 TRACE("(%p,%p)\n", iface
, pIEncoderOptions
);
141 if (This
->initialized
) return WINCODEC_ERR_WRONGSTATE
;
143 if (pIEncoderOptions
)
144 WARN("ignoring encoder options.\n");
146 This
->initialized
= TRUE
;
151 static HRESULT WINAPI
BmpFrameEncode_SetSize(IWICBitmapFrameEncode
*iface
,
152 UINT uiWidth
, UINT uiHeight
)
154 BmpFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
155 TRACE("(%p,%u,%u)\n", iface
, uiWidth
, uiHeight
);
157 if (!This
->initialized
|| This
->bits
) return WINCODEC_ERR_WRONGSTATE
;
159 This
->width
= uiWidth
;
160 This
->height
= uiHeight
;
165 static HRESULT WINAPI
BmpFrameEncode_SetResolution(IWICBitmapFrameEncode
*iface
,
166 double dpiX
, double dpiY
)
168 BmpFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
169 TRACE("(%p,%0.2f,%0.2f)\n", iface
, dpiX
, dpiY
);
171 if (!This
->initialized
|| This
->bits
) return WINCODEC_ERR_WRONGSTATE
;
179 static HRESULT WINAPI
BmpFrameEncode_SetPixelFormat(IWICBitmapFrameEncode
*iface
,
180 WICPixelFormatGUID
*pPixelFormat
)
182 BmpFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
184 TRACE("(%p,%s)\n", iface
, debugstr_guid(pPixelFormat
));
186 if (!This
->initialized
|| This
->bits
) return WINCODEC_ERR_WRONGSTATE
;
188 if (IsEqualGUID(pPixelFormat
, &GUID_WICPixelFormatBlackWhite
))
189 *pPixelFormat
= GUID_WICPixelFormat1bppIndexed
;
190 else if (IsEqualGUID(pPixelFormat
, &GUID_WICPixelFormat2bppIndexed
))
191 *pPixelFormat
= GUID_WICPixelFormat4bppIndexed
;
193 for (i
=0; formats
[i
].guid
; i
++)
195 if (IsEqualGUID(formats
[i
].guid
, pPixelFormat
))
199 if (!formats
[i
].guid
) i
= 0;
201 This
->format
= &formats
[i
];
202 memcpy(pPixelFormat
, This
->format
->guid
, sizeof(GUID
));
207 static HRESULT WINAPI
BmpFrameEncode_SetColorContexts(IWICBitmapFrameEncode
*iface
,
208 UINT cCount
, IWICColorContext
**ppIColorContext
)
210 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
214 static HRESULT WINAPI
BmpFrameEncode_SetPalette(IWICBitmapFrameEncode
*iface
,
215 IWICPalette
*palette
)
217 BmpFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
220 TRACE("(%p,%p)\n", iface
, palette
);
222 if (!palette
) return E_INVALIDARG
;
224 if (!This
->initialized
)
225 return WINCODEC_ERR_NOTINITIALIZED
;
227 hr
= IWICPalette_GetColors(palette
, 256, This
->palette
, &This
->colors
);
231 for (i
= 0; i
< This
->colors
; i
++)
232 This
->palette
[i
] |= 0xff000000; /* BMP palette has no alpha */
237 static HRESULT WINAPI
BmpFrameEncode_SetThumbnail(IWICBitmapFrameEncode
*iface
,
238 IWICBitmapSource
*pIThumbnail
)
240 FIXME("(%p,%p): stub\n", iface
, pIThumbnail
);
241 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
244 static HRESULT
BmpFrameEncode_AllocateBits(BmpFrameEncode
*This
)
248 if (!This
->initialized
|| !This
->width
|| !This
->height
|| !This
->format
)
249 return WINCODEC_ERR_WRONGSTATE
;
251 This
->stride
= (((This
->width
* This
->format
->bpp
)+31)/32)*4;
252 This
->bits
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->stride
* This
->height
);
253 if (!This
->bits
) return E_OUTOFMEMORY
;
259 static HRESULT WINAPI
BmpFrameEncode_WritePixels(IWICBitmapFrameEncode
*iface
,
260 UINT lineCount
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbPixels
)
262 BmpFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
263 UINT dstbuffersize
, bytesperrow
, row
;
267 TRACE("(%p,%u,%u,%u,%p)\n", iface
, lineCount
, cbStride
, cbBufferSize
, pbPixels
);
269 if (!This
->initialized
|| !This
->width
|| !This
->height
|| !This
->format
)
270 return WINCODEC_ERR_WRONGSTATE
;
272 hr
= BmpFrameEncode_AllocateBits(This
);
273 if (FAILED(hr
)) return hr
;
275 bytesperrow
= ((This
->format
->bpp
* This
->width
) + 7) / 8;
277 if (This
->stride
< bytesperrow
)
280 dstbuffersize
= This
->stride
* (This
->height
- This
->lineswritten
);
281 if ((This
->stride
* (lineCount
- 1)) + bytesperrow
> dstbuffersize
)
285 dst
= This
->bits
+ This
->stride
* (This
->height
- This
->lineswritten
- 1);
286 for (row
= 0; row
< lineCount
; row
++)
288 memcpy(dst
, src
, bytesperrow
);
293 This
->lineswritten
+= lineCount
;
298 static HRESULT WINAPI
BmpFrameEncode_WriteSource(IWICBitmapFrameEncode
*iface
,
299 IWICBitmapSource
*pIBitmapSource
, WICRect
*prc
)
301 BmpFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
303 TRACE("(%p,%p,%s)\n", iface
, pIBitmapSource
, debug_wic_rect(prc
));
305 if (!This
->initialized
)
306 return WINCODEC_ERR_WRONGSTATE
;
308 hr
= configure_write_source(iface
, pIBitmapSource
, prc
,
309 This
->format
? This
->format
->guid
: NULL
, This
->width
, This
->height
,
310 This
->xres
, This
->yres
);
314 hr
= write_source(iface
, pIBitmapSource
, prc
,
315 This
->format
->guid
, This
->format
->bpp
, !This
->colors
&& This
->format
->colors
,
316 This
->width
, This
->height
);
322 static HRESULT WINAPI
BmpFrameEncode_Commit(IWICBitmapFrameEncode
*iface
)
324 BmpFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
325 BITMAPFILEHEADER bfh
;
332 TRACE("(%p)\n", iface
);
334 if (!This
->bits
|| This
->committed
|| This
->height
!= This
->lineswritten
)
335 return WINCODEC_ERR_WRONGSTATE
;
337 bfh
.bfType
= 0x4d42; /* "BM" */
341 bih
.bV5Size
= info_size
= sizeof(BITMAPINFOHEADER
);
342 bih
.bV5Width
= This
->width
;
343 bih
.bV5Height
= This
->height
;
345 bih
.bV5BitCount
= This
->format
->bpp
;
346 bih
.bV5Compression
= This
->format
->compression
;
347 bih
.bV5SizeImage
= This
->stride
*This
->height
;
348 bih
.bV5XPelsPerMeter
= (This
->xres
+0.0127) / 0.0254;
349 bih
.bV5YPelsPerMeter
= (This
->yres
+0.0127) / 0.0254;
350 bih
.bV5ClrUsed
= (This
->format
->bpp
<= 8) ? This
->colors
: 0;
351 bih
.bV5ClrImportant
= bih
.bV5ClrUsed
;
353 if (This
->format
->compression
== BI_BITFIELDS
)
355 if (This
->format
->alphamask
)
356 bih
.bV5Size
= info_size
= sizeof(BITMAPV4HEADER
);
358 info_size
= sizeof(BITMAPINFOHEADER
)+12;
359 bih
.bV5RedMask
= This
->format
->redmask
;
360 bih
.bV5GreenMask
= This
->format
->greenmask
;
361 bih
.bV5BlueMask
= This
->format
->bluemask
;
362 bih
.bV5AlphaMask
= This
->format
->alphamask
;
363 bih
.bV5CSType
= LCS_DEVICE_RGB
;
366 bfh
.bfSize
= sizeof(BITMAPFILEHEADER
) + info_size
+ bih
.bV5SizeImage
;
367 bfh
.bfOffBits
= sizeof(BITMAPFILEHEADER
) + info_size
;
368 bfh
.bfOffBits
+= bih
.bV5ClrUsed
* sizeof(WICColor
);
371 hr
= IStream_Seek(This
->stream
, pos
, STREAM_SEEK_SET
, NULL
);
372 if (FAILED(hr
)) return hr
;
374 hr
= IStream_Write(This
->stream
, &bfh
, sizeof(BITMAPFILEHEADER
), &byteswritten
);
375 if (FAILED(hr
)) return hr
;
376 if (byteswritten
!= sizeof(BITMAPFILEHEADER
)) return E_FAIL
;
378 hr
= IStream_Write(This
->stream
, &bih
, info_size
, &byteswritten
);
379 if (FAILED(hr
)) return hr
;
380 if (byteswritten
!= info_size
) return E_FAIL
;
382 /* write the palette */
383 if (This
->format
->colors
)
385 hr
= IStream_Write(This
->stream
, This
->palette
, This
->colors
* sizeof(WICColor
), &byteswritten
);
386 if (FAILED(hr
)) return hr
;
387 if (byteswritten
!= This
->colors
* sizeof(WICColor
)) return E_FAIL
;
390 hr
= IStream_Write(This
->stream
, This
->bits
, bih
.bV5SizeImage
, &byteswritten
);
391 if (FAILED(hr
)) return hr
;
392 if (byteswritten
!= bih
.bV5SizeImage
) return E_FAIL
;
394 This
->committed
= TRUE
;
399 static HRESULT WINAPI
BmpFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode
*iface
,
400 IWICMetadataQueryWriter
**query_writer
)
402 BmpFrameEncode
*encoder
= impl_from_IWICBitmapFrameEncode(iface
);
404 TRACE("iface %p, query_writer %p.\n", iface
, query_writer
);
406 if (!encoder
->initialized
)
407 return WINCODEC_ERR_NOTINITIALIZED
;
409 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
412 static const IWICBitmapFrameEncodeVtbl BmpFrameEncode_Vtbl
= {
413 BmpFrameEncode_QueryInterface
,
414 BmpFrameEncode_AddRef
,
415 BmpFrameEncode_Release
,
416 BmpFrameEncode_Initialize
,
417 BmpFrameEncode_SetSize
,
418 BmpFrameEncode_SetResolution
,
419 BmpFrameEncode_SetPixelFormat
,
420 BmpFrameEncode_SetColorContexts
,
421 BmpFrameEncode_SetPalette
,
422 BmpFrameEncode_SetThumbnail
,
423 BmpFrameEncode_WritePixels
,
424 BmpFrameEncode_WriteSource
,
425 BmpFrameEncode_Commit
,
426 BmpFrameEncode_GetMetadataQueryWriter
429 typedef struct BmpEncoder
{
430 IWICBitmapEncoder IWICBitmapEncoder_iface
;
433 BmpFrameEncode
*frame
;
436 static inline BmpEncoder
*impl_from_IWICBitmapEncoder(IWICBitmapEncoder
*iface
)
438 return CONTAINING_RECORD(iface
, BmpEncoder
, IWICBitmapEncoder_iface
);
441 static HRESULT WINAPI
BmpEncoder_QueryInterface(IWICBitmapEncoder
*iface
, REFIID iid
,
444 BmpEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
445 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
447 if (!ppv
) return E_INVALIDARG
;
449 if (IsEqualIID(&IID_IUnknown
, iid
) ||
450 IsEqualIID(&IID_IWICBitmapEncoder
, iid
))
452 *ppv
= &This
->IWICBitmapEncoder_iface
;
457 return E_NOINTERFACE
;
460 IUnknown_AddRef((IUnknown
*)*ppv
);
464 static ULONG WINAPI
BmpEncoder_AddRef(IWICBitmapEncoder
*iface
)
466 BmpEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
467 ULONG ref
= InterlockedIncrement(&This
->ref
);
469 TRACE("(%p) refcount=%u\n", iface
, ref
);
474 static ULONG WINAPI
BmpEncoder_Release(IWICBitmapEncoder
*iface
)
476 BmpEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
477 ULONG ref
= InterlockedDecrement(&This
->ref
);
479 TRACE("(%p) refcount=%u\n", iface
, ref
);
483 if (This
->stream
) IStream_Release(This
->stream
);
484 if (This
->frame
) IWICBitmapFrameEncode_Release(&This
->frame
->IWICBitmapFrameEncode_iface
);
485 HeapFree(GetProcessHeap(), 0, This
);
491 static HRESULT WINAPI
BmpEncoder_Initialize(IWICBitmapEncoder
*iface
,
492 IStream
*pIStream
, WICBitmapEncoderCacheOption cacheOption
)
494 BmpEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
496 TRACE("(%p,%p,%u)\n", iface
, pIStream
, cacheOption
);
498 IStream_AddRef(pIStream
);
499 This
->stream
= pIStream
;
504 static HRESULT WINAPI
BmpEncoder_GetContainerFormat(IWICBitmapEncoder
*iface
,
505 GUID
*pguidContainerFormat
)
507 TRACE("(%p,%p)\n", iface
, pguidContainerFormat
);
509 if (!pguidContainerFormat
)
512 memcpy(pguidContainerFormat
, &GUID_ContainerFormatBmp
, sizeof(GUID
));
516 static HRESULT WINAPI
BmpEncoder_GetEncoderInfo(IWICBitmapEncoder
*iface
, IWICBitmapEncoderInfo
**info
)
518 IWICComponentInfo
*comp_info
;
521 TRACE("%p,%p\n", iface
, info
);
523 if (!info
) return E_INVALIDARG
;
525 hr
= CreateComponentInfo(&CLSID_WICBmpEncoder
, &comp_info
);
528 hr
= IWICComponentInfo_QueryInterface(comp_info
, &IID_IWICBitmapEncoderInfo
, (void **)info
);
529 IWICComponentInfo_Release(comp_info
);
534 static HRESULT WINAPI
BmpEncoder_SetColorContexts(IWICBitmapEncoder
*iface
,
535 UINT cCount
, IWICColorContext
**ppIColorContext
)
537 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
541 static HRESULT WINAPI
BmpEncoder_SetPalette(IWICBitmapEncoder
*iface
, IWICPalette
*palette
)
543 BmpEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
545 TRACE("(%p,%p)\n", iface
, palette
);
546 return This
->stream
? WINCODEC_ERR_UNSUPPORTEDOPERATION
: WINCODEC_ERR_NOTINITIALIZED
;
549 static HRESULT WINAPI
BmpEncoder_SetThumbnail(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIThumbnail
)
551 TRACE("(%p,%p)\n", iface
, pIThumbnail
);
552 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
555 static HRESULT WINAPI
BmpEncoder_SetPreview(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIPreview
)
557 TRACE("(%p,%p)\n", iface
, pIPreview
);
558 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
561 static HRESULT WINAPI
BmpEncoder_CreateNewFrame(IWICBitmapEncoder
*iface
,
562 IWICBitmapFrameEncode
**ppIFrameEncode
, IPropertyBag2
**ppIEncoderOptions
)
564 BmpEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
565 BmpFrameEncode
*encode
;
567 static const PROPBAG2 opts
[1] =
569 { PROPBAG2_TYPE_DATA
, VT_BOOL
, 0, 0, (LPOLESTR
)L
"EnableV5Header32bppBGRA" },
572 TRACE("(%p,%p,%p)\n", iface
, ppIFrameEncode
, ppIEncoderOptions
);
574 if (This
->frame
) return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
576 if (!This
->stream
) return WINCODEC_ERR_NOTINITIALIZED
;
578 if (ppIEncoderOptions
)
580 hr
= CreatePropertyBag2(opts
, ARRAY_SIZE(opts
), ppIEncoderOptions
);
581 if (FAILED(hr
)) return hr
;
584 encode
= HeapAlloc(GetProcessHeap(), 0, sizeof(BmpFrameEncode
));
587 IPropertyBag2_Release(*ppIEncoderOptions
);
588 *ppIEncoderOptions
= NULL
;
589 return E_OUTOFMEMORY
;
591 encode
->IWICBitmapFrameEncode_iface
.lpVtbl
= &BmpFrameEncode_Vtbl
;
593 IStream_AddRef(This
->stream
);
594 encode
->stream
= This
->stream
;
595 encode
->initialized
= FALSE
;
599 encode
->format
= NULL
;
602 encode
->lineswritten
= 0;
604 encode
->committed
= FALSE
;
606 *ppIFrameEncode
= &encode
->IWICBitmapFrameEncode_iface
;
607 This
->frame
= encode
;
612 static HRESULT WINAPI
BmpEncoder_Commit(IWICBitmapEncoder
*iface
)
614 BmpEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
615 TRACE("(%p)\n", iface
);
617 if (!This
->frame
|| !This
->frame
->committed
) return WINCODEC_ERR_WRONGSTATE
;
622 static HRESULT WINAPI
BmpEncoder_GetMetadataQueryWriter(IWICBitmapEncoder
*iface
,
623 IWICMetadataQueryWriter
**ppIMetadataQueryWriter
)
625 FIXME("(%p,%p): stub\n", iface
, ppIMetadataQueryWriter
);
629 static const IWICBitmapEncoderVtbl BmpEncoder_Vtbl
= {
630 BmpEncoder_QueryInterface
,
633 BmpEncoder_Initialize
,
634 BmpEncoder_GetContainerFormat
,
635 BmpEncoder_GetEncoderInfo
,
636 BmpEncoder_SetColorContexts
,
637 BmpEncoder_SetPalette
,
638 BmpEncoder_SetThumbnail
,
639 BmpEncoder_SetPreview
,
640 BmpEncoder_CreateNewFrame
,
642 BmpEncoder_GetMetadataQueryWriter
645 HRESULT
BmpEncoder_CreateInstance(REFIID iid
, void** ppv
)
650 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
654 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(BmpEncoder
));
655 if (!This
) return E_OUTOFMEMORY
;
657 This
->IWICBitmapEncoder_iface
.lpVtbl
= &BmpEncoder_Vtbl
;
662 ret
= IWICBitmapEncoder_QueryInterface(&This
->IWICBitmapEncoder_iface
, iid
, ppv
);
663 IWICBitmapEncoder_Release(&This
->IWICBitmapEncoder_iface
);