2 * Interface with jxr library
4 * Copyright 2020 Esme Povirk
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define NONAMELESSUNION
25 #define WIN32_NO_STATUS
34 #include "wincodecs_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
41 const WICPixelFormatGUID
*format
;
43 } pixel_format_bpp
[] =
45 {&GUID_PKPixelFormat128bppRGBAFixedPoint
, 128},
46 {&GUID_PKPixelFormat128bppRGBAFloat
, 128},
47 {&GUID_PKPixelFormat128bppRGBFloat
, 128},
48 {&GUID_PKPixelFormat16bppRGB555
, 16},
49 {&GUID_PKPixelFormat16bppRGB565
, 16},
50 {&GUID_PKPixelFormat16bppGray
, 16},
51 {&GUID_PKPixelFormat16bppGrayFixedPoint
, 16},
52 {&GUID_PKPixelFormat16bppGrayHalf
, 16},
53 {&GUID_PKPixelFormat24bppBGR
, 24},
54 {&GUID_PKPixelFormat24bppRGB
, 24},
55 {&GUID_PKPixelFormat32bppBGR
, 32},
56 {&GUID_PKPixelFormat32bppRGB101010
, 32},
57 {&GUID_PKPixelFormat32bppBGRA
, 32},
58 {&GUID_PKPixelFormat32bppCMYK
, 32},
59 {&GUID_PKPixelFormat32bppGrayFixedPoint
, 32},
60 {&GUID_PKPixelFormat32bppGrayFloat
, 32},
61 {&GUID_PKPixelFormat32bppRGBE
, 32},
62 {&GUID_PKPixelFormat40bppCMYKAlpha
, 40},
63 {&GUID_PKPixelFormat48bppRGB
, 48},
64 {&GUID_PKPixelFormat48bppRGBFixedPoint
, 48},
65 {&GUID_PKPixelFormat48bppRGBHalf
, 48},
66 {&GUID_PKPixelFormat64bppCMYK
, 64},
67 {&GUID_PKPixelFormat64bppRGBA
, 64},
68 {&GUID_PKPixelFormat64bppRGBAFixedPoint
, 64},
69 {&GUID_PKPixelFormat64bppRGBAHalf
, 64},
70 {&GUID_PKPixelFormat80bppCMYKAlpha
, 80},
71 {&GUID_PKPixelFormat8bppGray
, 8},
72 {&GUID_PKPixelFormat96bppRGBFixedPoint
, 96},
73 {&GUID_PKPixelFormatBlackWhite
, 1},
76 static inline UINT
pixel_format_get_bpp(const WICPixelFormatGUID
*format
)
79 for (i
= 0; i
< ARRAY_SIZE(pixel_format_bpp
); ++i
)
80 if (IsEqualGUID(format
, pixel_format_bpp
[i
].format
)) return pixel_format_bpp
[i
].bpp
;
86 struct decoder decoder_iface
;
87 struct WMPStream WMPStream_iface
;
88 PKImageDecode
*decoder
;
90 struct decoder_frame frame
;
95 static inline struct wmp_decoder
*impl_from_decoder(struct decoder
*iface
)
97 return CONTAINING_RECORD(iface
, struct wmp_decoder
, decoder_iface
);
100 static inline struct wmp_decoder
*impl_from_WMPStream(struct WMPStream
*iface
)
102 return CONTAINING_RECORD(iface
, struct wmp_decoder
, WMPStream_iface
);
105 static JXR_ERR
wmp_stream_Close(struct WMPStream
**piface
)
107 TRACE("iface %p\n", piface
);
108 return WMP_errSuccess
;
111 static Bool
wmp_stream_EOS(struct WMPStream
*iface
)
113 FIXME("iface %p, stub!\n", iface
);
117 static JXR_ERR
wmp_stream_Read(struct WMPStream
*iface
, void *buf
, size_t len
)
119 struct wmp_decoder
*This
= impl_from_WMPStream(iface
);
121 if (FAILED(stream_read(This
->stream
, buf
, len
, &count
)) || count
!= len
)
123 WARN("Failed to read data!\n");
124 return WMP_errFileIO
;
126 return WMP_errSuccess
;
129 static JXR_ERR
wmp_stream_Write(struct WMPStream
*iface
, const void *buf
, size_t len
)
131 struct wmp_decoder
*This
= impl_from_WMPStream(iface
);
133 if (FAILED(stream_write(This
->stream
, buf
, len
, &count
)) || count
!= len
)
135 WARN("Failed to write data!\n");
136 return WMP_errFileIO
;
138 return WMP_errSuccess
;
141 static JXR_ERR
wmp_stream_SetPos(struct WMPStream
*iface
, size_t pos
)
143 struct wmp_decoder
*This
= impl_from_WMPStream(iface
);
144 if (FAILED(stream_seek(This
->stream
, pos
, STREAM_SEEK_SET
, NULL
)))
146 WARN("Failed to set stream pos!\n");
147 return WMP_errFileIO
;
149 return WMP_errSuccess
;
152 static JXR_ERR
wmp_stream_GetPos(struct WMPStream
*iface
, size_t *pos
)
154 struct wmp_decoder
*This
= impl_from_WMPStream(iface
);
156 if (FAILED(stream_seek(This
->stream
, 0, STREAM_SEEK_CUR
, &ofs
)))
158 WARN("Failed to get stream pos!\n");
159 return WMP_errFileIO
;
162 return WMP_errSuccess
;
165 static HRESULT CDECL
wmp_decoder_initialize(struct decoder
*iface
, IStream
*stream
, struct decoder_stat
*st
)
167 struct wmp_decoder
*This
= impl_from_decoder(iface
);
173 TRACE("iface %p, stream %p, st %p\n", iface
, stream
, st
);
176 return WINCODEC_ERR_WRONGSTATE
;
178 This
->stream
= stream
;
179 if (FAILED(hr
= stream_seek(This
->stream
, 0, STREAM_SEEK_SET
, NULL
)))
181 if (This
->decoder
->Initialize(This
->decoder
, &This
->WMPStream_iface
))
183 ERR("Failed to initialize jxrlib decoder!\n");
187 if (This
->decoder
->GetFrameCount(This
->decoder
, &st
->frame_count
))
189 ERR("Failed to get frame count!\n");
193 if (st
->frame_count
> 1) FIXME("multi frame JPEG-XR not implemented\n");
195 st
->flags
= WICBitmapDecoderCapabilityCanDecodeAllImages
|
196 WICBitmapDecoderCapabilityCanDecodeSomeImages
|
197 WICBitmapDecoderCapabilityCanEnumerateMetadata
;
199 if (This
->decoder
->SelectFrame(This
->decoder
, 0))
201 ERR("Failed to select frame 0!\n");
204 if (This
->decoder
->GetPixelFormat(This
->decoder
, &This
->frame
.pixel_format
))
206 ERR("Failed to get frame pixel format!\n");
209 if (This
->decoder
->GetSize(This
->decoder
, &width
, &height
))
211 ERR("Failed to get frame size!\n");
214 if (This
->decoder
->GetResolution(This
->decoder
, &dpix
, &dpiy
))
216 ERR("Failed to get frame resolution!\n");
219 if (This
->decoder
->GetColorContext(This
->decoder
, NULL
, &count
))
221 ERR("Failed to get frame color context size!\n");
225 if (!(This
->frame
.bpp
= pixel_format_get_bpp(&This
->frame
.pixel_format
))) return E_FAIL
;
226 This
->frame
.width
= width
;
227 This
->frame
.height
= height
;
228 This
->frame
.dpix
= dpix
;
229 This
->frame
.dpiy
= dpiy
;
230 This
->frame
.num_colors
= 0;
231 if (count
) This
->frame
.num_color_contexts
= 1;
232 else This
->frame
.num_color_contexts
= 0;
237 static HRESULT CDECL
wmp_decoder_get_frame_info(struct decoder
*iface
, UINT frame
, struct decoder_frame
*info
)
239 struct wmp_decoder
*This
= impl_from_decoder(iface
);
241 TRACE("iface %p, frame %d, info %p\n", iface
, frame
, info
);
245 FIXME("multi frame JPEG-XR not implemented\n");
253 static HRESULT CDECL
wmp_decoder_copy_pixels(struct decoder
*iface
, UINT frame
, const WICRect
*prc
, UINT stride
, UINT buffersize
, BYTE
*buffer
)
255 struct wmp_decoder
*This
= impl_from_decoder(iface
);
259 TRACE("iface %p, frame %d, rect %p, stride %d, buffersize %d, buffer %p\n", iface
, frame
, prc
, stride
, buffersize
, buffer
);
263 FIXME("multi frame JPEG-XR not implemented\n");
267 if (!This
->frame_data
)
271 pkrect
.Width
= This
->frame
.width
;
272 pkrect
.Height
= This
->frame
.height
;
273 This
->frame_stride
= (This
->frame
.width
* This
->frame
.bpp
+ 7) / 8;
274 if (!(frame_data
= RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->frame
.height
* This
->frame_stride
)))
276 if (This
->decoder
->Copy(This
->decoder
, &pkrect
, frame_data
, stride
))
278 ERR("Failed to copy frame data!\n");
279 RtlFreeHeap(GetProcessHeap(), 0, frame_data
);
283 This
->frame_data
= frame_data
;
286 return copy_pixels(This
->frame
.bpp
, This
->frame_data
,
287 This
->frame
.width
, This
->frame
.height
, This
->frame_stride
,
288 prc
, stride
, buffersize
, buffer
);
291 static HRESULT CDECL
wmp_decoder_get_metadata_blocks(struct decoder
* iface
, UINT frame
, UINT
*count
, struct decoder_block
**blocks
)
293 TRACE("iface %p, frame %d, count %p, blocks %p\n", iface
, frame
, count
, blocks
);
300 static HRESULT CDECL
wmp_decoder_get_color_context(struct decoder
* iface
, UINT frame
, UINT num
, BYTE
**data
, DWORD
*datasize
)
302 struct wmp_decoder
*This
= impl_from_decoder(iface
);
306 TRACE("iface %p, frame %d, num %u, data %p, datasize %p\n", iface
, frame
, num
, data
, datasize
);
311 if (This
->decoder
->GetColorContext(This
->decoder
, NULL
, &count
))
313 ERR("Failed to get frame color context size!\n");
318 bytes
= RtlAllocateHeap(GetProcessHeap(), 0, count
);
320 return E_OUTOFMEMORY
;
322 if (This
->decoder
->GetColorContext(This
->decoder
, bytes
, &count
))
324 ERR("Failed to get frame color context!\n");
325 RtlFreeHeap(GetProcessHeap(), 0, bytes
);
333 static void CDECL
wmp_decoder_destroy(struct decoder
* iface
)
335 struct wmp_decoder
*This
= impl_from_decoder(iface
);
337 TRACE("iface %p\n", iface
);
339 This
->decoder
->Release(&This
->decoder
);
340 RtlFreeHeap(GetProcessHeap(), 0, This
->frame_data
);
341 RtlFreeHeap(GetProcessHeap(), 0, This
);
344 static const struct decoder_funcs wmp_decoder_vtable
= {
345 wmp_decoder_initialize
,
346 wmp_decoder_get_frame_info
,
347 wmp_decoder_copy_pixels
,
348 wmp_decoder_get_metadata_blocks
,
349 wmp_decoder_get_color_context
,
353 HRESULT CDECL
wmp_decoder_create(struct decoder_info
*info
, struct decoder
**result
)
355 struct wmp_decoder
*This
;
356 PKImageDecode
*decoder
;
358 if (PKImageDecode_Create_WMP(&decoder
)) return E_FAIL
;
359 This
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This
));
362 decoder
->Release(&decoder
);
363 return E_OUTOFMEMORY
;
366 This
->decoder_iface
.vtable
= &wmp_decoder_vtable
;
367 This
->WMPStream_iface
.Close
= &wmp_stream_Close
;
368 This
->WMPStream_iface
.EOS
= &wmp_stream_EOS
;
369 This
->WMPStream_iface
.Read
= &wmp_stream_Read
;
370 This
->WMPStream_iface
.Write
= &wmp_stream_Write
;
371 This
->WMPStream_iface
.SetPos
= &wmp_stream_SetPos
;
372 This
->WMPStream_iface
.GetPos
= &wmp_stream_GetPos
;
374 This
->decoder
= decoder
;
376 memset(&This
->frame
, 0, sizeof(This
->frame
));
377 This
->frame_stride
= 0;
378 This
->frame_data
= NULL
;
380 *result
= &This
->decoder_iface
;
382 info
->container_format
= GUID_ContainerFormatWmp
;
383 info
->block_format
= GUID_ContainerFormatWmp
;
384 info
->clsid
= CLSID_WICWmpDecoder
;