2 * unix_lib.c - This is the Unix side of the Unix interface.
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
26 #include "wine/port.h"
30 #define NONAMELESSUNION
33 #define WIN32_NO_STATUS
40 #ifdef SONAME_LIBJXRGLUE
46 #include "wincodecs_private.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
51 #include "wincodecs_common.h"
53 #ifdef SONAME_LIBJXRGLUE
54 static void *libjxrglue
;
55 static typeof(PKImageDecode_Create_WMP
) *pPKImageDecode_Create_WMP
;
59 const WICPixelFormatGUID
*format
;
61 } pixel_format_bpp
[] =
63 {&GUID_PKPixelFormat128bppRGBAFixedPoint
, 128},
64 {&GUID_PKPixelFormat128bppRGBAFloat
, 128},
65 {&GUID_PKPixelFormat128bppRGBFloat
, 128},
66 {&GUID_PKPixelFormat16bppRGB555
, 16},
67 {&GUID_PKPixelFormat16bppRGB565
, 16},
68 {&GUID_PKPixelFormat16bppGray
, 16},
69 {&GUID_PKPixelFormat16bppGrayFixedPoint
, 16},
70 {&GUID_PKPixelFormat16bppGrayHalf
, 16},
71 {&GUID_PKPixelFormat24bppBGR
, 24},
72 {&GUID_PKPixelFormat24bppRGB
, 24},
73 {&GUID_PKPixelFormat32bppBGR
, 32},
74 {&GUID_PKPixelFormat32bppRGB101010
, 32},
75 {&GUID_PKPixelFormat32bppBGRA
, 32},
76 {&GUID_PKPixelFormat32bppCMYK
, 32},
77 {&GUID_PKPixelFormat32bppGrayFixedPoint
, 32},
78 {&GUID_PKPixelFormat32bppGrayFloat
, 32},
79 {&GUID_PKPixelFormat32bppRGBE
, 32},
80 {&GUID_PKPixelFormat40bppCMYKAlpha
, 40},
81 {&GUID_PKPixelFormat48bppRGB
, 48},
82 {&GUID_PKPixelFormat48bppRGBFixedPoint
, 48},
83 {&GUID_PKPixelFormat48bppRGBHalf
, 48},
84 {&GUID_PKPixelFormat64bppCMYK
, 64},
85 {&GUID_PKPixelFormat64bppRGBA
, 64},
86 {&GUID_PKPixelFormat64bppRGBAFixedPoint
, 64},
87 {&GUID_PKPixelFormat64bppRGBAHalf
, 64},
88 {&GUID_PKPixelFormat80bppCMYKAlpha
, 80},
89 {&GUID_PKPixelFormat8bppGray
, 8},
90 {&GUID_PKPixelFormat96bppRGBFixedPoint
, 96},
91 {&GUID_PKPixelFormatBlackWhite
, 1},
94 static inline UINT
pixel_format_get_bpp(const WICPixelFormatGUID
*format
)
97 for (i
= 0; i
< ARRAY_SIZE(pixel_format_bpp
); ++i
)
98 if (IsEqualGUID(format
, pixel_format_bpp
[i
].format
)) return pixel_format_bpp
[i
].bpp
;
104 struct decoder decoder_iface
;
105 struct WMPStream WMPStream_iface
;
106 PKImageDecode
*decoder
;
108 struct decoder_frame frame
;
113 static inline struct wmp_decoder
*impl_from_decoder(struct decoder
*iface
)
115 return CONTAINING_RECORD(iface
, struct wmp_decoder
, decoder_iface
);
118 static inline struct wmp_decoder
*impl_from_WMPStream(struct WMPStream
*iface
)
120 return CONTAINING_RECORD(iface
, struct wmp_decoder
, WMPStream_iface
);
123 static JXR_ERR
wmp_stream_Close(struct WMPStream
**piface
)
125 TRACE("iface %p\n", piface
);
126 return WMP_errSuccess
;
129 static Bool
wmp_stream_EOS(struct WMPStream
*iface
)
131 FIXME("iface %p, stub!\n", iface
);
135 static JXR_ERR
wmp_stream_Read(struct WMPStream
*iface
, void *buf
, size_t len
)
137 struct wmp_decoder
*This
= impl_from_WMPStream(iface
);
139 if (FAILED(stream_read(This
->stream
, buf
, len
, &count
)) || count
!= len
)
141 WARN("Failed to read data!\n");
142 return WMP_errFileIO
;
144 return WMP_errSuccess
;
147 static JXR_ERR
wmp_stream_Write(struct WMPStream
*iface
, const void *buf
, size_t len
)
149 struct wmp_decoder
*This
= impl_from_WMPStream(iface
);
151 if (FAILED(stream_write(This
->stream
, buf
, len
, &count
)) || count
!= len
)
153 WARN("Failed to write data!\n");
154 return WMP_errFileIO
;
156 return WMP_errSuccess
;
159 static JXR_ERR
wmp_stream_SetPos(struct WMPStream
*iface
, size_t pos
)
161 struct wmp_decoder
*This
= impl_from_WMPStream(iface
);
162 if (FAILED(stream_seek(This
->stream
, pos
, STREAM_SEEK_SET
, NULL
)))
164 WARN("Failed to set stream pos!\n");
165 return WMP_errFileIO
;
167 return WMP_errSuccess
;
170 static JXR_ERR
wmp_stream_GetPos(struct WMPStream
*iface
, size_t *pos
)
172 struct wmp_decoder
*This
= impl_from_WMPStream(iface
);
174 if (FAILED(stream_seek(This
->stream
, 0, STREAM_SEEK_CUR
, &ofs
)))
176 WARN("Failed to get stream pos!\n");
177 return WMP_errFileIO
;
180 return WMP_errSuccess
;
183 HRESULT CDECL
wmp_decoder_initialize(struct decoder
*iface
, IStream
*stream
, struct decoder_stat
*st
)
185 struct wmp_decoder
*This
= impl_from_decoder(iface
);
191 TRACE("iface %p, stream %p, st %p\n", iface
, stream
, st
);
194 return WINCODEC_ERR_WRONGSTATE
;
196 This
->stream
= stream
;
197 if (FAILED(hr
= stream_seek(This
->stream
, 0, STREAM_SEEK_SET
, NULL
)))
199 if (This
->decoder
->Initialize(This
->decoder
, &This
->WMPStream_iface
))
201 ERR("Failed to initialize jxrlib decoder!\n");
205 if (This
->decoder
->GetFrameCount(This
->decoder
, &st
->frame_count
))
207 ERR("Failed to get frame count!\n");
211 if (st
->frame_count
> 1) FIXME("multi frame JPEG-XR not implemented\n");
213 st
->flags
= WICBitmapDecoderCapabilityCanDecodeAllImages
|
214 WICBitmapDecoderCapabilityCanDecodeSomeImages
|
215 WICBitmapDecoderCapabilityCanEnumerateMetadata
;
217 if (This
->decoder
->SelectFrame(This
->decoder
, 0))
219 ERR("Failed to select frame 0!\n");
222 if (This
->decoder
->GetPixelFormat(This
->decoder
, &This
->frame
.pixel_format
))
224 ERR("Failed to get frame pixel format!\n");
227 if (This
->decoder
->GetSize(This
->decoder
, &width
, &height
))
229 ERR("Failed to get frame size!\n");
232 if (This
->decoder
->GetResolution(This
->decoder
, &dpix
, &dpiy
))
234 ERR("Failed to get frame resolution!\n");
237 if (This
->decoder
->GetColorContext(This
->decoder
, NULL
, &count
))
239 ERR("Failed to get frame color context size!\n");
243 if (!(This
->frame
.bpp
= pixel_format_get_bpp(&This
->frame
.pixel_format
))) return E_FAIL
;
244 This
->frame
.width
= width
;
245 This
->frame
.height
= height
;
246 This
->frame
.dpix
= dpix
;
247 This
->frame
.dpiy
= dpiy
;
248 This
->frame
.num_colors
= 0;
249 if (count
) This
->frame
.num_color_contexts
= 1;
250 else This
->frame
.num_color_contexts
= 0;
255 HRESULT CDECL
wmp_decoder_get_frame_info(struct decoder
*iface
, UINT frame
, struct decoder_frame
*info
)
257 struct wmp_decoder
*This
= impl_from_decoder(iface
);
259 TRACE("iface %p, frame %d, info %p\n", iface
, frame
, info
);
263 FIXME("multi frame JPEG-XR not implemented\n");
271 HRESULT CDECL
wmp_decoder_copy_pixels(struct decoder
*iface
, UINT frame
, const WICRect
*prc
, UINT stride
, UINT buffersize
, BYTE
*buffer
)
273 struct wmp_decoder
*This
= impl_from_decoder(iface
);
277 TRACE("iface %p, frame %d, rect %p, stride %d, buffersize %d, buffer %p\n", iface
, frame
, prc
, stride
, buffersize
, buffer
);
281 FIXME("multi frame JPEG-XR not implemented\n");
285 if (!This
->frame_data
)
289 pkrect
.Width
= This
->frame
.width
;
290 pkrect
.Height
= This
->frame
.height
;
291 This
->frame_stride
= (This
->frame
.width
* This
->frame
.bpp
+ 7) / 8;
292 if (!(frame_data
= RtlAllocateHeap(GetProcessHeap(), 0, This
->frame
.height
* This
->frame_stride
)))
294 if (This
->decoder
->Copy(This
->decoder
, &pkrect
, frame_data
, stride
))
296 ERR("Failed to copy frame data!\n");
297 RtlFreeHeap(GetProcessHeap(), 0, frame_data
);
301 This
->frame_data
= frame_data
;
304 return copy_pixels(This
->frame
.bpp
, This
->frame_data
,
305 This
->frame
.width
, This
->frame
.height
, This
->frame_stride
,
306 prc
, stride
, buffersize
, buffer
);
309 HRESULT CDECL
wmp_decoder_get_metadata_blocks(struct decoder
* iface
, UINT frame
, UINT
*count
, struct decoder_block
**blocks
)
311 TRACE("iface %p, frame %d, count %p, blocks %p\n", iface
, frame
, count
, blocks
);
318 HRESULT CDECL
wmp_decoder_get_color_context(struct decoder
* iface
, UINT frame
, UINT num
, BYTE
**data
, DWORD
*datasize
)
320 struct wmp_decoder
*This
= impl_from_decoder(iface
);
324 TRACE("iface %p, frame %d, num %u, data %p, datasize %p\n", iface
, frame
, num
, data
, datasize
);
329 if (This
->decoder
->GetColorContext(This
->decoder
, NULL
, &count
))
331 ERR("Failed to get frame color context size!\n");
336 bytes
= RtlAllocateHeap(GetProcessHeap(), 0, count
);
338 return E_OUTOFMEMORY
;
340 if (This
->decoder
->GetColorContext(This
->decoder
, bytes
, &count
))
342 ERR("Failed to get frame color context!\n");
343 RtlFreeHeap(GetProcessHeap(), 0, bytes
);
351 void CDECL
wmp_decoder_destroy(struct decoder
* iface
)
353 struct wmp_decoder
*This
= impl_from_decoder(iface
);
355 TRACE("iface %p\n", iface
);
357 This
->decoder
->Release(&This
->decoder
);
358 RtlFreeHeap(GetProcessHeap(), 0, This
->frame_data
);
359 RtlFreeHeap(GetProcessHeap(), 0, This
);
362 static const struct decoder_funcs wmp_decoder_vtable
= {
363 wmp_decoder_initialize
,
364 wmp_decoder_get_frame_info
,
365 wmp_decoder_copy_pixels
,
366 wmp_decoder_get_metadata_blocks
,
367 wmp_decoder_get_color_context
,
371 HRESULT CDECL
wmp_decoder_create(struct decoder_info
*info
, struct decoder
**result
)
373 struct wmp_decoder
*This
;
374 PKImageDecode
*decoder
;
376 if (!pPKImageDecode_Create_WMP
|| pPKImageDecode_Create_WMP(&decoder
)) return E_FAIL
;
377 This
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This
));
379 return E_OUTOFMEMORY
;
381 This
->decoder_iface
.vtable
= &wmp_decoder_vtable
;
382 This
->WMPStream_iface
.Close
= &wmp_stream_Close
;
383 This
->WMPStream_iface
.EOS
= &wmp_stream_EOS
;
384 This
->WMPStream_iface
.Read
= &wmp_stream_Read
;
385 This
->WMPStream_iface
.Write
= &wmp_stream_Write
;
386 This
->WMPStream_iface
.SetPos
= &wmp_stream_SetPos
;
387 This
->WMPStream_iface
.GetPos
= &wmp_stream_GetPos
;
389 This
->decoder
= decoder
;
391 memset(&This
->frame
, 0, sizeof(This
->frame
));
392 This
->frame_stride
= 0;
393 This
->frame_data
= NULL
;
395 *result
= &This
->decoder_iface
;
397 info
->container_format
= GUID_ContainerFormatWmp
;
398 info
->block_format
= GUID_ContainerFormatWmp
;
399 info
->clsid
= CLSID_WICWmpDecoder
;
405 static const struct win32_funcs
*win32_funcs
;
407 HRESULT CDECL
stream_getsize(IStream
*stream
, ULONGLONG
*size
)
409 return win32_funcs
->stream_getsize(stream
, size
);
412 HRESULT CDECL
stream_read(IStream
*stream
, void *buffer
, ULONG read
, ULONG
*bytes_read
)
414 return win32_funcs
->stream_read(stream
, buffer
, read
, bytes_read
);
417 HRESULT CDECL
stream_seek(IStream
*stream
, LONGLONG ofs
, DWORD origin
, ULONGLONG
*new_position
)
419 return win32_funcs
->stream_seek(stream
, ofs
, origin
, new_position
);
422 HRESULT CDECL
stream_write(IStream
*stream
, const void *buffer
, ULONG write
, ULONG
*bytes_written
)
424 return win32_funcs
->stream_write(stream
, buffer
, write
, bytes_written
);
427 HRESULT CDECL
decoder_create(const CLSID
*decoder_clsid
, struct decoder_info
*info
, struct decoder
**result
)
429 if (IsEqualGUID(decoder_clsid
, &CLSID_WICWmpDecoder
))
430 #ifdef SONAME_LIBJXRGLUE
431 return wmp_decoder_create(info
, result
);
434 WARN("jxrlib support not compiled in, returning E_NOINTERFACE.\n");
435 return E_NOINTERFACE
;
439 FIXME("encoder_clsid %s, info %p, result %p, stub!\n", debugstr_guid(decoder_clsid
), info
, result
);
443 HRESULT CDECL
encoder_create(const CLSID
*encoder_clsid
, struct encoder_info
*info
, struct encoder
**result
)
445 FIXME("encoder_clsid %s, info %p, result %p, stub!\n", debugstr_guid(encoder_clsid
), info
, result
);
449 static const struct unix_funcs unix_funcs
= {
452 decoder_get_frame_info
,
454 decoder_get_metadata_blocks
,
455 decoder_get_color_context
,
459 encoder_get_supported_format
,
460 encoder_create_frame
,
462 encoder_commit_frame
,
467 NTSTATUS CDECL
__wine_init_unix_lib( HMODULE module
, DWORD reason
, const void *ptr_in
, void *ptr_out
)
469 if (reason
!= DLL_PROCESS_ATTACH
) return STATUS_SUCCESS
;
471 win32_funcs
= ptr_in
;
473 #ifdef SONAME_LIBJXRGLUE
474 if (!(libjxrglue
= dlopen(SONAME_LIBJXRGLUE
, RTLD_NOW
)))
475 ERR("failed to load %s\n", SONAME_LIBJXRGLUE
);
476 else if (!(pPKImageDecode_Create_WMP
= dlsym(libjxrglue
, "PKImageDecode_Create_WMP")))
477 ERR("unable to find PKImageDecode_Create_WMP in %s!\n", SONAME_LIBJXRGLUE
);
479 ERR("jxrlib support not compiled in!\n");
482 *(const struct unix_funcs
**)ptr_out
= &unix_funcs
;
483 return STATUS_SUCCESS
;