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