1 /* 2 * wincodecs_common.c - Functions shared with other WIC libraries. 3 * 4 * Copyright 2020 Esme Povirk 5 * 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. 10 * 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. 15 * 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 19 */ 20 21 #define COBJMACROS 22 23 #include <stdarg.h> 24 25 #include "windef.h" 26 #include "winbase.h" 27 #include "winternl.h" 28 #include "objbase.h" 29 30 #include "wincodecs_private.h" 31 32 #include "wine/debug.h" 33 34 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); 35 36 #include "wincodecs_common.h" 37 38 HRESULT configure_write_source(IWICBitmapFrameEncode *iface, 39 IWICBitmapSource *source, const WICRect *prc, 40 const WICPixelFormatGUID *format, 41 INT width, INT height, double xres, double yres) 42 { 43 UINT src_width, src_height; 44 HRESULT hr = S_OK; 45 46 if (width == 0 && height == 0) 47 { 48 if (prc) 49 { 50 if (prc->Width <= 0 || prc->Height <= 0) return E_INVALIDARG; 51 width = prc->Width; 52 height = prc->Height; 53 } 54 else 55 { 56 hr = IWICBitmapSource_GetSize(source, &src_width, &src_height); 57 if (FAILED(hr)) return hr; 58 if (src_width == 0 || src_height == 0) return E_INVALIDARG; 59 width = src_width; 60 height = src_height; 61 } 62 hr = IWICBitmapFrameEncode_SetSize(iface, (UINT)width, (UINT)height); 63 if (FAILED(hr)) return hr; 64 } 65 if (width == 0 || height == 0) return E_INVALIDARG; 66 67 if (!format) 68 { 69 WICPixelFormatGUID src_format; 70 71 hr = IWICBitmapSource_GetPixelFormat(source, &src_format); 72 if (FAILED(hr)) return hr; 73 74 hr = IWICBitmapFrameEncode_SetPixelFormat(iface, &src_format); 75 if (FAILED(hr)) return hr; 76 } 77 78 if (xres == 0.0 || yres == 0.0) 79 { 80 hr = IWICBitmapSource_GetResolution(source, &xres, &yres); 81 if (FAILED(hr)) return hr; 82 hr = IWICBitmapFrameEncode_SetResolution(iface, xres, yres); 83 if (FAILED(hr)) return hr; 84 } 85 86 return hr; 87 } 88 89 HRESULT write_source(IWICBitmapFrameEncode *iface, 90 IWICBitmapSource *source, const WICRect *prc, 91 const WICPixelFormatGUID *format, UINT bpp, BOOL need_palette, 92 INT width, INT height) 93 { 94 IWICBitmapSource *converted_source; 95 HRESULT hr=S_OK; 96 WICRect rc; 97 UINT stride; 98 BYTE* pixeldata; 99 100 if (!prc) 101 { 102 UINT src_width, src_height; 103 hr = IWICBitmapSource_GetSize(source, &src_width, &src_height); 104 if (FAILED(hr)) return hr; 105 rc.X = 0; 106 rc.Y = 0; 107 rc.Width = src_width; 108 rc.Height = src_height; 109 prc = &rc; 110 } 111 112 if (prc->Width != width || prc->Height <= 0) 113 return E_INVALIDARG; 114 115 hr = WICConvertBitmapSource(format, source, &converted_source); 116 if (FAILED(hr)) 117 { 118 ERR("Failed to convert source, target format %s, %#lx\n", debugstr_guid(format), hr); 119 return E_NOTIMPL; 120 } 121 122 if (need_palette) 123 { 124 IWICImagingFactory *factory; 125 IWICPalette *palette; 126 127 hr = create_instance(&CLSID_WICImagingFactory, &IID_IWICImagingFactory, (void**)&factory); 128 129 if (SUCCEEDED(hr)) 130 { 131 hr = IWICImagingFactory_CreatePalette(factory, &palette); 132 IWICImagingFactory_Release(factory); 133 } 134 135 if (SUCCEEDED(hr)) 136 { 137 hr = IWICBitmapSource_CopyPalette(converted_source, palette); 138 139 if (SUCCEEDED(hr)) 140 hr = IWICBitmapFrameEncode_SetPalette(iface, palette); 141 142 IWICPalette_Release(palette); 143 } 144 145 if (FAILED(hr)) 146 { 147 IWICBitmapSource_Release(converted_source); 148 return hr; 149 } 150 } 151 152 stride = (bpp * width + 7)/8; 153 154 pixeldata = malloc(stride * prc->Height); 155 if (!pixeldata) 156 { 157 IWICBitmapSource_Release(converted_source); 158 return E_OUTOFMEMORY; 159 } 160 161 hr = IWICBitmapSource_CopyPixels(converted_source, prc, stride, 162 stride*prc->Height, pixeldata); 163 164 if (SUCCEEDED(hr)) 165 { 166 hr = IWICBitmapFrameEncode_WritePixels(iface, prc->Height, stride, 167 stride*prc->Height, pixeldata); 168 } 169 170 free(pixeldata); 171 IWICBitmapSource_Release(converted_source); 172 173 return hr; 174 } 175 176 HRESULT CDECL stream_getsize(IStream *stream, ULONGLONG *size) 177 { 178 STATSTG statstg; 179 HRESULT hr; 180 181 hr = IStream_Stat(stream, &statstg, STATFLAG_NONAME); 182 183 if (SUCCEEDED(hr)) 184 *size = statstg.cbSize.QuadPart; 185 186 return hr; 187 } 188 189 HRESULT CDECL stream_read(IStream *stream, void *buffer, ULONG read, ULONG *bytes_read) 190 { 191 return IStream_Read(stream, buffer, read, bytes_read); 192 } 193 194 HRESULT CDECL stream_seek(IStream *stream, LONGLONG ofs, DWORD origin, ULONGLONG *new_position) 195 { 196 HRESULT hr; 197 LARGE_INTEGER ofs_large; 198 ULARGE_INTEGER pos_large; 199 200 ofs_large.QuadPart = ofs; 201 hr = IStream_Seek(stream, ofs_large, origin, &pos_large); 202 if (new_position) 203 *new_position = pos_large.QuadPart; 204 205 return hr; 206 } 207 208 HRESULT CDECL stream_write(IStream *stream, const void *buffer, ULONG write, ULONG *bytes_written) 209 { 210 return IStream_Write(stream, buffer, write, bytes_written); 211 } 212