1 /* 2 * Copyright 2009 Vincent Povirk for CodeWeavers 3 * 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. 8 * 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. 13 * 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 17 */ 18 19 20 #define COBJMACROS 21 #include "config.h" 22 23 #include <stdarg.h> 24 25 #include "windef.h" 26 #include "winbase.h" 27 #include "objbase.h" 28 29 #include "wincodecs_private.h" 30 31 #include "wine/debug.h" 32 33 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); 34 35 extern BOOL WINAPI WIC_DllMain(HINSTANCE, DWORD, LPVOID) DECLSPEC_HIDDEN; 36 37 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 38 { 39 40 switch (fdwReason) 41 { 42 case DLL_PROCESS_ATTACH: 43 DisableThreadLibraryCalls(hinstDLL); 44 break; 45 case DLL_PROCESS_DETACH: 46 ReleaseComponentInfos(); 47 break; 48 } 49 50 return WIC_DllMain(hinstDLL, fdwReason, lpvReserved); 51 } 52 53 HRESULT WINAPI DllCanUnloadNow(void) 54 { 55 return S_FALSE; 56 } 57 58 HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer, 59 UINT srcwidth, UINT srcheight, INT srcstride, 60 const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer) 61 { 62 UINT bytesperrow; 63 UINT row_offset; /* number of bits into the source rows where the data starts */ 64 WICRect rect; 65 66 if (!rc) 67 { 68 rect.X = 0; 69 rect.Y = 0; 70 rect.Width = srcwidth; 71 rect.Height = srcheight; 72 rc = ▭ 73 } 74 else 75 { 76 if (rc->X < 0 || rc->Y < 0 || rc->X+rc->Width > srcwidth || rc->Y+rc->Height > srcheight) 77 return E_INVALIDARG; 78 } 79 80 bytesperrow = ((bpp * rc->Width)+7)/8; 81 82 if (dststride < bytesperrow) 83 return E_INVALIDARG; 84 85 if ((dststride * (rc->Height-1)) + ((rc->Width * bpp) + 7)/8 > dstbuffersize) 86 return E_INVALIDARG; 87 88 /* if the whole bitmap is copied and the buffer format matches then it's a matter of a single memcpy */ 89 if (rc->X == 0 && rc->Y == 0 && rc->Width == srcwidth && rc->Height == srcheight && 90 srcstride == dststride && srcstride == bytesperrow) 91 { 92 memcpy(dstbuffer, srcbuffer, srcstride * srcheight); 93 return S_OK; 94 } 95 96 row_offset = rc->X * bpp; 97 98 if (row_offset % 8 == 0) 99 { 100 /* everything lines up on a byte boundary */ 101 INT row; 102 const BYTE *src; 103 BYTE *dst; 104 105 src = srcbuffer + (row_offset / 8) + srcstride * rc->Y; 106 dst = dstbuffer; 107 for (row=0; row < rc->Height; row++) 108 { 109 memcpy(dst, src, bytesperrow); 110 src += srcstride; 111 dst += dststride; 112 } 113 return S_OK; 114 } 115 else 116 { 117 /* we have to do a weird bitwise copy. eww. */ 118 FIXME("cannot reliably copy bitmap data if bpp < 8\n"); 119 return E_FAIL; 120 } 121 } 122 123 HRESULT configure_write_source(IWICBitmapFrameEncode *iface, 124 IWICBitmapSource *source, const WICRect *prc, 125 const WICPixelFormatGUID *format, 126 INT width, INT height, double xres, double yres) 127 { 128 HRESULT hr = S_OK; 129 130 if (width == 0 || height == 0) 131 return WINCODEC_ERR_WRONGSTATE; 132 133 if (!format) 134 { 135 WICPixelFormatGUID src_format; 136 137 hr = IWICBitmapSource_GetPixelFormat(source, &src_format); 138 if (FAILED(hr)) return hr; 139 140 hr = IWICBitmapFrameEncode_SetPixelFormat(iface, &src_format); 141 if (FAILED(hr)) return hr; 142 } 143 144 if (xres == 0.0 || yres == 0.0) 145 { 146 hr = IWICBitmapSource_GetResolution(source, &xres, &yres); 147 if (FAILED(hr)) return hr; 148 hr = IWICBitmapFrameEncode_SetResolution(iface, xres, yres); 149 if (FAILED(hr)) return hr; 150 } 151 152 return hr; 153 } 154 155 HRESULT write_source(IWICBitmapFrameEncode *iface, 156 IWICBitmapSource *source, const WICRect *prc, 157 const WICPixelFormatGUID *format, UINT bpp, 158 INT width, INT height) 159 { 160 IWICBitmapSource *converted_source; 161 HRESULT hr=S_OK; 162 WICRect rc; 163 UINT stride; 164 BYTE* pixeldata; 165 166 if (!prc) 167 { 168 UINT src_width, src_height; 169 hr = IWICBitmapSource_GetSize(source, &src_width, &src_height); 170 if (FAILED(hr)) return hr; 171 rc.X = 0; 172 rc.Y = 0; 173 rc.Width = src_width; 174 rc.Height = src_height; 175 prc = &rc; 176 } 177 178 if (prc->Width != width || prc->Height <= 0) 179 return E_INVALIDARG; 180 181 hr = WICConvertBitmapSource(format, source, &converted_source); 182 if (FAILED(hr)) 183 { 184 ERR("Failed to convert source, target format %s, %#x\n", debugstr_guid(format), hr); 185 return hr; 186 } 187 188 stride = (bpp * width + 7)/8; 189 190 pixeldata = HeapAlloc(GetProcessHeap(), 0, stride * prc->Height); 191 if (!pixeldata) 192 { 193 IWICBitmapSource_Release(converted_source); 194 return E_OUTOFMEMORY; 195 } 196 197 hr = IWICBitmapSource_CopyPixels(converted_source, prc, stride, 198 stride*prc->Height, pixeldata); 199 200 if (SUCCEEDED(hr)) 201 { 202 hr = IWICBitmapFrameEncode_WritePixels(iface, prc->Height, stride, 203 stride*prc->Height, pixeldata); 204 } 205 206 HeapFree(GetProcessHeap(), 0, pixeldata); 207 IWICBitmapSource_Release(converted_source); 208 209 return hr; 210 } 211 212 void reverse_bgr8(UINT bytesperpixel, LPBYTE bits, UINT width, UINT height, INT stride) 213 { 214 UINT x, y; 215 BYTE *pixel, temp; 216 217 for (y=0; y<height; y++) 218 { 219 pixel = bits + stride * y; 220 221 for (x=0; x<width; x++) 222 { 223 temp = pixel[2]; 224 pixel[2] = pixel[0]; 225 pixel[0] = temp; 226 pixel += bytesperpixel; 227 } 228 } 229 } 230 231 HRESULT get_pixelformat_bpp(const GUID *pixelformat, UINT *bpp) 232 { 233 HRESULT hr; 234 IWICComponentInfo *info; 235 IWICPixelFormatInfo *formatinfo; 236 237 hr = CreateComponentInfo(pixelformat, &info); 238 if (SUCCEEDED(hr)) 239 { 240 hr = IWICComponentInfo_QueryInterface(info, &IID_IWICPixelFormatInfo, (void**)&formatinfo); 241 242 if (SUCCEEDED(hr)) 243 { 244 hr = IWICPixelFormatInfo_GetBitsPerPixel(formatinfo, bpp); 245 246 IWICPixelFormatInfo_Release(formatinfo); 247 } 248 249 IWICComponentInfo_Release(info); 250 } 251 252 return hr; 253 } 254