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
24 #define WIN32_NO_STATUS
33 #include "wincodecs_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
40 const WICPixelFormatGUID
*format
;
42 } pixel_format_bpp
[] =
44 {&GUID_PKPixelFormat128bppRGBAFixedPoint
, 128},
45 {&GUID_PKPixelFormat128bppRGBAFloat
, 128},
46 {&GUID_PKPixelFormat128bppRGBFloat
, 128},
47 {&GUID_PKPixelFormat16bppRGB555
, 16},
48 {&GUID_PKPixelFormat16bppRGB565
, 16},
49 {&GUID_PKPixelFormat16bppGray
, 16},
50 {&GUID_PKPixelFormat16bppGrayFixedPoint
, 16},
51 {&GUID_PKPixelFormat16bppGrayHalf
, 16},
52 {&GUID_PKPixelFormat24bppBGR
, 24},
53 {&GUID_PKPixelFormat24bppRGB
, 24},
54 {&GUID_PKPixelFormat32bppBGR
, 32},
55 {&GUID_PKPixelFormat32bppRGB101010
, 32},
56 {&GUID_PKPixelFormat32bppBGRA
, 32},
57 {&GUID_PKPixelFormat32bppCMYK
, 32},
58 {&GUID_PKPixelFormat32bppGrayFixedPoint
, 32},
59 {&GUID_PKPixelFormat32bppGrayFloat
, 32},
60 {&GUID_PKPixelFormat32bppRGBE
, 32},
61 {&GUID_PKPixelFormat40bppCMYKAlpha
, 40},
62 {&GUID_PKPixelFormat48bppRGB
, 48},
63 {&GUID_PKPixelFormat48bppRGBFixedPoint
, 48},
64 {&GUID_PKPixelFormat48bppRGBHalf
, 48},
65 {&GUID_PKPixelFormat64bppCMYK
, 64},
66 {&GUID_PKPixelFormat64bppRGBA
, 64},
67 {&GUID_PKPixelFormat64bppRGBAFixedPoint
, 64},
68 {&GUID_PKPixelFormat64bppRGBAHalf
, 64},
69 {&GUID_PKPixelFormat80bppCMYKAlpha
, 80},
70 {&GUID_PKPixelFormat8bppGray
, 8},
71 {&GUID_PKPixelFormat96bppRGBFixedPoint
, 96},
72 {&GUID_PKPixelFormatBlackWhite
, 1},
75 static inline UINT
pixel_format_get_bpp(const WICPixelFormatGUID
*format
)
78 for (i
= 0; i
< ARRAY_SIZE(pixel_format_bpp
); ++i
)
79 if (IsEqualGUID(format
, pixel_format_bpp
[i
].format
)) return pixel_format_bpp
[i
].bpp
;
85 struct decoder decoder_iface
;
86 struct WMPStream WMPStream_iface
;
87 PKImageDecode
*decoder
;
89 struct decoder_frame frame
;
94 static inline struct wmp_decoder
*impl_from_decoder(struct decoder
*iface
)
96 return CONTAINING_RECORD(iface
, struct wmp_decoder
, decoder_iface
);
99 static inline struct wmp_decoder
*impl_from_WMPStream(struct WMPStream
*iface
)
101 return CONTAINING_RECORD(iface
, struct wmp_decoder
, WMPStream_iface
);
104 static JXR_ERR
wmp_stream_Close(struct WMPStream
**piface
)
106 TRACE("iface %p\n", piface
);
107 return WMP_errSuccess
;
110 static Bool
wmp_stream_EOS(struct WMPStream
*iface
)
112 FIXME("iface %p, stub!\n", iface
);
116 static JXR_ERR
wmp_stream_Read(struct WMPStream
*iface
, void *buf
, size_t len
)
118 struct wmp_decoder
*This
= impl_from_WMPStream(iface
);
120 if (FAILED(stream_read(This
->stream
, buf
, len
, &count
)) || count
!= len
)
122 WARN("Failed to read data!\n");
123 return WMP_errFileIO
;
125 return WMP_errSuccess
;
128 static JXR_ERR
wmp_stream_Write(struct WMPStream
*iface
, const void *buf
, size_t len
)
130 struct wmp_decoder
*This
= impl_from_WMPStream(iface
);
132 if (FAILED(stream_write(This
->stream
, buf
, len
, &count
)) || count
!= len
)
134 WARN("Failed to write data!\n");
135 return WMP_errFileIO
;
137 return WMP_errSuccess
;
140 static JXR_ERR
wmp_stream_SetPos(struct WMPStream
*iface
, size_t pos
)
142 struct wmp_decoder
*This
= impl_from_WMPStream(iface
);
143 if (FAILED(stream_seek(This
->stream
, pos
, STREAM_SEEK_SET
, NULL
)))
145 WARN("Failed to set stream pos!\n");
146 return WMP_errFileIO
;
148 return WMP_errSuccess
;
151 static JXR_ERR
wmp_stream_GetPos(struct WMPStream
*iface
, size_t *pos
)
153 struct wmp_decoder
*This
= impl_from_WMPStream(iface
);
155 if (FAILED(stream_seek(This
->stream
, 0, STREAM_SEEK_CUR
, &ofs
)))
157 WARN("Failed to get stream pos!\n");
158 return WMP_errFileIO
;
161 return WMP_errSuccess
;
164 static HRESULT CDECL
wmp_decoder_initialize(struct decoder
*iface
, IStream
*stream
, struct decoder_stat
*st
)
166 struct wmp_decoder
*This
= impl_from_decoder(iface
);
172 TRACE("iface %p, stream %p, st %p\n", iface
, stream
, st
);
175 return WINCODEC_ERR_WRONGSTATE
;
177 This
->stream
= stream
;
178 if (FAILED(hr
= stream_seek(This
->stream
, 0, STREAM_SEEK_SET
, NULL
)))
180 if (This
->decoder
->Initialize(This
->decoder
, &This
->WMPStream_iface
))
182 ERR("Failed to initialize jxrlib decoder!\n");
186 if (This
->decoder
->GetFrameCount(This
->decoder
, &st
->frame_count
))
188 ERR("Failed to get frame count!\n");
192 if (st
->frame_count
> 1) FIXME("multi frame JPEG-XR not implemented\n");
194 st
->flags
= WICBitmapDecoderCapabilityCanDecodeAllImages
|
195 WICBitmapDecoderCapabilityCanDecodeSomeImages
|
196 WICBitmapDecoderCapabilityCanEnumerateMetadata
;
198 if (This
->decoder
->SelectFrame(This
->decoder
, 0))
200 ERR("Failed to select frame 0!\n");
203 if (This
->decoder
->GetPixelFormat(This
->decoder
, &This
->frame
.pixel_format
))
205 ERR("Failed to get frame pixel format!\n");
208 if (This
->decoder
->GetSize(This
->decoder
, &width
, &height
))
210 ERR("Failed to get frame size!\n");
213 if (This
->decoder
->GetResolution(This
->decoder
, &dpix
, &dpiy
))
215 ERR("Failed to get frame resolution!\n");
218 if (This
->decoder
->GetColorContext(This
->decoder
, NULL
, &count
))
220 ERR("Failed to get frame color context size!\n");
224 if (!(This
->frame
.bpp
= pixel_format_get_bpp(&This
->frame
.pixel_format
))) return E_FAIL
;
225 This
->frame
.width
= width
;
226 This
->frame
.height
= height
;
227 This
->frame
.dpix
= dpix
;
228 This
->frame
.dpiy
= dpiy
;
229 This
->frame
.num_colors
= 0;
230 if (count
) This
->frame
.num_color_contexts
= 1;
231 else This
->frame
.num_color_contexts
= 0;
236 static HRESULT CDECL
wmp_decoder_get_frame_info(struct decoder
*iface
, UINT frame
, struct decoder_frame
*info
)
238 struct wmp_decoder
*This
= impl_from_decoder(iface
);
240 TRACE("iface %p, frame %d, info %p\n", iface
, frame
, info
);
244 FIXME("multi frame JPEG-XR not implemented\n");
252 static HRESULT CDECL
wmp_decoder_copy_pixels(struct decoder
*iface
, UINT frame
, const WICRect
*prc
, UINT stride
, UINT buffersize
, BYTE
*buffer
)
254 struct wmp_decoder
*This
= impl_from_decoder(iface
);
258 TRACE("iface %p, frame %d, rect %p, stride %d, buffersize %d, buffer %p\n", iface
, frame
, prc
, stride
, buffersize
, buffer
);
262 FIXME("multi frame JPEG-XR not implemented\n");
266 if (!This
->frame_data
)
270 pkrect
.Width
= This
->frame
.width
;
271 pkrect
.Height
= This
->frame
.height
;
272 This
->frame_stride
= (This
->frame
.width
* This
->frame
.bpp
+ 7) / 8;
273 if (!(frame_data
= RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->frame
.height
* This
->frame_stride
)))
275 if (This
->decoder
->Copy(This
->decoder
, &pkrect
, frame_data
, stride
))
277 ERR("Failed to copy frame data!\n");
278 RtlFreeHeap(GetProcessHeap(), 0, frame_data
);
282 This
->frame_data
= frame_data
;
285 return copy_pixels(This
->frame
.bpp
, This
->frame_data
,
286 This
->frame
.width
, This
->frame
.height
, This
->frame_stride
,
287 prc
, stride
, buffersize
, buffer
);
290 static HRESULT CDECL
wmp_decoder_get_metadata_blocks(struct decoder
* iface
, UINT frame
, UINT
*count
, struct decoder_block
**blocks
)
292 TRACE("iface %p, frame %d, count %p, blocks %p\n", iface
, frame
, count
, blocks
);
299 static HRESULT CDECL
wmp_decoder_get_color_context(struct decoder
* iface
, UINT frame
, UINT num
, BYTE
**data
, DWORD
*datasize
)
301 struct wmp_decoder
*This
= impl_from_decoder(iface
);
305 TRACE("iface %p, frame %d, num %u, data %p, datasize %p\n", iface
, frame
, num
, data
, datasize
);
310 if (This
->decoder
->GetColorContext(This
->decoder
, NULL
, &count
))
312 ERR("Failed to get frame color context size!\n");
317 bytes
= RtlAllocateHeap(GetProcessHeap(), 0, count
);
319 return E_OUTOFMEMORY
;
321 if (This
->decoder
->GetColorContext(This
->decoder
, bytes
, &count
))
323 ERR("Failed to get frame color context!\n");
324 RtlFreeHeap(GetProcessHeap(), 0, bytes
);
332 static void CDECL
wmp_decoder_destroy(struct decoder
* iface
)
334 struct wmp_decoder
*This
= impl_from_decoder(iface
);
336 TRACE("iface %p\n", iface
);
338 This
->decoder
->Release(&This
->decoder
);
339 RtlFreeHeap(GetProcessHeap(), 0, This
->frame_data
);
340 RtlFreeHeap(GetProcessHeap(), 0, This
);
343 static const struct decoder_funcs wmp_decoder_vtable
= {
344 wmp_decoder_initialize
,
345 wmp_decoder_get_frame_info
,
346 wmp_decoder_copy_pixels
,
347 wmp_decoder_get_metadata_blocks
,
348 wmp_decoder_get_color_context
,
352 HRESULT CDECL
wmp_decoder_create(struct decoder_info
*info
, struct decoder
**result
)
354 struct wmp_decoder
*This
;
355 PKImageDecode
*decoder
;
357 if (PKImageDecode_Create_WMP(&decoder
)) return E_FAIL
;
358 This
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This
));
361 decoder
->Release(&decoder
);
362 return E_OUTOFMEMORY
;
365 This
->decoder_iface
.vtable
= &wmp_decoder_vtable
;
366 This
->WMPStream_iface
.Close
= &wmp_stream_Close
;
367 This
->WMPStream_iface
.EOS
= &wmp_stream_EOS
;
368 This
->WMPStream_iface
.Read
= &wmp_stream_Read
;
369 This
->WMPStream_iface
.Write
= &wmp_stream_Write
;
370 This
->WMPStream_iface
.SetPos
= &wmp_stream_SetPos
;
371 This
->WMPStream_iface
.GetPos
= &wmp_stream_GetPos
;
373 This
->decoder
= decoder
;
375 memset(&This
->frame
, 0, sizeof(This
->frame
));
376 This
->frame_stride
= 0;
377 This
->frame_data
= NULL
;
379 *result
= &This
->decoder_iface
;
381 info
->container_format
= GUID_ContainerFormatWmp
;
382 info
->block_format
= GUID_ContainerFormatWmp
;
383 info
->clsid
= CLSID_WICWmpDecoder
;