xref: /reactos/dll/win32/windowscodecs/main.c (revision f4d29a74)
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 = &rect;
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