1 /* 2 * Copyright 2010 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 #include <stdarg.h> 20 21 #define COBJMACROS 22 23 #include "windef.h" 24 #include "winbase.h" 25 #include "objbase.h" 26 27 #include "wincodecs_private.h" 28 29 #include "wine/debug.h" 30 31 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); 32 33 typedef struct FlipRotator { 34 IWICBitmapFlipRotator IWICBitmapFlipRotator_iface; 35 LONG ref; 36 IWICBitmapSource *source; 37 int flip_x; 38 int flip_y; 39 int swap_xy; 40 CRITICAL_SECTION lock; /* must be held when initialized */ 41 } FlipRotator; 42 43 static inline FlipRotator *impl_from_IWICBitmapFlipRotator(IWICBitmapFlipRotator *iface) 44 { 45 return CONTAINING_RECORD(iface, FlipRotator, IWICBitmapFlipRotator_iface); 46 } 47 48 static HRESULT WINAPI FlipRotator_QueryInterface(IWICBitmapFlipRotator *iface, REFIID iid, 49 void **ppv) 50 { 51 FlipRotator *This = impl_from_IWICBitmapFlipRotator(iface); 52 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 53 54 if (!ppv) return E_INVALIDARG; 55 56 if (IsEqualIID(&IID_IUnknown, iid) || 57 IsEqualIID(&IID_IWICBitmapSource, iid) || 58 IsEqualIID(&IID_IWICBitmapFlipRotator, iid)) 59 { 60 *ppv = &This->IWICBitmapFlipRotator_iface; 61 } 62 else 63 { 64 *ppv = NULL; 65 return E_NOINTERFACE; 66 } 67 68 IUnknown_AddRef((IUnknown*)*ppv); 69 return S_OK; 70 } 71 72 static ULONG WINAPI FlipRotator_AddRef(IWICBitmapFlipRotator *iface) 73 { 74 FlipRotator *This = impl_from_IWICBitmapFlipRotator(iface); 75 ULONG ref = InterlockedIncrement(&This->ref); 76 77 TRACE("(%p) refcount=%lu\n", iface, ref); 78 79 return ref; 80 } 81 82 static ULONG WINAPI FlipRotator_Release(IWICBitmapFlipRotator *iface) 83 { 84 FlipRotator *This = impl_from_IWICBitmapFlipRotator(iface); 85 ULONG ref = InterlockedDecrement(&This->ref); 86 87 TRACE("(%p) refcount=%lu\n", iface, ref); 88 89 if (ref == 0) 90 { 91 This->lock.DebugInfo->Spare[0] = 0; 92 DeleteCriticalSection(&This->lock); 93 if (This->source) IWICBitmapSource_Release(This->source); 94 free(This); 95 } 96 97 return ref; 98 } 99 100 static HRESULT WINAPI FlipRotator_GetSize(IWICBitmapFlipRotator *iface, 101 UINT *puiWidth, UINT *puiHeight) 102 { 103 FlipRotator *This = impl_from_IWICBitmapFlipRotator(iface); 104 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight); 105 106 if (!This->source) 107 return WINCODEC_ERR_WRONGSTATE; 108 else if (This->swap_xy) 109 return IWICBitmapSource_GetSize(This->source, puiHeight, puiWidth); 110 else 111 return IWICBitmapSource_GetSize(This->source, puiWidth, puiHeight); 112 } 113 114 static HRESULT WINAPI FlipRotator_GetPixelFormat(IWICBitmapFlipRotator *iface, 115 WICPixelFormatGUID *pPixelFormat) 116 { 117 FlipRotator *This = impl_from_IWICBitmapFlipRotator(iface); 118 TRACE("(%p,%p)\n", iface, pPixelFormat); 119 120 if (!This->source) 121 return WINCODEC_ERR_WRONGSTATE; 122 else 123 return IWICBitmapSource_GetPixelFormat(This->source, pPixelFormat); 124 } 125 126 static HRESULT WINAPI FlipRotator_GetResolution(IWICBitmapFlipRotator *iface, 127 double *pDpiX, double *pDpiY) 128 { 129 FlipRotator *This = impl_from_IWICBitmapFlipRotator(iface); 130 TRACE("(%p,%p,%p)\n", iface, pDpiX, pDpiY); 131 132 if (!This->source) 133 return WINCODEC_ERR_WRONGSTATE; 134 else if (This->swap_xy) 135 return IWICBitmapSource_GetResolution(This->source, pDpiY, pDpiX); 136 else 137 return IWICBitmapSource_GetResolution(This->source, pDpiX, pDpiY); 138 } 139 140 static HRESULT WINAPI FlipRotator_CopyPalette(IWICBitmapFlipRotator *iface, 141 IWICPalette *pIPalette) 142 { 143 FlipRotator *This = impl_from_IWICBitmapFlipRotator(iface); 144 TRACE("(%p,%p)\n", iface, pIPalette); 145 146 if (!This->source) 147 return WINCODEC_ERR_WRONGSTATE; 148 else 149 return IWICBitmapSource_CopyPalette(This->source, pIPalette); 150 } 151 152 static HRESULT WINAPI FlipRotator_CopyPixels(IWICBitmapFlipRotator *iface, 153 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) 154 { 155 FlipRotator *This = impl_from_IWICBitmapFlipRotator(iface); 156 HRESULT hr; 157 UINT y; 158 UINT srcy, srcwidth, srcheight; 159 WICRect rc; 160 WICRect rect; 161 162 TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer); 163 164 if (!This->source) return WINCODEC_ERR_WRONGSTATE; 165 166 if (This->swap_xy || This->flip_x) 167 { 168 /* This requires knowledge of the pixel format. */ 169 FIXME("flipping x and rotating are not implemented\n"); 170 return E_NOTIMPL; 171 } 172 173 hr = IWICBitmapSource_GetSize(This->source, &srcwidth, &srcheight); 174 if (FAILED(hr)) return hr; 175 176 if (!prc) 177 { 178 UINT width, height; 179 hr = IWICBitmapFlipRotator_GetSize(iface, &width, &height); 180 if (FAILED(hr)) return hr; 181 rect.X = 0; 182 rect.Y = 0; 183 rect.Width = width; 184 rect.Height = height; 185 prc = ▭ 186 } 187 188 for (y=prc->Y; y - prc->Y < prc->Height; y++) 189 { 190 if (This->flip_y) 191 srcy = srcheight - 1 - y; 192 else 193 srcy = y; 194 195 rc.X = prc->X; 196 rc.Y = srcy; 197 rc.Width = prc->Width; 198 rc.Height = 1; 199 200 hr = IWICBitmapSource_CopyPixels(This->source, &rc, cbStride, cbStride, 201 pbBuffer); 202 203 if (FAILED(hr)) break; 204 205 pbBuffer += cbStride; 206 } 207 208 return hr; 209 } 210 211 static HRESULT WINAPI FlipRotator_Initialize(IWICBitmapFlipRotator *iface, 212 IWICBitmapSource *pISource, WICBitmapTransformOptions options) 213 { 214 FlipRotator *This = impl_from_IWICBitmapFlipRotator(iface); 215 HRESULT hr=S_OK; 216 217 TRACE("(%p,%p,%u)\n", iface, pISource, options); 218 219 EnterCriticalSection(&This->lock); 220 221 if (This->source) 222 { 223 hr = WINCODEC_ERR_WRONGSTATE; 224 goto end; 225 } 226 227 if (options&WICBitmapTransformRotate90) 228 { 229 This->swap_xy = 1; 230 This->flip_x = !This->flip_x; 231 } 232 233 if (options&WICBitmapTransformRotate180) 234 { 235 This->flip_x = !This->flip_x; 236 This->flip_y = !This->flip_y; 237 } 238 239 if (options&WICBitmapTransformFlipHorizontal) 240 This->flip_x = !This->flip_x; 241 242 if (options&WICBitmapTransformFlipVertical) 243 This->flip_y = !This->flip_y; 244 245 IWICBitmapSource_AddRef(pISource); 246 This->source = pISource; 247 248 end: 249 LeaveCriticalSection(&This->lock); 250 251 return hr; 252 } 253 254 static const IWICBitmapFlipRotatorVtbl FlipRotator_Vtbl = { 255 FlipRotator_QueryInterface, 256 FlipRotator_AddRef, 257 FlipRotator_Release, 258 FlipRotator_GetSize, 259 FlipRotator_GetPixelFormat, 260 FlipRotator_GetResolution, 261 FlipRotator_CopyPalette, 262 FlipRotator_CopyPixels, 263 FlipRotator_Initialize 264 }; 265 266 HRESULT FlipRotator_Create(IWICBitmapFlipRotator **fliprotator) 267 { 268 FlipRotator *This; 269 270 This = malloc(sizeof(FlipRotator)); 271 if (!This) return E_OUTOFMEMORY; 272 273 This->IWICBitmapFlipRotator_iface.lpVtbl = &FlipRotator_Vtbl; 274 This->ref = 1; 275 This->source = NULL; 276 This->flip_x = 0; 277 This->flip_y = 0; 278 This->swap_xy = 0; 279 #ifdef __REACTOS__ 280 InitializeCriticalSection(&This->lock); 281 #else 282 InitializeCriticalSectionEx(&This->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO); 283 #endif 284 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FlipRotator.lock"); 285 286 *fliprotator = &This->IWICBitmapFlipRotator_iface; 287 288 return S_OK; 289 } 290