2 * Copyright (C) 2009 Tony Wasserka
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/debug.h"
23 #include "d3dx9_36_private.h"
29 #define DDSD_DEPTH 0x00800000
31 #define DDSD_ALL 0x00fff9ee
34 WINE_DEFAULT_DEBUG_CHANNEL(d3dx
);
36 const GUID GUID_d3dx_container_format_dds
= { 0x2559CD66, 0xA5D4, 0x44AB, { 0xBD, 0xF3, 0x72, 0x69, 0xBA, 0x9B, 0xC9, 0xE0 } };
37 const GUID GUID_d3dx_pixel_format32bppRGB
= { 0x55F197D5, 0xE1AB, 0x48B9, { 0x99, 0x51, 0x01, 0x13, 0xB4, 0x6B, 0x8A, 0x85 } };
38 const GUID GUID_d3dx_pixel_format32bppRGBA
= { 0xE170EC37, 0x48D4, 0x443B, { 0x8E, 0xA7, 0xA4, 0x63, 0x28, 0x43, 0x74, 0x57 } };
40 typedef struct DDSFrameDecode
{
41 const IWICBitmapFrameDecodeVtbl
*lpVtbl
;
46 const WICPixelFormatGUID
*pPixelFormat
;
55 static HRESULT WINAPI
DDSFrameDecode_QueryInterface(IWICBitmapFrameDecode
*iface
, REFIID iid
, void **ppv
)
57 DDSFrameDecode
*This
= (DDSFrameDecode
*)iface
;
58 TRACE("(%p)\n", This
);
60 if (!ppv
) return E_INVALIDARG
;
62 if (IsEqualIID(&IID_IUnknown
, iid
) ||
63 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
64 IsEqualIID(&IID_IWICBitmapFrameDecode
, iid
)) {
66 IUnknown_AddRef((IUnknown
*)*ppv
);
74 static ULONG WINAPI
DDSFrameDecode_AddRef(IWICBitmapFrameDecode
*iface
)
76 DDSFrameDecode
*This
= (DDSFrameDecode
*)iface
;
77 ULONG ref
= InterlockedIncrement(&This
->ref
);
79 TRACE("(%p) AddRef to %u\n", iface
, ref
);
84 static ULONG WINAPI
DDSFrameDecode_Release(IWICBitmapFrameDecode
*iface
)
86 DDSFrameDecode
*This
= (DDSFrameDecode
*)iface
;
87 ULONG ref
= InterlockedDecrement(&This
->ref
);
89 TRACE("(%p) Release to %u\n", iface
, ref
);
92 if(This
->pImageData
) HeapFree(GetProcessHeap(), 0, This
->pImageData
);
93 if(This
->pStream
) IStream_Release(This
->pStream
);
94 HeapFree(GetProcessHeap(), 0, This
);
99 static HRESULT WINAPI
DDSFrameDecode_CopyPalette(IWICBitmapFrameDecode
*iface
, IWICPalette
*pIPalette
)
101 DDSFrameDecode
*This
= (DDSFrameDecode
*)iface
;
102 FIXME("(%p): stub\n", This
);
106 static HRESULT WINAPI
DDSFrameDecode_CopyPixels(IWICBitmapFrameDecode
*iface
, const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
108 DDSFrameDecode
*This
= (DDSFrameDecode
*)iface
;
116 TRACE("(%p)\n", This
);
121 rect
.Width
= This
->Width
;
122 rect
.Height
= This
->Height
;
125 if(cbStride
< (unsigned)This
->Desc
.lPitch
) return E_INVALIDARG
;
126 if(cbStride
* rect
.Height
> cbBufferSize
) return E_INVALIDARG
;
128 if(rect
.X
< 0 || rect
.Y
< 0 || (unsigned)(rect
.X
+ rect
.Width
) > This
->Width
|| (unsigned)(rect
.Y
+ rect
.Height
) > This
->Height
)
131 Pos
.QuadPart
= This
->StreamOffset
;
132 hr
= IStream_Seek(This
->pStream
, Pos
, STREAM_SEEK_SET
, NULL
);
133 if(FAILED(hr
)) return E_INVALIDARG
;
135 if( !This
->pImageData
) This
->pImageData
= HeapAlloc(GetProcessHeap(), 0, This
->Height
* This
->Desc
.lPitch
);
137 hr
= IStream_Read(This
->pStream
, This
->pImageData
, This
->Height
* This
->Desc
.lPitch
, NULL
);
138 if(FAILED(hr
)) return E_INVALIDARG
;
140 src
= This
->pImageData
+ rect
.X
* This
->Desc
.ddpfPixelFormat
.dwRGBBitCount
/ 8;
142 bytesperrow
= (rect
.Width
* This
->Desc
.ddpfPixelFormat
.dwRGBBitCount
) / 8;
143 for (row
= 0; row
< (unsigned)rect
.Height
; row
++) {
144 memcpy(dst
, src
, bytesperrow
);
145 src
+= This
->Desc
.lPitch
;
152 static HRESULT WINAPI
DDSFrameDecode_GetPixelFormat(IWICBitmapFrameDecode
*iface
, WICPixelFormatGUID
*pPixelFormat
)
154 DDSFrameDecode
*This
= (DDSFrameDecode
*)iface
;
155 TRACE("(%p)\n", This
);
157 if( !pPixelFormat
) return E_INVALIDARG
;
158 *pPixelFormat
= *This
->pPixelFormat
;
163 static HRESULT WINAPI
DDSFrameDecode_GetResolution(IWICBitmapFrameDecode
*iface
, double *pDpiX
, double *pDpiY
)
165 DDSFrameDecode
*This
= (DDSFrameDecode
*)iface
;
166 FIXME("(%p): stub\n", This
);
170 static HRESULT WINAPI
DDSFrameDecode_GetSize(IWICBitmapFrameDecode
*iface
, UINT
*puiWidth
, UINT
*puiHeight
)
172 DDSFrameDecode
*This
= (DDSFrameDecode
*)iface
;
173 TRACE("(%p)\n", This
);
175 if( !puiWidth
|| !puiHeight
) return E_INVALIDARG
;
177 *puiWidth
= This
->Width
;
178 *puiHeight
= This
->Height
;
183 static HRESULT WINAPI
DDSFrameDecode_GetColorContexts(IWICBitmapFrameDecode
*iface
, UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
185 DDSFrameDecode
*This
= (DDSFrameDecode
*)iface
;
186 FIXME("(%p): stub\n", This
);
190 static HRESULT WINAPI
DDSFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode
*iface
, IWICMetadataQueryReader
**ppIMetadataQueryReader
)
192 DDSFrameDecode
*This
= (DDSFrameDecode
*)iface
;
193 FIXME("(%p): stub\n", This
);
197 static HRESULT WINAPI
DDSFrameDecode_GetThumbnail(IWICBitmapFrameDecode
*iface
, IWICBitmapSource
**ppIThumbnail
)
199 DDSFrameDecode
*This
= (DDSFrameDecode
*)iface
;
200 FIXME("(%p): stub\n", This
);
204 static const IWICBitmapFrameDecodeVtbl DDSFrameDecodeVtbl
= {
205 DDSFrameDecode_QueryInterface
,
206 DDSFrameDecode_AddRef
,
207 DDSFrameDecode_Release
,
208 DDSFrameDecode_GetSize
,
209 DDSFrameDecode_GetPixelFormat
,
210 DDSFrameDecode_GetResolution
,
211 DDSFrameDecode_CopyPalette
,
212 DDSFrameDecode_CopyPixels
,
213 DDSFrameDecode_GetMetadataQueryReader
,
214 DDSFrameDecode_GetColorContexts
,
215 DDSFrameDecode_GetThumbnail
219 typedef struct DDSDecoder
{
220 const IWICBitmapDecoderVtbl
*lpVtbl
;
225 const WICPixelFormatGUID
*pPixelFormat
;
228 DDSFrameDecode
**ppFrameDecoders
;
232 static HRESULT WINAPI
DDSDecoder_QueryInterface(IWICBitmapDecoder
*iface
, REFIID iid
, void **ppv
)
234 DDSDecoder
*This
= (DDSDecoder
*)iface
;
235 TRACE("(%p)\n", This
);
237 if (!ppv
) return E_INVALIDARG
;
239 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IWICBitmapDecoder
, iid
)) {
241 IUnknown_AddRef((IUnknown
*)*ppv
);
245 return E_NOINTERFACE
;
249 static ULONG WINAPI
DDSDecoder_AddRef(IWICBitmapDecoder
*iface
)
251 DDSDecoder
*This
= (DDSDecoder
*)iface
;
252 ULONG ref
= InterlockedIncrement(&This
->ref
);
254 TRACE("(%p) AddRef to %u\n", iface
, ref
);
259 static ULONG WINAPI
DDSDecoder_Release(IWICBitmapDecoder
*iface
)
261 DDSDecoder
*This
= (DDSDecoder
*)iface
;
262 ULONG ref
= InterlockedDecrement(&This
->ref
);
264 TRACE("(%p) Release to %u\n", iface
, ref
);
267 if(This
->ppFrameDecoders
) {
269 for(i
= 0;i
< This
->NumFrames
;i
++) if(This
->ppFrameDecoders
[i
]) IUnknown_Release((IUnknown
*)(This
->ppFrameDecoders
[i
]));
270 HeapFree(GetProcessHeap(), 0, This
->ppFrameDecoders
);
272 if(This
->pStream
) IStream_Release(This
->pStream
);
273 HeapFree(GetProcessHeap(), 0, This
);
278 struct dds_pixel_format
{
279 WORD bitcount
; /* 0 for end of list */
284 const WICPixelFormatGUID
*pixelformat
;
287 static const struct dds_pixel_format dds_pixel_formats
[] = {
288 { 16, 0x7c00, 0x3e0, 0x1f, 0, &GUID_WICPixelFormat16bppBGR555
},
289 { 16, 0xf800, 0x7e0, 0x1f, 0, &GUID_WICPixelFormat16bppBGR565
},
290 { 24, 0xff0000, 0xff00, 0xff, 0, &GUID_WICPixelFormat24bppBGR
},
291 { 32, 0xff0000, 0xff00, 0xff, 0, &GUID_WICPixelFormat32bppBGR
},
292 { 32, 0xff0000, 0xff00, 0xff, 0xff000000, &GUID_WICPixelFormat32bppBGRA
},
293 { 32, 0xff, 0xff00, 0xff0000, 0, &GUID_d3dx_pixel_format32bppRGB
},
294 { 32, 0xff, 0xff00, 0xff0000, 0xff000000, &GUID_d3dx_pixel_format32bppRGBA
},
295 { 0, 0, 0, 0, 0, NULL
}
299 static HRESULT
DDSDecoder_ReadHeaders(DDSDecoder
*This
, IStream
*pStream
)
305 if(This
->bInitialized
) return WINCODEC_ERR_WRONGSTATE
;
307 hr
= IStream_Read(pStream
, &dwMagic
, sizeof(DWORD
), &BytesRead
);
308 if(FAILED(hr
)) return hr
;
309 if(BytesRead
!= sizeof(DWORD
)) return E_INVALIDARG
;
310 if(dwMagic
!= 0x20534444) {
311 TRACE("File is not a DDS file\n");
315 hr
= IStream_Read(pStream
, &This
->Desc
, sizeof(DDSURFACEDESC2
), &BytesRead
);
316 if(FAILED(hr
)) return hr
;
317 if(BytesRead
!= sizeof(DDSURFACEDESC2
)) return E_INVALIDARG
;
319 if(This
->Desc
.dwSize
!= 124) {
320 WARN("Invalid DDSURFACEDESC2 structure size %d\n", This
->Desc
.dwSize
);
323 if( !(This
->Desc
.dwFlags
& (DDSD_CAPS
| DDSD_HEIGHT
| DDSD_WIDTH
| DDSD_PIXELFORMAT
)) ) {
324 WARN("Invalid DDS flags %#x\n", This
->Desc
.dwFlags
);
327 if(This
->Desc
.dwHeight
== 0 || This
->Desc
.dwWidth
== 0) return E_INVALIDARG
;
329 if( !(This
->Desc
.ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
) ) {
330 WARN("DDS caps %#x don't contain DDSCAPS_TEXTURE\n", This
->Desc
.ddsCaps
.dwCaps
);
334 if(This
->Desc
.dwFlags
& DDSD_PITCH
) {
336 } else if(This
->Desc
.dwFlags
& DDSD_LINEARSIZE
) {
339 This
->Desc
.lPitch
= This
->Desc
.dwWidth
* This
->Desc
.ddpfPixelFormat
.dwRGBBitCount
/ 8;
341 This
->Desc
.lPitch
= This
->Desc
.dwWidth
* This
->Desc
.ddpfPixelFormat
.dwRGBBitCount
/ 8;
344 if(This
->Desc
.dwFlags
& DDSD_MIPMAPCOUNT
) This
->NumFrames
= This
->Desc
.dwMipMapCount
+ 1; /* TODO: Verify the + 1 */
345 if(This
->Desc
.dwFlags
& DDSD_DEPTH
) {
346 FIXME("Depth images aren't supported, yet\n");
350 if(This
->Desc
.ddpfPixelFormat
.dwFlags
== DDPF_RGB
) {
352 for(i
= 0;dds_pixel_formats
[i
].bitcount
!= 0;i
++) {
353 if(dds_pixel_formats
[i
].bitcount
== This
->Desc
.ddpfPixelFormat
.dwRGBBitCount
&&
354 dds_pixel_formats
[i
].redmask
== This
->Desc
.ddpfPixelFormat
.dwRBitMask
&&
355 dds_pixel_formats
[i
].greenmask
== This
->Desc
.ddpfPixelFormat
.dwGBitMask
&&
356 dds_pixel_formats
[i
].bluemask
== This
->Desc
.ddpfPixelFormat
.dwBBitMask
) {
357 This
->pPixelFormat
= dds_pixel_formats
[i
].pixelformat
;
361 if(dds_pixel_formats
[i
].bitcount
== 0) {
362 WARN("Unknown RGB pixel format %#x, %#x, %#x\n", This
->Desc
.ddpfPixelFormat
.dwRBitMask
,
363 This
->Desc
.ddpfPixelFormat
.dwGBitMask
,
364 This
->Desc
.ddpfPixelFormat
.dwBBitMask
);
367 } else if(This
->Desc
.ddpfPixelFormat
.dwFlags
== (DDPF_RGB
| DDPF_ALPHAPIXELS
)) {
369 for(i
= 0;dds_pixel_formats
[i
].bitcount
!= 0;i
++) {
370 if(dds_pixel_formats
[i
].bitcount
== This
->Desc
.ddpfPixelFormat
.dwRGBBitCount
&&
371 dds_pixel_formats
[i
].redmask
== This
->Desc
.ddpfPixelFormat
.dwRBitMask
&&
372 dds_pixel_formats
[i
].greenmask
== This
->Desc
.ddpfPixelFormat
.dwGBitMask
&&
373 dds_pixel_formats
[i
].bluemask
== This
->Desc
.ddpfPixelFormat
.dwBBitMask
&&
374 dds_pixel_formats
[i
].alphamask
== This
->Desc
.ddpfPixelFormat
.dwRGBAlphaBitMask
) {
375 This
->pPixelFormat
= dds_pixel_formats
[i
].pixelformat
;
379 if(dds_pixel_formats
[i
].bitcount
== 0) {
380 WARN("Unknown ARGB pixel format %#x, %#x, %#x, %#x\n", This
->Desc
.ddpfPixelFormat
.dwRGBAlphaBitMask
,
381 This
->Desc
.ddpfPixelFormat
.dwRBitMask
,
382 This
->Desc
.ddpfPixelFormat
.dwGBitMask
,
383 This
->Desc
.ddpfPixelFormat
.dwBBitMask
);
386 } else if(This
->Desc
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
) {
387 FIXME("FourCC images not supported, yet!, %#x\n", This
->Desc
.ddpfPixelFormat
.dwFlags
);
389 } else if(This
->Desc
.ddpfPixelFormat
.dwFlags
& DDPF_LUMINANCE
) {
390 FIXME("Luminance images not supported, yet!, %#x\n", This
->Desc
.ddpfPixelFormat
.dwFlags
);
393 WARN("Unknown flags %#x\n", This
->Desc
.ddpfPixelFormat
.dwFlags
);
397 This
->bInitialized
= TRUE
;
401 static HRESULT WINAPI
DDSDecoder_QueryCapability(IWICBitmapDecoder
*iface
, IStream
*pIStream
, DWORD
*pdwCapability
)
403 DDSDecoder
*This
= (DDSDecoder
*)iface
;
404 ULARGE_INTEGER StreamPosition
;
405 LARGE_INTEGER LargeInt
;
407 TRACE("(%p)\n", This
);
409 if( !pdwCapability
) return E_INVALIDARG
;
411 /* save current stream position */
412 LargeInt
.QuadPart
= 0;
413 IStream_Seek(pIStream
, LargeInt
, STREAM_SEEK_CUR
, &StreamPosition
);
415 hr
= DDSDecoder_ReadHeaders(This
, pIStream
);
417 /* restore stream position */
418 LargeInt
.QuadPart
= StreamPosition
.QuadPart
;
419 IStream_Seek(pIStream
, LargeInt
, STREAM_SEEK_SET
, &StreamPosition
);
421 if(FAILED(hr
)) return hr
;
422 *pdwCapability
= WICBitmapDecoderCapabilityCanDecodeAllImages
;
426 static HRESULT WINAPI
DDSDecoder_Initialize(IWICBitmapDecoder
*iface
, IStream
*pIStream
, WICDecodeOptions cacheOptions
)
428 DDSDecoder
*This
= (DDSDecoder
*)iface
;
429 LARGE_INTEGER LargeInt
;
432 TRACE("(%p)\n", This
);
434 LargeInt
.QuadPart
= 0;
435 IStream_Seek(pIStream
, LargeInt
, STREAM_SEEK_SET
, NULL
);
437 hr
= DDSDecoder_ReadHeaders(This
, pIStream
);
438 if(FAILED(hr
)) return hr
;
440 This
->ppFrameDecoders
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->NumFrames
* sizeof(DDSFrameDecode
*));
441 if( !This
->ppFrameDecoders
) return E_OUTOFMEMORY
;
443 This
->pStream
= pIStream
;
444 IStream_AddRef(pIStream
);
446 for(i
= 0;i
< This
->NumFrames
;i
++) {
447 This
->ppFrameDecoders
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DDSFrameDecode
));
449 This
->ppFrameDecoders
[i
]->lpVtbl
= &DDSFrameDecodeVtbl
;
450 This
->ppFrameDecoders
[i
]->ref
= 1;
451 This
->ppFrameDecoders
[i
]->Desc
= This
->Desc
;
452 This
->ppFrameDecoders
[i
]->pPixelFormat
= This
->pPixelFormat
;
453 This
->ppFrameDecoders
[i
]->pImageData
= NULL
;
454 This
->ppFrameDecoders
[i
]->pStream
= This
->pStream
;
455 IStream_AddRef(This
->pStream
);
456 This
->ppFrameDecoders
[i
]->bInitialized
= TRUE
;
458 /* TODO: Use substreams instead of offsets */
460 if(This
->Desc
.dwFlags
& DDSD_DEPTH
) {
461 FIXME("TODO: Support depth textures\n");
463 if(This
->Desc
.dwFlags
& DDSD_MIPMAPCOUNT
) {
464 This
->ppFrameDecoders
[i
]->Width
= This
->ppFrameDecoders
[i
-1]->Width
/ 2;
465 This
->ppFrameDecoders
[i
]->Height
= This
->ppFrameDecoders
[i
-1]->Height
/ 2;
466 This
->ppFrameDecoders
[i
]->StreamOffset
= This
->ppFrameDecoders
[i
-1]->StreamOffset
+ This
->ppFrameDecoders
[i
]->Width
* This
->ppFrameDecoders
[i
]->Height
* This
->Desc
.ddpfPixelFormat
.dwRGBBitCount
/ 8;
469 This
->ppFrameDecoders
[i
]->Width
= This
->Desc
.dwWidth
;
470 This
->ppFrameDecoders
[i
]->Height
= This
->Desc
.dwHeight
;
471 This
->ppFrameDecoders
[i
]->StreamOffset
= sizeof(DWORD
) + This
->Desc
.dwSize
;
478 static HRESULT WINAPI
DDSDecoder_GetContainerFormat(IWICBitmapDecoder
*iface
, GUID
*pguidContainerFormat
)
480 DDSDecoder
*This
= (DDSDecoder
*)iface
;
481 TRACE("(%p)\n", This
);
483 if (!pguidContainerFormat
) return E_INVALIDARG
;
484 memcpy(pguidContainerFormat
, &GUID_d3dx_container_format_dds
, sizeof(GUID
));
489 static HRESULT WINAPI
DDSDecoder_GetDecoderInfo(IWICBitmapDecoder
*iface
, IWICBitmapDecoderInfo
**ppIDecoderInfo
)
491 DDSDecoder
*This
= (DDSDecoder
*)iface
;
492 FIXME("(%p): stub\n", This
);
496 static HRESULT WINAPI
DDSDecoder_CopyPalette(IWICBitmapDecoder
*iface
, IWICPalette
*pIPalette
)
498 DDSDecoder
*This
= (DDSDecoder
*)iface
;
499 FIXME("(%p): stub\n", This
);
503 static HRESULT WINAPI
DDSDecoder_GetMetadataQueryReader(IWICBitmapDecoder
*iface
, IWICMetadataQueryReader
**ppIMetadataQueryReader
)
505 DDSDecoder
*This
= (DDSDecoder
*)iface
;
506 FIXME("(%p): stub\n", This
);
510 static HRESULT WINAPI
DDSDecoder_GetPreview(IWICBitmapDecoder
*iface
, IWICBitmapSource
**ppIBitmapSource
)
512 DDSDecoder
*This
= (DDSDecoder
*)iface
;
513 FIXME("(%p): stub\n", This
);
517 static HRESULT WINAPI
DDSDecoder_GetColorContexts(IWICBitmapDecoder
*iface
, UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
519 DDSDecoder
*This
= (DDSDecoder
*)iface
;
520 FIXME("(%p): stub\n", This
);
524 static HRESULT WINAPI
DDSDecoder_GetThumbnail(IWICBitmapDecoder
*iface
, IWICBitmapSource
**ppIThumbnail
)
526 DDSDecoder
*This
= (DDSDecoder
*)iface
;
527 FIXME("(%p): stub\n", This
);
531 static HRESULT WINAPI
DDSDecoder_GetFrameCount(IWICBitmapDecoder
*iface
, UINT
*pCount
)
533 DDSDecoder
*This
= (DDSDecoder
*)iface
;
534 TRACE("(%p)\n", This
);
536 if( !pCount
) return E_INVALIDARG
;
537 *pCount
= This
->NumFrames
;
542 /***********************************************
543 * DDSDecoder_GetFrame
545 * Frame indices for normal textures:
552 static HRESULT WINAPI
DDSDecoder_GetFrame(IWICBitmapDecoder
*iface
, UINT index
, IWICBitmapFrameDecode
**ppIBitmapFrame
)
554 DDSDecoder
*This
= (DDSDecoder
*)iface
;
555 TRACE("(%p)\n", This
);
557 if (!This
->pStream
) return WINCODEC_ERR_WRONGSTATE
;
558 if(index
>= This
->NumFrames
) return E_INVALIDARG
;
560 *ppIBitmapFrame
= (IWICBitmapFrameDecode
*)This
->ppFrameDecoders
[index
];
561 IWICBitmapFrameDecode_AddRef((IWICBitmapFrameDecode
*)This
->ppFrameDecoders
[index
]);
567 static const IWICBitmapDecoderVtbl DDSDecoderVtbl
= {
568 DDSDecoder_QueryInterface
,
571 DDSDecoder_QueryCapability
,
572 DDSDecoder_Initialize
,
573 DDSDecoder_GetContainerFormat
,
574 DDSDecoder_GetDecoderInfo
,
575 DDSDecoder_CopyPalette
,
576 DDSDecoder_GetMetadataQueryReader
,
577 DDSDecoder_GetPreview
,
578 DDSDecoder_GetColorContexts
,
579 DDSDecoder_GetThumbnail
,
580 DDSDecoder_GetFrameCount
,
584 HRESULT
DDSDecoder_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
589 TRACE("(%p,%s,%p)\n", pUnkOuter
, debugstr_guid(iid
), ppv
);
591 if (!ppv
) return E_INVALIDARG
;
594 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
596 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DDSDecoder
));
597 if (!This
) return E_OUTOFMEMORY
;
599 This
->lpVtbl
= &DDSDecoderVtbl
;
602 ret
= IWICBitmapDecoder_QueryInterface((IWICBitmapDecoder
*)This
, iid
, ppv
);
603 IWICBitmapDecoder_Release((IWICBitmapDecoder
*)This
);